
    1Vh(                         d Z ddlZddlmZ ddlmZ ddlmZ ddlmZ  ej                         Z
 G d d      Z G d	 d
e      Zy)z;Contains the implementation for the DirectoryWatcher class.    N)
io_wrapper)tf)io_util)
tb_loggingc                   J    e Zd ZdZd fdZd Zd ZdZd Zd Z	d	 Z
d
 Zd Zy)DirectoryWatchera  A DirectoryWatcher wraps a loader to load from a sequence of paths.

    A loader reads a path and produces some kind of values as an iterator. A
    DirectoryWatcher takes a directory, a factory for loaders, and optionally a
    path filter and watches all the paths inside that directory.

    This class is only valid under the assumption that only one path will be
    written to by the data source at a time and that once the source stops writing
    to a path, it will start writing to a new path that's lexicographically
    greater and never come back. It uses some heuristics to check whether this is
    true based on tracking changes to the files' sizes, but the check can have
    false negatives. However, it should have no false positives.
    c                      y)NT )xs    f/home/dcms/DCMS/lib/python3.12/site-packages/tensorboard/backend/event_processing/directory_watcher.py<lambda>zDirectoryWatcher.<lambda>,   s        c                     |t        d      |t        d      || _        d| _        || _        d| _        || _        d| _        i | _        y)a  Constructs a new DirectoryWatcher.

        Args:
          directory: The directory to load files from.
          loader_factory: A factory for creating loaders. The factory should take a
            path and return an object that has a Load method returning an
            iterator that will yield all events that have not been yielded yet.
          path_filter: If specified, only paths matching this filter are loaded.

        Raises:
          ValueError: If path_provider or loader_factory are None.
        NzA directory is requiredzA loader factory is requiredF)
ValueError
_directory_path_loader_factory_loader_path_filter_ooo_writes_detected_finalized_sizes)self	directoryloader_factorypath_filters       r   __init__zDirectoryWatcher.__init__,   s]     677!;<<#
-'$)! "r   c              #     K   	 | j                         D ]  }|  y# t        j                  j                  $ rN t        j                  j
                  j                  | j                        st        d| j                  z        Y yw xY ww)a  Loads new values.

        The watcher will load from one path at a time; as soon as that path stops
        yielding events, it will move on to the next path. We assume that old paths
        are never modified after a newer path has been written. As a result, Load()
        can be called multiple times in a row without losing events that have not
        been yielded yet. In other words, we guarantee that every event will be
        yielded exactly once.

        Yields:
          All values that have not been yielded yet.

        Raises:
          DirectoryDeletedError: If the directory has been permanently deleted
            (as opposed to being temporarily unavailable).
        z)Directory %s has been permanently deletedN)	_LoadInternalr   errorsOpErroriogfileexistsr   DirectoryDeletedError)r   events     r   LoadzDirectoryWatcher.LoadF   s{     "	++- yy   	55;;%%doo6+?oo&  7	s&   B BA(B	BB		Bc              #     K   | j                   s| j                          | j                   sy	 | j                   j                         D ]  }|  | j                         }|s!t        j                  d| j                         y| j                   j                         D ]  }|  t        j                  d| j                  |       | j                  |       w)a6  Internal implementation of Load().

        The only difference between this and Load() is that the latter will throw
        DirectoryDeletedError on I/O errors if it thinks that the directory has been
        permanently deleted.

        Yields:
          All values that have not been yielded yet.
        NzNo path found after %sz)Directory watcher advancing from %s to %s)r   _InitializeLoaderr&   _GetNextPathloggerinfor   _SetPath)r   r%   	next_paths      r   r   zDirectoryWatcher._LoadInternala   s      ||""$ ||**,  ))+I4djjA$ **,  KK;

 MM)$K s   CC   c                     | j                   S )a  Returns whether any out-of-order writes have been detected.

        Out-of-order writes are only checked as part of the Load() iterator. Once an
        out-of-order write is detected, this function will always return true.

        Note that out-of-order write detection is not performed on GCS paths, so
        this function will always return false.

        Returns:
          Whether any out-of-order write has ever been detected by this watcher.
        )r   )r   s    r   OutOfOrderWritesDetectedz)DirectoryWatcher.OutOfOrderWritesDetected   s     (((r   c                 L    | j                         }|r| j                  |       y y N)r)   r,   )r   paths     r   r(   z"DirectoryWatcher._InitializeLoader   s$      "MM$ r   c                    | j                   }|rot        j                  |      sZ	 t        j                  j
                  j                  |      j                  }t        j                  d||       || j                  |<   || _         | j                  |      | _        y# t        j                  j                  $ r!}t        j                  d||       Y d}~Wd}~ww xY w)zSets the current path to watch for new events.

        This also records the size of the old path, if any. If the size can't be
        found, an error is logged.

        Args:
          path: The full path of the file to watch.
        zSetting latest size of %s to %dzUnable to get size of %s: %sN)r   r   IsCloudPathr   r!   r"   statlengthr*   debugr   r   r    errorr   r   )r   r3   old_pathsizees        r   r,   zDirectoryWatcher._SetPath   s     ::G//9Juu{{''188>$O26%%h/ 
