
    t                         d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlZddlZddlm	Z	 ddl
mZ dd	l
mZ ej                  Z G d
 de      Z G d dej"                        Zy)zIThreading code for estimating total work of long-running gsutil commands.    )absolute_import)print_function)division)unicode_literalsN)thread_message)	constants)parallelism_framework_utilc                       e Zd ZdZddZy)SeekAheadResultzResult class for seek_ahead_iterator results.

  A class is used instead of a namedtuple, making it easier to document
  and use default keyword arguments.
  c                      || _         || _        y)a  Create a SeekAheadResult.

    Args:
      est_num_ops: Number of operations the iterated result represents.
          Operation is loosely defined as a single API call for a single
          object. The total number of API calls may not be known at the time of
          iteration, so this number is approximate.
      data_bytes: Number of data bytes that will be transferred (uploaded,
          downloaded, or rewritten) for this iterated result.
    N)est_num_ops
data_bytes)selfr   r   s      *platform/gsutil/gslib/seek_ahead_thread.py__init__zSeekAheadResult.__init__'   s     #D DO    N)   r   )__name__
__module____qualname____doc__r    r   r   r   r       s    !r   r   c                   (     e Zd ZdZ fdZd Z xZS )SeekAheadThreada  Thread to estimate total work to be performed by all processes and threads.

  Because the ProducerThread can only buffer a certain number of tasks on the
  global task queue, it cannot reliably provide the total count or size of
  iterated results for operations involving many iterated arguments until it
  nears the end of iteration.

  This thread consumes an iterator that should be functionally identical
  to the ProducerThread, but iterates to the end without adding tasks to the
  global task queue in an effort to estimate the amount of total work that the
  call to Apply will perform. It should be used only for large operations, and
  thus it is created by the main ProducerThread only when the number of
  iterated arguments exceeds a threshold.

  This thread may produce an inaccurate estimate if its iterator produces
  different results than the iterator used by the ProducerThread. This can
  happen due to eventual listing consistency or due to the source being
  modified as iteration occurs.

  This thread estimates operations for top-level objects only;
  sub-operations (such as a parallel composite upload) should be reported via
  the iterator as a single object including the total number of bytes affected.
  c                     t         t        |           || _        || _        || _        d| _        | j                          y)ay  Initializes the seek ahead thread.

    Args:
      seek_ahead_iterator: Iterator matching the ProducerThread's args_iterator,
          but returning only object name and/or size in the result.
      cancel_event: threading.Event for signaling the
          seek-ahead iterator to terminate.
      status_queue: Status queue for posting summary of fully iterated results.
    FN)superr   r   status_queueseek_ahead_iteratorcancel_event	terminatestart)r   r   r   r   	__class__s       r   r   zSeekAheadThread.__init__O   s:     
/4)+$D2D$DDNJJLr   c           	         d}d}	 | j                   D ]`  }| j                  r y |t        j                  z  dk(  r| j                  j                         r y ||j                  z  }||j                  z  }b 	 | j                  j                         ry t        | j                  t        j                  ||t        j                                      y # t        $ r
}Y d }~y d }~ww xY w)Nr   )r   r    r   NUM_OBJECTS_PER_LIST_PAGEr   isSetr   r   OSError_PutToQueueWithTimeoutr   r   SeekAheadMessagetime)r   num_objectsnum_data_bytesseek_ahead_resultes        r   runzSeekAheadThread.runb   s    KN#77
>>
 )===!C$$&(444+666  8(  ''^(,			56   s   C 1C  C 	C"C")r   r   r   r   r   r.   __classcell__)r"   s   @r   r   r   6   s    0&6r   r   )r   
__future__r   r   r   r   	threadingr)   gslibr   gslib.utilsr   r	   PutToQueueWithTimeoutr'   objectr   Threadr   r   r   r   <module>r7      sR    P & %  '     ! 23II !f !,J6i&& J6r   