++D1	 99$$ J;XqIIJs   AB C9CCc                     t         fdt        j                   j                        D              }|sy j                  |d   S t        j                  |d         si j                  s]t        j                  | j                        }t        d| j                  z
        }||| D ]  } j                  |      sd _         n t         fd|D              }|rt        |      S y)zGets the next path to load from.

        This function also does the checking for out-of-order writes as it iterates
        through the paths.

        Returns:
          The next path to load events from, or None if there are no more paths.
        c              3   D   K   | ]  }j                  |      r|  y wr2   )r   .0r3   r   s     r   	<genexpr>z0DirectoryWatcher._GetNextPath.<locals>.<genexpr>   s'      
  & 
s    Nr   Tc              3   Z   K   | ]"  }j                   |j                   kD  s| $ y wr2   )r   r?   s     r   rA   z0DirectoryWatcher._GetNextPath.<locals>.<genexpr>   s*      
djj&8D4::<MD
s    ++)sortedr   ListDirectoryAbsoluter   r   r   r5   r   bisectbisect_leftmax_OOO_WRITE_CHECK_COUNT_HasOOOWritelistmin)r   pathscurrent_path_indexooo_check_startr3   
next_pathss   `     r   r)   zDirectoryWatcher._GetNextPath   s      
"88I
 

 ::8O ""58,T5N5N!'!3!3E4::!F!%(C(CCO o.@A $$T*04D-
  
"
 

 z?"r   c                 8   t         j                  j                  j                  |      j                  }| j
                  j                  |d      }||k7  rF|"t        j                  d|| j                         yt        j                  d|| j                         yy)z7Returns whether the path has had an out-of-order write.NzHFile %s created after file %s even though it's lexicographically earlierz2File %s updated even though the current file is %sTF)
r   r!   r"   r6   r7   r   getr*   r9   r   )r   r3   r;   old_sizes       r   rI   zDirectoryWatcher._HasOOOWrite   s     uu{{%,,((,,T4880JJ	  HJJ
 r   N)__name__
__module____qualname____doc__r   r&   r   rH   r0   r(   r,   r)   rI   r
   r   r   r   r      s?     ?M #468%v  ) 
2,'Rr   r   c                       e Zd ZdZy)r$   a  Thrown by Load() when the directory is *permanently* gone.

    We distinguish this from temporary errors so that other code can
    decide to drop all of our data only when a directory has been
    intentionally deleted, as opposed to due to transient filesystem
    errors.
    N)rS   rT   rU   rV   r
   r   r   r$   r$     s     	r   r$   )rV   rE   $tensorboard.backend.event_processingr   tensorboard.compatr   tensorboard.utilr   r   
get_loggerr*   r   	Exceptionr$   r
   r   r   <module>r]      sE     B  ; ! $ ' 
			 h hV		I 		r   