
    N                       S r SSKJr  SSKJr  SSKJr  SSKJr  SSKrSSKJr  SSK	r	SSK
r
SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJr  SSKrSS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJ r   SSK!J"r"  SSK#J$r$  SSK%J&r&  SSK%J'r'  SSK(J)r)  SSK(J*r*  SSK(J+r+  SSK(J,r,  SSK(J-r-  SSK.J/r/  SSK0J1r1  SSK2J3r3  SSK2J4r4  SSK2J5r5  SSK2J6r6  SSK2J7r7  SSK8J9r9  SS K8J:r:  SS!K8J;r;  SS"K8J<r<  SS#K8J=r=  SS$K>J?r@  SS%KAJBrB  SS&KAJCrC  SS'KAJDrD  SS(KAJErE  SS)KFJGrG  SS*KFJHrH  SS+KFJIrI  SS,KJJKrK  SS-KJJLrL  SS.KMJNrN  SS/KMJOrO  SSKPrSS0KPJQrQ  SS1KPJRrR  SS2KPJSrS  SS3KPJTrT  SS4KPJUrU  SS5KPJVrV  SS6KPJWrW  SS7KPJXrX  SS8KPJYrY  SS9KZJ[r[  SS:K\J]r]  SS;K^J_r_  SS<K^J`r`  SS=KaJbrb  SS>KaJcrc  SS?KaJdrd  SS@KeJfrf  SSAKgJhri   SSBKjJkrl  SCrnSDroSE rpSF rqSG rrSH rsS}SI jrtSJ ru/ rvSK rwSL rxSM rySNrzSOr{SP r|SCr}SQSR/SQSS/SQST/SUSS/SUST/SVSR/SVSS/SVST// SWQ/ SXQSYSS/SZSS/SZST/S[SS/S[ST/S\.r~S] rS^ rS_ r\" S`/ SaQ5      r " Sb Sc\$\]5      r " Sd Se\5      r " Sf Sg\" SgSh5      5      rSi r " Sj Sk\GR                  5      r " Sl Sm\5      r " Sn So\GR                  5      r " Sp Sq\5      rSr r " Ss St\5      rSu rSv rSw rSx rSy rSz rS{ rS| rg! \m a    Srl GNf = f)~ax  Base class for gsutil commands.

In addition to base class code, this file contains helpers that depend on base
class state (such as GetAndPrintAcl) In general, functions that depend on
class state and that are used by multiple commands belong in this file.
Functions that don't depend on class state belong in util.py, and non-shared
helpers belong in individual subclasses.
    )absolute_import)print_function)division)unicode_literalsN)
namedtuple)
StorageUri)AccessDeniedException)ArgumentException)ServiceException)CloudApiDelegator)ApiSelector)GsutilApiMapFactory)CommandException)HelpProvider)CaptureThreadStatException)LogPerformanceSummaryParams)CopyObjectInfo)CopyObjectsIterator)NameExpansionIterator)NameExpansionResult)SeekAheadNameExpansionIterator)PluralityCheckableIterator)SeekAheadThread)ChildProcessSignalHandler)GetCaughtSignals)KillProcess)MultithreadedMainSignalHandler)RegisterSignalHandler)HaveFileUrls)HaveProviderUrls)StorageUrlFromString)UrlsAreForSingleProvider)UrlsAreMixOfBucketsAndObjects)storage_v1_messages)FinalMessage)MetadataMessage)PerformanceSummaryMessage)ProducerThreadMessage)MainThreadUIQueue)UIController)UIThread)GetFriendlyConfigFilePaths)!GetMaxConcurrentCompressedUploads)NO_MAX)UTF8)
AtomicDict)$CheckMultiprocessingAvailableAndInit)multiprocessing_context)ProcessAndThreadSafeInt)PutToQueueWithTimeout)SEEK_AHEAD_JOIN_TIMEOUT)ShouldProhibitMultiprocessing)UI_THREAD_JOIN_TIMEOUT)ZERO_TASKS_TO_DO_ARGUMENT)RsyncDiffToApply)GcloudStorageCommandMixin)GetTermLines)
IS_WINDOWS)AclTranslation)GetNonMetadataHeaders)PRIVATE_DEFAULT_OBJ_ACL)CreateWildcardIterator)queue)Random   i  c                 J   [         R                  " U 5      nUR                  (       d{  SUl        UR	                  [         R
                  R                  5        [         R                  " 5       nUR                  [         R                  " S5      5        UR                  U5        U$ )a  Fetches a logger with the given name that resembles 'print' output.

Initial Logger Configuration:

The logger abides by gsutil -d/-D/-DD/-q options. If none of those options
were specified at invocation, the returned logger will display all messages
logged with level INFO or above. Log propagation is disabled.

If a logger with the specified name has already been created and configured,
it is not reconfigured, e.g.:

  foo = CreateOrGetGsutilLogger('foo')  # Creates and configures Logger "foo".
  foo.setLevel(logging.DEBUG)  # Change level from INFO to DEBUG
  foo = CreateOrGetGsutilLogger('foo')  # Does not reset level to INFO.

Args:
  command_name: (str) Command name to create logger for.

Returns:
  A logging.Logger object.
Fz%(message)s)logging	getLoggerhandlers	propagatesetLevelrootlevelStreamHandlersetFormatter	Formatter
addHandler)command_nameloglog_handlers       platform/gsutil/gslib/command.pyCreateOrGetGsutilLoggerrT   t   sr    , 	,'# 
CMLL##$'')KW..}=>NN;	*    c                 :    U R                   R                  U5        g N)logger	exceptionclses     rS   _DefaultExceptionHandlerr]      s    **qrU   c                     U R                   (       d  gUR                  nUR                  5       (       aK  [        R                  R                  UR                  5      (       a  U R                  R                  SU5        gg)NTzSkipping symbolic link %s...F)	exclude_symlinksexpanded_storage_url	IsFileUrlospathislinkobject_namerX   info)command_instanceurlexp_src_urls      rS   _UrlArgCheckerrj      s]    		*	*((+0G0G!H!H  !?M	rU   c                      g)NT )unused_argss    rS   DummyArgCheckerrn      s    	rU   c                      U R                  XS9$ )Nthread_state)
SetAclFunc)r[   name_expansion_resultrq   s      rS   SetAclFuncWrapperrt      s    	-	IIrU   c                 Z    U R                   R                  [        U5      5        SU l        g)zDException handler that maintains state about post-completion status.FN)rX   errorstreverything_set_okayrZ   s     rS   SetAclExceptionHandlerry      s     **3q6!#rU   c                  t    [         (       a-  [        [         SS 5      (       a  [         R                  " 5         g g g )Natfork)CryptoRandomgetattrr{   rl   rU   rS   _CryptoRandomAtForkr~      s*    \glHd;;
  <\rU   c                  d    [         R                  " [        5      n [        R	                  U 5        U $ rW   )r2   QueueMAX_QUEUE_SIZEqueuesappend	new_queues    rS   _NewMultiprocessingQueuer      s$    %++N;)--		rU   c                  d    [         R                   " [        5      n [        R                  U 5        U $ rW   )r   r   r   r   r   s    rS   _NewThreadsafeQueuer      s"    kk.))--		rU   i~  i0u  c                  L    [         R                  R                  SS[        5      $ )NGSUtiltask_estimation_threshold)botoconfiggetint!DEFAULT_TASK_ESTIMATION_THRESHOLDrl   rU   rS   _GetTaskEstimationThresholdr      s!    			H&A=
? ?rU   aclchgetsetcorsdefacl)rE   r   off)rE   r   onrE   
versioningweb)chaclgetaclsetaclgetcorssetcorschdefacl	getdefacl	setdefacldisableloggingenablelogging
getlogginggetversioningsetversioning	getwebcfg	setwebcfgc                  P   [         R                  " 5       q/ q/ q[        R                  5       q[        S5      q[        [        S9q
[        [        S9q[        [        S9q[        R                  5       q[        R                  5       q[        [        S9q[        S5      q[        S5      q[        [        S9q[        [        S9q[        [        S9q[        R-                  5       q[        S5      q[        R3                  [4        5      q[        R9                  [;        5       5      qg)a  Initializes module-level variables that will be inherited by subprocesses.

On Windows, a multiprocessing.Manager object should only
be created within an "if __name__ == '__main__':" block. This function
must be called, otherwise every command that calls Command.Apply will fail.

While multiprocessing variables are initialized at the beginning of
gsutil execution, new processes and threads are created only by calls
to Command.Apply. When multiple processes and threads are used,
the flow of startup/teardown looks like this:

1. __main__: initializes multiprocessing variables, including any necessary
   Manager processes (here and in gslib.utils.parallelism_framework_util).
2. __main__: Registers signal handlers for terminating signals responsible
   for cleaning up multiprocessing variables and manager processes upon exit.
3. Command.Apply registers signal handlers for the main process to kill
   itself after the cleanup handlers registered by __main__ have executed.
4. If worker processes have not been created for the current level of
   recursive calls, Command.Apply creates those processes.

---- Parallel operations start here, so steps are no longer numbered. ----
- Command.Apply in the main thread starts the ProducerThread.
  - The Producer thread adds task arguments to the global task queue.
    - It optionally starts the SeekAheadThread which estimates total
      work for the Apply call.

- Command.Apply in the main thread starts the UIThread, which will consume
  messages from the global status queue, process them, and display them to
  the user.

- Each worker process creates a thread pool to perform work.
  - The worker process registers signal handlers to kill itself in
    response to a terminating signal.
  - The main thread of the worker process moves items from the global
    task queue to the process-local task queue.
  - Worker threads retrieve items from the process-local task queue,
    perform the work, and post messages to the global status queue.
  - Worker threads may themselves call Command.Apply.
    - This creates a new pool of worker subprocesses with the same size
      as the main pool. This pool is shared amongst all Command.Apply calls
      at the given recursion depth.
    - This reuses the global UIThread, global status queue, and global task
      queue.
    - This starts a new ProducerThread.
    - A SeekAheadThread is not started at this level; only one such thread
      exists at the top level, and it provides estimates for top-level work
      only.

- The ProducerThread runs out of tasks, or the user signals cancellation.
  - The ProducerThread cancels the SeekAheadThread (if it is running) via
    an event.
  - The ProducerThread enqueues special terminating messages on the
    global task queue and global status queue, signaling the UI Thread to
    shut down and the main thread to continue operation.
  - In the termination case, existing processes exit in response to
    terminating signals from the main process.

---- Parallel operations end here. ----
5. Further top-level calls to Command.Apply can be made, which will repeat
   all of the steps made in #4, except that worker processes will be
   reused.
T)managerN)r2   Managerr   consumer_poolstask_queuesLockcaller_id_lockr3   caller_id_counterr0   total_taskscall_completed_mapglobal_return_values_map	Conditionneed_pool_or_done_condworker_checking_level_lockcaller_id_finished_countnew_pool_neededcurrent_max_recursive_levelshared_vars_mapshared_vars_list_mapthread_statsdict	class_mapfailure_countr   r   glob_status_queueBoundedSemaphorer-   !concurrent_compressed_upload_lockrl   rU   rS   "InitializeMultiprocessingVariablesr   
  s   R $++-' . + <<>.-d3 7++ "'2 (8 #,,.  '||~ (8
 ,D1/ 7 = w//#G4 G,, lln) *$/-  mmN3 '.&>&>')'+#rU   c                      [        5         [        R                  5         [        R                  R
                  R                  R                  5         g)z7Should be called by signal handlers prior to shut down.N)ShutDownGsutilr   shutdowngslibutilsparallelism_framework_utiltop_level_managerrl   rU   rS    TeardownMultiprocessingProcessesr     s4     
 
++((::CCErU   c                     [        S5      q[        5       q[        R
                  " 5       q[        5       q[        5       q[        S5      q	[        S5      q
[        R                  " [        5      q[        5       q[        R                  " 5       q[        5       q[        5       q[        5       q/ q[        5       q[        R
                  " 5       q[        R.                  " [1        5       5      qg)a:  Initializes module-level variables used when running multi-threaded.

When multiprocessing is not available (or on Windows where only 1 process
is used), thread-safe analogs to the multiprocessing global variables
must be initialized. This function is the thread-safe analog to
InitializeMultiprocessingVariables.
FN)r3   r   r0   r   	threadingr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r-   r   rl   rU   rS   InitializeThreadingVariablesr     s     .e4'\>>#.!|l) 7 >)%0-kk.1'\$..0#L/,++(~~/&/&@&@')'+#rU   CommandSpecrP   usage_synopsiscommand_name_aliasesmin_argsmax_argssupported_sub_argsfile_url_okprovider_url_okurls_start_arggs_api_supportgs_default_apisupported_private_argsargparse_argumentsc                     ^  \ rS rSrSrSrSrSrSr\	SSS\
SSSSSSSS4S	 j5       rS
 r\" \5      rS rS r    S-U 4S jjrS rS r   S.S jrS rS/S jrS rS r S0S jrS0S jrS rS rS rS rS rS r S r!S0S jr"S0S jr#S  r$ S1S! jr%S" r&S# r' " S$ S%\(5      r)S\*SSSSSS4S& jr+S' r,S( r-  S2S) jr.S* r/S+ r0S,r1U =r2$ )3Commandi  z#Base class for all gsutil commands.N)	r   r   iamkmslabelrE   notification	retentionr   r    Fc                     [        U UU=(       d    / UUUUUUU	=(       d    [        R                  /U
=(       d    [        R                  UU=(       d    / S9$ )z2Creates an instance of CommandSpec, with defaults.r   )r   r   XMLr   s                rS   CreateCommandSpecCommand.CreateCommandSpec  sX     L&4,@,FB ( (*<#.'6&4&4&I8I&4&G.D*<*BD DrU   c                 .    U R                   R                  $ rW   )command_specrP   selfs    rS   _GetDefaultCommandNameCommand._GetDefaultCommandName  s    )))rU   c                 .    U R                   R                  $ )zzCalculate the index in args of the first URL arg.

Returns:
  Index of the first URL arg (according to the command spec).
)r   r   r   s    rS   _CalculateUrlsStartArgCommand._CalculateUrlsStartArg$  s     +++rU   c           
         [         R                  U R                  S5      nU(       a`  USS U-   nU R                  R	                  SR                  [        R                  " SU R                  U R                  S.-  5      5      5        U$ )zBMap deprecated aliases to the corresponding new command, and warn.N   
zYou are using a deprecated alias, "%(used_alias)s", for the "%(command_name)s" command. This will stop working on 9/9/2014. Please use "%(command_name)s" with the appropriate sub-command in the future. See "gsutil help %(command_name)s" for details.)
used_aliasrP   )	OLD_ALIAS_MAPr   command_alias_usedrX   warnjointextwrapwraprP   )r   argsnew_command_argss      rS   _TranslateDeprecatedAliases#Command._TranslateDeprecatedAliases,  s    $(()@)@$G ab!D(d
kktyy
--M
 !% 7 7"&"3"3		 	 KrU   c                   > [         TU ]  5         Xl        X l        X0l        X@l        XPl        Xl        X`l        Xl	        Xpl
        Xl        SU l        SU l        SU l        Xl        SU l        [#        U R$                  5      U l        U	(       a$  U	 H  nU R&                  R)                  U5        M      U R                  b  [+        U R                  5      U l        OSU l        U R.                  c  [1        SU R$                  -  5      eU R&                  R3                  [4        R6                  5      (       + U l        [;        U R8                  [<        R>                  RA                  SSS5      S9q!U RE                  U5      U l#        U RI                  5         U R.                  RK                  U RM                  5       S9U l        [O        U RF                  5      U R.                  RP                  :  d-  [O        U RF                  5      U R.                  RR                  :  a  U RU                  5         U R$                  U RV                  ;  a  U RY                  5         U R.                  RZ                  [\        R^                  /S.nU R.                  R`                  [\        R^                  S.n[b        Rd                  " U R                  X5      U l3        SU l4        [k        U R                  U Rf                  U R&                  [m        [n        Rp                  [B        5      U R
                  U R,                  U R                  U R                  U R                  S	9	U l9        S
U l:        [v        (       a  U =Rt                  S-  sl:        [x        Rz                  U l>        U =Rt                  U R|                  -  sl:        U R~                  (       a+  U R~                   H  u  nnUS:X  d  US:X  d  M  SU l          O   [        5       R                  U lB        g)a  Instantiates a Command.

Args:
  command_runner: CommandRunner (for commands built atop other commands).
  args: Command-line args (arg0 = actual arg, not command name ala bash).
  headers: Dictionary containing optional HTTP headers to pass to boto.
  debug: Debug level to pass in to boto connection (range 0..3).
  trace_token: Trace token to pass to the API implementation.
  parallel_operations: Should command operations be executed in parallel?
  bucket_storage_uri_class: Class to instantiate for cloud StorageUris.
                            Settable for testing/mocking.
  gsutil_api_class_map_factory: Creates map of cloud storage interfaces.
                                Settable for testing/mocking.
  logging_filters: Optional list of logging. Filters to apply to this
                   command's logger.
  command_alias_used: The alias that was actually used when running this
                      command (as opposed to the "official" command name,
                      which will always correspond to the file name).
  perf_trace_token: Performance measurement trace token to use when making
      API calls.
  user_project: Project to be billed for this request.

Implementation note: subclasses shouldn't need to define an __init__
method, and instead depend on the shared initialization that happens
here. If you do define an __init__ method in a subclass you'll need to
explicitly call super().__init__(). But you're encouraged not to do this,
because it will make changing the __init__ interface more painful.
FNzA"%s" command implementation is missing a command_spec definition.r   dump_status_messages_file)
quiet_moder  )r   )gss3debughttp_headerstrace_tokenperf_trace_tokenuser_projectr   zpython z-rz-RT)Csuper__init__command_runnerunparsed_argsheadersr  r
  r  parallel_operationsr  bucket_storage_uri_classgsutil_api_class_map_factoryr_   recursion_requestedall_versionsr   seek_ahead_gsutil_apirT   rP   rX   	addFilterr>   non_metadata_headersr   r   isEnabledForrE   INFOr  r*   r   r   r   ui_controllerr   r   ParseSubOpts_replacer   lenr   r   $RaiseWrongNumberOfArgumentsException&_commands_with_subcommands_and_suboptsCheckArgumentsr   r   r   r   r   	GetApiMapgsutil_api_map
project_idr   r)   sysstderr
gsutil_api
gsutil_cmdr<   r   GSUTIL_PATHgsutil_pathsub_optsr1   is_availablemultiprocessing_is_available)r   r  r   r  r  r
  r  r  r  logging_filtersr   r  r  
log_filtersupport_mapdefault_mapounused_a	__class__s                     rS   r  Command.__init__?  sF   T 
G(LJ",2$$<!(D%!D$DD0!%D *$*;*;<DK'*j) ( ||"7"Ed"&d  8:>:K:KL M M ++227<<@@DO DOO;?;;??%-/J%)<+,M 006DI ))22224 3 6D 	DII**333DII**333
//1 K KK
 ..K
 ..ooK .77));ED DO'(E(E(,(;(;(,(9,/JJ)G.2jj595N5N484D4D9=9N9N595F5F	HDO DOz
oo"o((DOOt'''O }}+!X9T	%)$
"
 ' 	-.;; 	%rU   c                    [        U R                  5      U R                  R                  :  aE  U R                  R                  S:  a  SOSnSU R                  U R                  R                  U4-  nO%SU R                  U R                  R
                  4-  nUSU R                  R                  < SU R                  < 3-  n[        U5      e)zCRaises exception for wrong number of arguments supplied to command.r   sr   z/The %s command requires at least %d argument%s.z,The %s command accepts at most %d arguments.z Usage:
(
For additional help run:
  gsutil help )r  r   r   r   rP   r   r   r   )r   tail_strmessages      rS   r   ,Command.RaiseWrongNumberOfArgumentsException  s    
499~))222))22Q6BhB##T%6%6%?%?JKg @##T%6%6%?%?@Ag(($*;*;= =G
7
##rU   c                 h    SU R                   R                  < SU R                  < 3n[        U5      e)z?Raises exception for specifying an invalid argument to command.z&Incorrect option(s) specified. Usage:
r9  )r   r   rP   r   )r   r;  s     rS   RaiseInvalidArgumentException%Command.RaiseInvalidArgumentException  s0     !!00$2C2CEG 7
##rU   c                    Uc  U R                   nOUn [        R                  " X@R                  R                  U R                  R                  =(       d    / 5      u  pVU(       a(  WWsU l        U l         U(       a  U R                  5         ggU(       a  [        S5      eWW4$ ! [        R
                   a    U R                  5          Nkf = f)a9  Parses sub-opt args.

Args:
  check_args: True to have CheckArguments() called after parsing.
  args: List of args. If None, self.args will be used.
  should_update_sub_opts_and_args: True if self.sub_opts and self.args
    should be updated with the values returned after parsing. Else return a
    tuple of sub_opts, args returned by getopt.getopt. This is done
    to allow this method to be called from get_gcloud_storage_args in which
    case we do not want to update self.sub_opts and self.args.

Raises:
  RaiseInvalidArgumentException: Invalid args specified.
NzIRequested to check arguments but sub_opts and args have not been updated.)
r   getoptr   r   r   GetoptErrorr>  r,  r"  	TypeError)r   
check_argsr   should_update_sub_opts_and_argsr  parsed_sub_optsparsed_argss          rS   r  Command.ParseSubOpts  s    $ |iimm+%+]]
**==



2
2
8b&:"o
 '!0+dmTY	 
 
  H I 	Ik))  +
((*+s   A
B# #$C
	C
c                    U R                   R                  (       dI  [        U R                  U R                   R                  S 5      (       a  [        SU R                  -  5      eU R                   R                  (       dJ  [        U R                  U R                   R                  S 5      (       a  [        SU R                  -  5      egg)a  Checks that command line arguments match the command_spec.

Any commands in self._commands_with_subcommands_and_subopts are responsible
for calling this method after handling initial parsing of their arguments.
This prevents commands with sub-commands as well as options from breaking
the parsing of getopt.

TODO: Provide a function to parse commands and sub-commands more
intelligently once we stop allowing the deprecated command versions.

Raises:
  CommandException if the arguments don't match.
NzN"%s" command does not support "file://" URLs. Did you mean to use a gs:// URL?z1"%s" command does not support provider-only URLs.)	r   r   r   r   r   r   rP   r   r    r   s    rS   r"  Command.CheckArguments  s     ))TYYt00??@ABB @!../ 0 0 --4#4#4#C#C#DEFF %'+'8'89 : : 	G .rU   c                 X    [        UU R                  UU R                  U R                  S9$ )a  Helper to instantiate gslib.WildcardIterator.

Args are same as gslib.WildcardIterator interface, but this method fills in
most of the values from instance state.

Args:
  url_string: URL string naming wildcard objects to iterate.
  all_versions: If true, the iterator yields all versions of objects
                matching the wildcard.  If false, yields just the live
                object version.

Returns:
  WildcardIterator for use by caller.
)r  r%  rX   )r@   r(  r%  rX   )r   
url_stringr  s      rS   WildcardIteratorCommand.WildcardIterator$  s+     "*"&///;-1__)-	6 6rU   c                 $   U R                   (       dt  [        U R                  U R                  [        R
                  " S5      [        U R                  U R                  U R                  U R                  U R                  S9	U l         U R                   $ )a?  Helper to instantiate a Cloud API instance for a seek-ahead iterator.

This must be separate from the core command.gsutil_api instance for
thread-safety, since other iterators typically use that instance and the
SeekAheadIterator operates in parallel.

Returns:
  Cloud API instance for use by the seek-ahead iterator.
dummyr  )r  r   r  r$  rE   rF   r   r  r  r
  r  r  r   s    rS   GetSeekAheadGsutilApiCommand.GetSeekAheadGsutilApi9  sv      %%#4

'
'





G
$


00&&00((	$*d  %%%rU   c                 2    [        SU R                  -  5      e)zAbstract function in base class. Subclasses must implement this.

The return value of this function will be used as the exit status of the
process, so subclass commands should return an integer exit code (0 for
success, a value in [1,255] for failure).
z5Command %s is missing its RunCommand() implementation)r   rP   r   s    rS   
RunCommandCommand.RunCommandV  s'      ,.2.?.?@ A ArU   c                 V   / n[        [        [        U5      5      n[        U5      (       a  U R                  (       d  [        S5      eU H  nUR                  5       (       a  UR                  5       (       a  U R                  (       a$  SUl        UR                  UR                  5        Mb  U R                  UR                  5      R                  S/S9 H#  n[        USSSUR                  SS9n	U" X	5        M%     M  UR                  UR                  5        M     [        U5      S:  a  [!        U R"                  U R$                  U R&                  U R(                  UU R                  U R*                  U R,                  =(       d    U R.                  US	9	n
[1        U R"                  U R$                  U R3                  5       UU R                  U R*                  S
9nU R5                  UU
UU R,                  (       + US9  U R6                  (       d  U R,                  (       d  [        S5      egg)a  Sets the standard or default object ACL depending on self.command_name.

Args:
  acl_func: ACL function to be passed to Apply.
  acl_excep_handler: ACL exception handler to be passed to Apply.
  url_strs: URL strings on which to set ACL.
  object_fields: If present, list of object metadata fields to retrieve;
      if None, default name expansion iterator fields will be used.

Raises:
  CommandException if an ACL could not be set.
z/Cannot operate on a mix of buckets and objects.*idbucket_fieldsFN)source_storage_urlis_multi_source_request!is_multi_top_level_source_requestnames_containerr`   expanded_resultr   )r  continue_on_errorbucket_listing_fields)r  )fail_on_errorseek_ahead_iterator'ACLs for some objects could not be set.)listmapr!   r#   r  r   
IsCloudUrlIsBucketre   r   rL  rM  IterBucketsr   storage_urlr  r   rP   r  rX   r(  r  r`  r  r   rQ  Applyrx   )r   acl_funcacl_excep_handlerurl_strsobject_fieldsmulti_threaded_url_argsurlsrh   blrname_expansion_for_urlname_expansion_iteratorrc  s               rS   ApplyAclFuncCommand.ApplyAclFuncg  s   " !((34D%d++D4L4LNOO 			cllnn##  #/
!
(
(
8 **nn)kk?@c%8#&(-27 %%(__ $&&" T2@ 	 &&s~~6- 0 "#q( 5



**
++
//
!

"
"(( 22Nd6N6N -	!/ ;



**

$
$
&
!

"
"((* jj("#'#9#99%8	  : ##D,B,BFGG -C#rU   c                    U(       a  U R                   (       a   eUnOU R                  nU R                   (       a  SOSnUR                  nU R                  R	                  SXE5        UR                  UR                  5      [        R                  :X  a"  UR                  S:w  a  U R                  XS5        OU R                  XS5        [        UR                  [        [        R                  " 5       S95        g)zSets the object ACL for the name_expansion_result provided.

Args:
  name_expansion_result: NameExpansionResult describing the target object.
  thread_state: If present, use this gsutil Cloud API instance for the set.
zdefault object ACLACLzSetting %s on %s...r  )message_timeN)def_aclr(  r`   rX   rf   GetApiSelectorschemer   r   _SetAclXmlPassthrough_SetAclGsutilApir4   status_queuer&   time)r   rs   rq   r(  	op_stringrh   s         rS   rr   Command.SetAclFunc  s     j??j(,$%I

4
4CKK*I;!!#**-@

d   1 C,*11)tyy{CErU   c                 v   UR                   n [        R                  Ul         UR                  U R                  UU R
                  U R                  UR                  S9  X2l         g! [         a>  nU R                  (       a'  SU l
        U R                  R                  U5         SnANIe SnAff = f! X2l         f = f)a  Sets the ACL for the URL provided using the XML passthrough functions.

This function assumes that self.def_acl, self.canned,
and self.continue_on_error are initialized, and that self.acl_arg is
either an XML string or a canned ACL string.

Args:
  url: CloudURL to set the ACL on.
  gsutil_api: gsutil Cloud API to use for the ACL set. Must support XML
      passthrough functions.
)canneddef_obj_aclproviderFN)
prefer_apir   r   XmlPassThroughSetAclacl_argr  rz  r|  r   r`  rx   rX   rv   )r   rh   r(  orig_prefer_apir\   s        rS   r}  Command._SetAclXmlPassthrough  s     !++O.)ooj%%dll&)-1[[26,,/2zz	 & ; .  			#( ! .s0   AA% %
B-/3B("B0 'B((B--B0 0B8c           	          UR                  5       (       Ga  U R                  (       a  U R                  (       aF  UR                  UR                  [
        R                  " 5       U R                  UR                  S/S9  g	[        R                  " U R                  [
        R                  5      nU(       d  UR                  [        5        [
        R                  " US9nUR                  UR                  UUR                  S/S9  g	U R                  (       aF  UR                  UR                  [
        R                  " 5       U R                  UR                  S/S9  g	[        R                  " U R                  [
        R                  5      n[
        R                  " US9nUR                  UR                  UUR                  S/S9  g	U R                  (       aZ  UR                  UR                  UR                   [
        R"                  " 5       UR                  UR$                  U R                  S9  g	[        R                  " U R                  [
        R                  5      n[
        R"                  " US9nUR                  UR                  UR                   UUR                  UR$                  S9  g	! [&         a  ne S	nAf[(         a>  nU R*                  (       a'  S
U l        U R.                  R1                  U5         S	nAg	e S	nAff = f)aH  Sets the ACL for the URL provided using the gsutil Cloud API.

This function assumes that self.def_acl, self.canned,
and self.continue_on_error are initialized, and that self.acl_arg is
either a JSON string or a canned ACL string.

Args:
  url: CloudURL to set the ACL on.
  gsutil_api: gsutil Cloud API to use for the ACL set.
rX  )canned_def_aclr  fields)defaultObjectAcl)r  r  )
canned_aclr  r  )r   )r  
generationr  )r  r  NF)rh  rz  r  PatchBucketbucket_nameapitools_messagesBucketr  r|  r=   JsonToMessageObjectAccessControlr   r?   BucketAccessControlPatchObjectMetadatare   Objectr  r
   r   r`  rx   rX   rv   )	r   rh   r(  r  bucket_metadata
bucket_acl
object_aclobject_metadatar\   s	            rS   r~  Command._SetAclGsutilApi  s]   =	<<[[""3??#4#;#;#=26,,,/JJ+/&	 # 2 )66/CCEK   !89/66!,.O""3??#2,/JJ+/& # 2
 [[""3??#4#;#;#=.2ll,/JJ+/&	 # 2 (55/CCEJ/66:FO""3??#2,/JJ+/& # 2
 ;;

(
(),):)A)A)C25**47NN48LL ) B &33ll-AAC*-44D/

(
(),)825**47NN	 ) D
   			#( !sM   A=J3  BJ3 AJ3 A*J3 	A*J3 4A>J3 3
L	=J>>L	3LLL	c                    U R                   S   nU R                   SS n[        U5      (       d  [        SU R                  -  5      e[        R
                  R                  U5      (       a=  [        R                  " US[        5       nUR                  5       nSSS5        SU l        OX[        R                  " US   U R                  SU R                  S9nUR!                  5       nX7;  a  [        SU-  5      eS	U l        S	U l        X0l        U R'                  XU5        U R"                  (       d  U R(                  (       d  [        S
5      egg! , (       d  f       N= f)zSets ACLs on the self.args using the passed-in acl function.

Args:
  acl_func: ACL function to be passed to Apply.
  acl_excep_handler: ACL exception handler to be passed to Apply.
r   r   Nz,"%s" command spanning providers not allowed.rF)r  validater  zInvalid canned ACL "%s".Trd  )r   r"   r   rP   rb   rc   isfilecodecsopenr/   readr  r   storage_urir  r  canned_aclsrx   r  ru  r`  )r   rl  rm  r  url_argsfr  r  s           rS   SetAclCommandHelperCommand.SetAclCommandHelper<  s2    iilGyy}H $H--K!../ 0 0
 
ww~~g;;wT*a&&( +dk $$
1+

#'#@#@	Bk  ++-k		#9GCDDdk  $DLh8<##D,B,BFGG -C#- +*s   E
Ec                     SSK Jn  U(       a?  U R                  R                  SR	                  [
        R                  " S5      5      5        gg)zWarns service account users who have received an AccessDenied error.

When one of the metadata-related commands fails due to AccessDenied, user
must ensure that they are listed as an Owner in the API console.
r   )IS_SERVICE_ACCOUNTr   a  It appears that your service account has been denied access while attempting to perform a metadata operation. If you believe that you should have access to this metadata (i.e., if it is associated with your account), please make sure that your service accounts email address is listed as an Owner in the Permissions tab of the API console. See "gsutil help creds" for further information.
N)$gcs_oauth2_boto_plugin.oauth2_pluginr  rX   warningr   r   r   )r   r  s     rS   _WarnServiceAccountsCommand._WarnServiceAccountsg  sD     H kk$))
--LMN O rU   c                    U R                  U5      n[        U5      nU R                  R                  UR                  5      [
        R                  :X  aZ  UR                  S:w  aJ   U R                  R                  UU R                  UR                  S9n[        UR                  5       5        gU R                  S:X  a;  UR                  R                  nU(       d  U R                   R#                  SXU5        O.UR                  R$                  nU(       d  U R'                  U5        [        [(        R*                  " U5      5        g! [         a  nU R                  5         e SnAff = f)zwPrints the standard or default object ACL depending on self.command_name.

Args:
  url_str: URL string to get ACL for.
r  )r  r  Nr   a  No default object ACL present for %s. This could occur if the default object ACL is private, in which case objects created in this bucket will be readable only by their creators. It could also mean you do not have OWNER permission on %s and therefore do not have permission to read the default object ACL. It could also mean that %s has Bucket Policy Only enabled and therefore object ACLs and default object ACLs are disabled (see https://cloud.google.com/storage/docs/bucket-policy-only).)#GetAclCommandBucketListingReferencer!   r(  r{  r|  r   r   XmlPassThroughGetAclrz  printto_xmlr	   r  rP   root_objectr  rX   r   r   _ListAccessControlsAclr=   JsonFromMessage)r   url_strrr  rh   r   _s         rS   GetAndPrintAclCommand.GetAndPrintAcl  s"    
2
27
;C
w
'C&&szz2kooE

doo223?C||<?JJ 3 H 	cjjl
 
		h	&oo..
++

K 
) oo!! 

%
%c
*N**3/03 # !!#s   %AE 
E'E""E'c                 &   UR                  5       (       a.  U R                  R                  UR                  UR                  S9$ UR                  5       (       a9  U R                  R                  UR                  UR                  UR                  S9$ g)aT  Returns either bucket or object access controls for a storage url.

Args:
  storage_url: StorageUrl object representing the bucket or object.

Returns:
  BucketAccessControls, ObjectAccessControls, or None if storage_url does
  not represent a cloud bucket or cloud object.

Raises:
  ServiceException if there was an error in the request.
)r  N)rh  r(  ListBucketAccessControlsr  r|  IsObjectListObjectAccessControlsre   )r   rj  s     rS   r  Command._ListAccessControlsAcl  s     __55

!
!K,>,> 6 @ @					__55

!
!

!
!%% 6 ' '
 rU   c                    [        U5      nUR                  5       (       a)  [        U R                  U5      R	                  S/S95      nO>U R
                  S:X  a  S/nOS/n[        U R                  U5      R                  US95      nUR                  5       (       a  [        S5      eUR                  5       (       a  [        U< SU R
                  < S35      e[        U5      S	   $ )
a  Gets a single bucket listing reference for an acl get command.

Args:
  url_str: URL string to get the bucket listing reference for.

Returns:
  BucketListingReference for the URL string.

Raises:
  CommandException if string did not result in exactly one reference.
r   )ra  r   r  rY  No URLs matchedz8 matched more than one URL, which is not allowed by the  commandr   )r!   r  r   rM  IterObjectsrP   ri  IsEmptyr   HasPluralityre  )r   r  wildcard_urlplurality_iterrZ  s        rS   r  +Command.GetAclCommandBucketListingReference  s     (0L1



(
4
4%*G 5 -.n 
		h	&+,1



(
4
4) 5 +,n .//""$$ 1 134 4 ""rU   c                     U R                  XS9nUR                  5       (       a  [        U< SU R                  < S35      e[	        U5      S   n[        UR                  5      UR                  4$ )a0  Gets a single bucket URL based on the command arguments.

Args:
  arg: String argument to get bucket URL for.
  bucket_fields: Fields to populate for the bucket.

Returns:
  (StorageUrl referring to a single bucket, Bucket metadata).

Raises:
  CommandException if args did not match exactly one bucket.
rY  z8 matched more than one URL, which is not
allowed by the r  r   )GetBucketUrlIterFromArgr  r   rP   re  r!   rL  r  )r   argrZ  plurality_checkable_iteratorrr  s        rS   GetSingleBucketUrlFromArg!Command.GetSingleBucketUrlFromArg  st     $(#?#? $@ $* #0022!4#4#46 7 7 +
,Q
/C/@@rU   c                 .   [        U5      nUR                  5       (       a  UR                  5       (       a  [        SU R                  -  5      e[        U R                  U5      R                  US95      nUR                  5       (       a  [        S5      eU$ )a  Gets a single bucket URL based on the command arguments.

Args:
  arg: String argument to iterate over.
  bucket_fields: Fields to populate for the bucket.

Returns:
  PluralityCheckableIterator over buckets.

Raises:
  CommandException if iterator matched no buckets.
z""%s" command must specify a bucketrY  r  )	r!   rg  r  r   rP   r   rM  ri  r  )r   r  rZ  arg_urlr  s        rS   r  Command.GetBucketUrlIterFromArg  s     #3'G7#3#3#5#5A!../ 0 0 $>c"..].K$M #++--.//''rU   c                     [         R                  nU(       a%  U H  nX   R                  R                  5         M!     0 [         l        S [         l        g rW   )r   provider_pool
connectionclose)r   connection_poolis      rS   _ResetConnectionPoolCommand._ResetConnectionPool  sC     !..O!%%++-   "J JrU   c                    U R                   (       d  U(       a  U(       dC  [        R                  R                  SS[        R
                  R                  R                  5      nUS:  a  [        SU-  5      eU(       dC  [        R                  R                  SS[        R
                  R                  R                  5      nUS:  a  [        SU-  5      eOSnSn[        5       u  pVU(       aT  US:  aN  [        SR                  [        R                  " SU< S	S
R                  [        5       5      < S35      5      5      eU R                  S:H  nU(       a.  US:X  a(  US:  a"  U(       a  U R                  R!                  S5        U R                  R#                  SU5        U R                  R#                  SU5        X4$ )a  Determines the values of process_count and thread_count.

These values are used for parallel operations.
If we're not performing operations in parallel, then ignore
existing values and use process_count = thread_count = 1.

Args:
  process_count: A positive integer or None. In the latter case, we read
                 the value from the .boto config file.
  thread_count: A positive integer or None. In the latter case, we read
                the value from the .boto config file.
  parallel_operations_override: Used to override self.parallel_operations.
                                This allows the caller to safely override
                                the top-level flag for a single call.
  print_macos_warning: Print a warning about parallel processing on MacOS
                       if true.

Returns:
  (process_count, thread_count): The number of processes and threads to use,
                                 respectively.
r   parallel_process_countr   z$Invalid parallel_process_count "%d".parallel_thread_countz#Invalid parallel_thread_count "%d".r   z/It is not possible to set process_count > 1 on z0. Please update your config file(s) (located at z, z') and set "parallel_process_count = 1".r   macOSa^  If you experience problems with multiprocessing on MacOS, they might be related to https://bugs.python.org/issue33725. You can disable multiprocessing by editing your .boto config or by adding the following flag to your command: `-o "GSUtil:parallel_process_count=1"`. Note that multithreading is still available even if you disable multiprocessing.
zprocess count: %dzthread count: %d)r  r   r   r   r   commandsDEFAULT_PARALLEL_PROCESS_COUNTr   DEFAULT_PARALLEL_THREAD_COUNTr6   r   r   r   r,   recursive_apply_levelrX   rf   r  )r   process_countthread_countparallel_operations_overrideprint_macos_warningshould_prohibit_multiprocessingos_nameis_main_threads           rS   _GetProcessAndThreadCount!Command._GetProcessAndThreadCount(  s   8 #?**.NN!!@@B 
	E, - . 	.{{))-NN!!??A 
	D+ , - 	- 

 ml/L/N,#&=1+<TYY
-- 		"<">?ABC D D //14Nw'1ma6GN
kkCD 	KK)=9KK(,7((rU   c                 p   [            [        R                  5         [        R                  5       nSSS5        [        R                  " U 5      nU=R
                  S-  sl        SUl        SUl        SUl        U[        W'   S[        U'   S[        U'   S[        U'   / [        U'   U$ ! , (       d  f       N}= f)zBSet up the state for a caller id, corresponding to one Apply call.Nr   r   Fr   )r   r   	IncrementGetValuecopyr  rX   r(  r  r   r   r   r   r   )r   	caller_idr[   s      rS   _SetUpPerCallerStateCommand._SetUpPerCallerStaten  s     
!!##,,.i 
 ))D/C"
 CJ CN $CIiK	$)y!*+Y'*,Y'3 
s   )B''
B5c                    / n[        5       n[        R                  U5        [        R	                  5         [        R                  5       [        :  a  [        S5      e[        U5       Hf  n[        [        5      n[        R                  " U R                  X!UU4S9nSUl        UR                  U5        [        5         UR!                  5         Mh     [#        XE5      n	[        R                  U	5        g)z7Create a new pool of processes that call _ApplyThreads.z,Recursion depth of Apply calls is too great.)targetr   TN)r   r   r   r   r  r  MAX_RECURSIVE_DEPTHr   ranger  r   r2   Process_ApplyThreadsdaemonr~   start_ConsumerPool)
r   num_processesnum_threadsr  	processes
task_queuer  r  pconsumer_pools
             rS   _CreateNewConsumerPoolCommand._CreateNewConsumerPool  s    I)+Jz"))+"++-0CCKLL=!!.1
!
)
)1C1C0;0E0<0>?a ahqggi " ")8M-(rU   c                   $    \ rS rSrSrSrSrSrSrg)Command.ParallelOverrideReasoni  zAEnum class to describe purpose of overriding parallel operations.slicespeedperfdiagrl   N)	__name__
__module____qualname____firstlineno____doc__SLICESPEEDPERFDIAG__static_attributes__rl   rU   rS   ParallelOverrideReasonr    s    KE EHrU   r  c                 8   U(       a$  0 nU H  n[        X5      X'   [        XS5        M     U R                  XxU5      u  pxU R                  S:H  =(       a    U R                  S:H  nU(       a
  [        UUS9  U
=(       a    Xx-  S:H  n
U(       a*  U R                  (       d  US:  a  [        U R                  S9  U R                  5       nU(       a  U[        U'   U H  nS[        X4'   M     U R                  (       a  UOSnUU-  S:  a+  U R                  UUUUUUUU	U
UUS9  U(       a
  [        5         OU R                  XX?XYU
5        U(       a1  U H+  nWU   [        R                  X45      -   n[        XU5        M-     U	(       a  [         R                  U5      $ g)a  Calls _Parallel/SequentialApply based on multiprocessing availability.

Args:
  func: Function to call to process each argument.
  args_iterator: Iterable collection of arguments to be put into the
                 work queue.
  exception_handler: Exception handler for WorkerThread class.
  shared_attrs: List of attributes to manage across sub-processes.
  arg_checker: Used to determine whether we should process the current
               argument or simply skip it. Also handles any logging that
               is specific to a particular type of argument.
  parallel_operations_override: A string (see ParallelOverrideReason)
                                describing the reason to override
                                self.parallel_operations. This allows the
                                caller to safely override the top-level flag
                                for a single call.
  process_count: The number of processes to use. If not specified, then
                 the configured default will be used.
  thread_count: The number of threads per process. If not specified, then
                the configured default will be used..
  should_return_results: If true, then return the results of all successful
                         calls to func in a list.
  fail_on_error: If true, then raise any exceptions encountered when
                 executing func. This is only applicable in the case of
                 process_count == thread_count == 1.
  seek_ahead_iterator: If present, a seek-ahead iterator that will
      provide an approximation of the total number of tasks and bytes that
      will be iterated by the ProducerThread. Used only if multiple
      processes and/or threads are used.

Returns:
  Results from spawned threads.
r   r   )r  r   r   )rX   )rc  r  N)r}   setattrr  r  sequential_caller_idr   r.  r1   rX   r  r   r   _ParallelApply_AggregateThreadStats_SequentialApplyr   r   )r   funcargs_iteratorexception_handlershared_attrsarg_checkerr  r  r  should_return_resultsrb  rc  original_shared_vars_valuesnamer  r  usable_processes_countfinal_values                     rS   rk  Command.Apply  s   f $&!$,3D,?#) 	A	  %)$B$B%A%C!] 00A5 6//25  !.:<
 "I}'Cq'HM 	t@@ +$++>))+I
 (49%$-.)* 
 "&!B!B ,HI ,,q0






 


1'C  E 

D1B'O $ 348?;N;N< K(  %)))44 rU   c                 2   [         R                  R                  SSS5      S:X  a%  [         R                  R                  SSS5      S:X  dM  U R                  R	                  S[
        R                  " SU R                  R                  -  5      -   S-   5        gg)	z2Outputs a suggestion to the user to use gsutil -m.r   r  r   r   r  r   z==> NOTE: You are performing a sequence of gsutil operations that may run significantly faster if you instead use gsutil -m %s ...
Please see the -m section under "gsutil help options" for further information about when gsutil -m can be advantageous.N)	r   r   r   rX   rf   r   fillr   rP   r   s    rS   _MaybeSuggestGsutilDashM Command._MaybeSuggestGsutilDashM6  s    KKx)A1EJKKx)@!DI
kkthmmB 


(
(	)* *
 -11 2 JrU   c           	         [        SSU R                  U R                  U R                  U R                  S9n[        U5      nSn	  [        U5      n
U	S-  n	U	[        :X  d  U	[        -  S:X  a  U R!                  5         U" X
5      (       a  [#        XXCXeU5      nUR%                  X5        Mf  ! [         a
  n SnAO~SnAf[         an  n[        5         U(       a  e  U" X5        OG! [         a:  nU R                  R                  SU[        R                  " 5       5         SnAOSnAff = f SnAM  SnAff = fU	[        -  nU['        5       :  a  U R!                  5         [)        U R*                  R,                  [/        [0        R0                  " 5       5      5        UR2                  R5                  X@5        U R7                  U5        g)zPerforms all function calls sequentially in the current thread.

No other threads or processes will be spawned. This degraded functionality
is used when the multiprocessing module is not available or the user
requests only one thread and one process.
NF)r  r  r
  r  r   4Caught exception while handling exception for %s:
%sr   )WorkerThreadr  r  r
  r  iternextStopIteration	Exception_IncrementFailureCountrX   r  	traceback
format_exc#OFFER_GSUTIL_M_SUGGESTION_THRESHOLD#OFFER_GSUTIL_M_SUGGESTION_FREQUENCYr)  TaskPerformTaskr;   r4   r(  r  r%   r  shared_vars_updaterUpdate_ProcessSourceUrlTypes)r   r  r  r  r  r   r!  rb  worker_threadsequential_call_countr   r\   r  task#lines_since_suggestion_last_printeds                  rS   r  Command._SequentialApplyB  s    !!&)-)B)B262G2G-1-=-=.2.?.?AM 'M 
M"  q 
#F
F
"E
E
J 	%%'	T	 	 D	)G!!$-? 
    
(d& (KKG$$&( (( 4 ,A+N,O'*ln< ##%$//66&tyy{35
 %%,,Y= 	.sH   B+ +
D5:D5D0C#"D0#
D'-0D"D0"D''D00D5c                 
   U R                   S:H  nXR                  R                  :X  aB  U R                   S::  a2  [        R	                  [        [        R                  " 5       S5      5        [        (       d=  U(       a6  [        R                  [        R                  4 H  n[        U[        SS9  M     [        (       d  US:  a  [        R                  [        5       5        O[!        5       n[        R                  U5        [#        UU R$                  UU R&                  U R(                  U R*                  [        U R,                  U R.                  U R0                  U R2                  S9  US:  a   U(       d  [4        R7                  5         U R                   [8        R;                  5       :  ah  [<           U(       a  U R?                  Xg[        5        O;[@        RC                  SS9  [<        RE                  5         [<        RG                  5         SSS5        U(       d  [4        RI                  5         OU(       d   [4        R7                  5         U R                   [K        5       :  a  [M        5         [!        5       n[        R                  U5        [#        UU R$                  UU R&                  U R(                  U R*                  [        U R,                  U R.                  U R0                  U R2                  S9  [4        RI                  5         [        U R                      nU
(       a	  U(       d  Sn
[O        [P        RP                  " U 5      UUUUUUUU	U
U(       a  [        OSS9nSnU(       a#  [S        [        [T        RV                  [X        5      n [<           [Z        U   (       a
   SSS5        OUS:  a^  U(       aW  [@        R;                  5       (       a>  [@        RC                  5         U R?                  Xg[        5        [<        RE                  5         [<        RG                  5         SSS5        M  U(       aB  []        [        [^        5        URa                  [b        S	9  U Re                  URf                  5        URh                  (       a  URh                  eURj                  (       a  U	(       a  URj                  eU(       a5  U(       d-  []        [        [m        [        R                  " 5       5      5        ggg! , (       d  f       GN= f! U(       d  [4        RI                  5         f f = f! [4        RI                  5         f = f! , (       d  f       GN$= f)
ac  Dispatches input arguments across a thread/process pool.

Pools are composed of parallel OS processes and/or Python threads,
based on options (-m or not) and settings in the user's config file.

If only one OS process is requested/available, dispatch requests across
threads in the current OS process.

In the multi-process case, we will create one pool of worker processes for
each level of the tree of recursive calls to Apply. E.g., if A calls
Apply(B), and B ultimately calls Apply(C) followed by Apply(D), then we
will only create two sets of worker processes - B will execute in the first,
and C and D will execute in the second. If C is then changed to call
Apply(E) and D is changed to call Apply(F), then we will automatically
create a third set of processes (lazily, when needed) that will be used to
execute calls to E and F. This might look something like:

Pool1 Executes:                B
                              / \
Pool2 Executes:              C   D
                            /     \
Pool3 Executes:            E       F

Apply's parallelism is generally broken up into 4 cases:
- If process_count == thread_count == 1, then all tasks will be executed
  by _SequentialApply.
- If process_count > 1 and thread_count == 1, then the main thread will
  create a new pool of processes (if they don't already exist) and each of
  those processes will execute the tasks in a single thread.
- If process_count == 1 and thread_count > 1, then this process will create
  a new pool of threads to execute the tasks.
- If process_count > 1 and thread_count > 1, then the main thread will
  create a new pool of processes (if they don't already exist) and each of
  those processes will, upon creation, create a pool of threads to
  execute the tasks.

Args:
  caller_id: The caller ID unique to this call to command.Apply.
  See command.Apply for description of other arguments.
r   r   T)is_final_handler)	r  r  r$  r  r  r  r  r
  r  )reset_valueN)rc  r  timeout)7r  r  r  r   putr'   r  r<   signalSIGINTSIGTERMr   r   r   r   r   r   
WorkerPoolrX   r  r$  r  r  r  r
  r  r   acquirer   r  r   r  r   Reset
notify_allwaitrelease_GetCurrentMaxRecursiveLevel"_IncrementCurrentMaxRecursiveLevelProducerThreadr  r+   r&  r'  r  r   r4   r8   r   r7   r;  r  unknown_exceptioniterator_exceptionr%   )r   r  r  r  r  r   r  r  r!  rb  rc  r  r  
signal_numr  producer_thread	ui_threads                    rS   r  Command._ParallelApply  s   t //14N$(C(C(I(II""a' 5diik4HI:.  7*j</3	5 8
 ;
 
	356(*
:& 	<;;(,0,I,I"&"5"5 144$($9$9#// $ 1 1
	3 q/
$
,
,
.%%)D)M)M)OO% ))-*;= ###2$//1$))+ & 
$
,
,
.	/
$
,
,
.''*F*HH /0,.Jz*|{{",040M0M&*&9&9!ZZ$5#88(,(=(=#'#3#3$($5$5
7 %
,
,
.T778J >  %		$/+9'tFO I,cjj-Hi !i(
 "! aN&&((



!

%
%m&79
 
+
+
-
 	##% " $ -/HInn3n4
!!/"?"?@
 ((--- ))m...:-|DIIK/HI ;~k &% 
$
,
,
. 0 %
,
,
.Z "!sF   /AT 2AS4T 8B<T' U +A8U 4
T>T T$'T= 
Uc                     [        U[        5      (       d  g[        UR                  UR                  UR
                  UR                  S9  g)z6Logs the URL type information to analytics collection.N)is_daisy_chainhas_file_srchas_cloud_srcprovider_types)
isinstancer   r   rZ  r[  r\  r]  )r   r  s     rS   r;  Command._ProcessSourceUrlTypest  s?    m%899}/K/K-:-G-G.;.I.I/</K/KMrU   c                    US:  d   S5       e[        5         [        5        H  n[        R                  " U[        5        M      U R	                  5         X0l        [        U   n[        R                  " U5      n[        UU R                  UU R                  U R                  U R                  UU R                  U R                  U R                   U R"                  S9nSn	 UR%                  SS9(       d,  [&        R(                  " S5        UR%                  SS9(       d  M,  UR+                  5       n
U
R,                  [.        :w  a  UR1                  U
5        U	S-  n	OUR3                  5         M  )ac  Assigns the work from the multi-process global task queue.

Work is assigned to an individual process for later consumption either by
the WorkerThreads or (if thread_count == 1) this thread.

Args:
  thread_count: The number of threads used to perform the work. If 1, then
                perform all work in this thread.
  process_count: The number of processes used to perform the work.
  recursive_apply_level: The depth in the tree of recursive calls to Apply
                         of this thread.
  status_queue: Multiprocessing/threading queue for progress reporting and
      performance aggregation.
r   zCInvalid state, calling command._ApplyThreads with only one process.	worker_semaphorer  r$  r  r  r  r  r
  r  r   F)blockingg{Gz?)r~   r   rG  r   r  r  r   r   r   rJ  rX   r  r$  r  r  r  r
  r  rK  r  sleepr   r   r8   AddTaskrO  )r   r  r  r  r  catch_signalr  rb  worker_poolnum_enqueuedr>  s              rS   r  Command._ApplyThreads}  sV     1 OMO 
 )*mmL";< + 	!623J !11,? )!%!>!>**jj!))..$$&&(K L
 ((%(8 	

4 !((%(88 ^^d	/	/ 	D! 	  ") rU   )r  r  r   r  r  r   r  r   r  rx   r_   r(  r  r$  r)  r+  r  rX   r.  r  r  r  r%  r  r  r  r  r,  r
  r  r  )NNNN)FNT)FrW   )TNN)3r  r  r  r  r  r   r!  r  r  staticmethodr.   r   r   propertyrP   r   r   r  r   r>  r  r"  rM  rQ  rT  ru  rr   r}  r~  r  r  r  r  r  r  r  r  r  r  r  objectr  rj   rk  r)  r  r  r;  r  r  __classcell__r5  s   @rS   r   r     s~   + ,,@(
  '+-1!"!'+-$)(-'('+'+/3+/D D:* 01,,8  $"& $ M=^$$ $37'*R:26*&:A* "&	RHhE4.:HT)HVO0)1V0$#LA,(8!$ 59	D)L#J),v  &)-"' $A5F	2E/d *.26hJTMJ# J#rU   r   c                        \ rS rSrS rS rSrg)r  i  c                     Xl         X l        g rW   r  r  )r   r  r  s      rS   r  _ConsumerPool.__init__  s    N OrU   c                 T    U R                    H  n[        UR                  5        M     g rW   )r  r   pid)r   processs     rS   ShutDown_ConsumerPool.ShutDown  s    >>'++ "rU   rr  N)r  r  r  r  r  rw  r  rl   rU   rS   r  r    s    !rU   r  c                       \ rS rSrSrSrg)r7  i  a!  Task class representing work to be completed.

Args:
  func: The function to be executed.
  args: The arguments to func.
  caller_id: The globally-unique caller ID corresponding to the Apply call.
  exception_handler: The exception handler to use if the call to func fails.
  should_return_results: True iff the results of this function should be
                         returned from the Apply call.
  arg_checker: Used to determine whether we should process the current
               argument or simply skip it. Also handles any logging that
               is specific to a particular type of argument.
  fail_on_error: If true, then raise any exceptions encountered when
                 executing func. This is only applicable in the case of
                 process_count == thread_count == 1.
rl   N)r  r  r  r  r  r  rl   rU   rS   r7  r7    s      rU   r7  zUfunc args caller_id exception_handler should_return_results arg_checker fail_on_errorc                 "    [        X[        5      $ )a  Initializes and runs the seek-ahead thread.

We defer starting this thread until it is needed, since it is only useful
when the ProducerThread iterates more results than it can store on the global
task queue.

Args:
  seek_ahead_iterator: Iterator that yields SeekAheadResults.
  seek_ahead_thread_cancel_event: threading.Event for signaling the
      seek-ahead thread to terminate.

Returns:
  The thread object for the initialized thread.
)r   r   )rc  seek_ahead_thread_cancel_events     rS   _StartSeekAheadThreadr|    s    * 
,*
, ,rU   c                   :   ^  \ rS rSrSr  SU 4S jjrS rSrU =r$ )rR  i
  z<Thread used to enqueue work for other processes and threads.c                   > [         [        U ]  5         X@l        Xl        X l        X0l        XPl        Xl        Xpl	        X`l
        Xl        [        5       U l        SU l        SU l        SU l        Xl        Xl        U R'                  5         g)a  Initializes the producer thread.

Args:
  cls: Instance of Command for which this ProducerThread was created.
  args_iterator: Iterable collection of arguments to be put into the
                 work queue.
  caller_id: Globally-unique caller ID corresponding to this call to Apply.
  func: The function to be called on each element of args_iterator.
  task_queue: The queue into which tasks will be put, to later be consumed
              by Command._ApplyThreads.
  should_return_results: True iff the results for this call to command.Apply
                         were requested.
  exception_handler: The exception handler to use when errors are
                     encountered during calls to func.
  arg_checker: Used to determine whether we should process the current
               argument or simply skip it. Also handles any logging that
               is specific to a particular type of argument.
  fail_on_error: If true, then raise any exceptions encountered when
                 executing func. This is only applicable in the case of
                 process_count == thread_count == 1.
  seek_ahead_iterator: If present, a seek-ahead iterator that will
      provide an approximation of the total number of tasks and bytes that
      will be iterated by the ProducerThread.
  status_queue: status_queue to inform task_queue estimation. Only
      valid when calling from the main thread, else None. Even if this is
      the main thread, the status_queue will only properly work if args
      is a collection of NameExpansionResults, which is the type that gives
      us initial information about files to be processed. Otherwise,
      nothing will be added to the queue.
TN)r  rR  r  r  r[   r  r  r  r   r  r!  rb  _SharedVariablesUpdatershared_variables_updaterr  rS  rT  rc  r  r  )r   r[   r  r  r  r  r!  r  r   rb  rc  r  r5  s               rS   r  ProducerThread.__init__  s|    T 
.$(*IH&N O".!6&$;$=D!DK!D"D2$JJLrU   c                    SnS nS nS nS nS nSnS n Sn	[        U R                  5      U l          [        U R                  5      nU R%                  U R                  U5      (       GaM  US-  nU R&                  (       Ga-  US-  (       dr  [)        U[*        5      (       d*  [)        U[,        5      (       d  [)        U[.        5      (       a3  [1        U R&                  [3        X[4        R4                  " 5       5      5        [)        U[*        5      (       d  [)        U[,        5      (       aI  UR6                  (       a7  [8        R:                  " UR6                  5      nSU;   a  U	[=        US   5      -  n	O>[)        U[.        5      (       a)  UR>                  (       a  U	[=        UR>                  5      -  n	U(       d  Uc
  [A        5       nUS::  a  SnO|X:  aw  U RB                  (       ad  [D        RF                  " 5       n[I        U RB                  U5      n[J        RL                  RO                  SS	S 5      (       a  URQ                  [R        S
9  SnUn[U        U R                  XR"                  U R                  U RV                  U R$                  U R                  5      nU(       a  U RX                  R[                  U5        GM  ! [         a  n
 S n
A
GOS n
A
f[         a  n
[        5         U R                  (       a  Xl        e  U R                  U R                  U
5        O[! [         aN  nU R                  R                  R                  SU R                  [        R                  " 5       5         S nAOS nAff = fU R                  R!                  U R"                  U R                  5         S n
A
GMx  S n
A
ff = f! [         a!  n
U R                  (       d  Xl.         S n
A
OS n
A
ff = fU[^        U R"                  '   U(       d  [U        S [`        U R"                  S S S S 5      nU RX                  R[                  U5        Ub#  URc                  5         URQ                  [R        S
9  U R&                  (       ar  [)        U[*        5      (       d*  [)        U[,        5      (       d  [)        U[.        5      (       a3  [1        U R&                  [3        UW	[4        R4                  " 5       SS95        [e        U R"                  [f        RO                  U R"                  5      5        g ! U[^        U R"                  '   U(       d  [U        S [`        U R"                  S S S S 5      nU RX                  R[                  U5        Ub#  URc                  5         URQ                  [R        S
9  U R&                  (       ar  [)        U[*        5      (       d*  [)        U[,        5      (       d  [)        U[.        5      (       a3  [1        U R&                  [3        UW	[4        R4                  " 5       SS95        [e        U R"                  [f        RO                  U R"                  5      5        f = f)Nr   FTr,  r   d   sizer   task_estimation_forcerD  )finished)4r.  r  r/  r0  r1  r2  rb  rT  r  r[   rX   r  r  r3  r4  r  r:  r  r   r  r^  r   r   r9   r4   r(   r  r_  jsonloadsint	copy_sizer   rc  r   Eventr|  r   r   r   r   r5   r7  r!  r  rF  rS  r   r8   r   _NotifyIfDoner   )r   	num_taskscur_task	last_taskr   seek_ahead_threadr{  seek_ahead_thread_consideredr   
total_sizer\   r  json_expanded_results                rS   runProducerThread.runI  s    IHI $%)"#( DpBj 2 23d	d(()$$ DHHd++
q.)s?T#677T>22T#344%%%))MO 4!455400%%'+zz$2F2F'G$11$8$@ AA*D"233c$..11
-(0*E*G'(A--1*7))1:1B.$9,,.L%N! ;;??8-DdKK#((1H(I-1*)$))T>>00$2L2L**D,>,>@( OO	*A   	
 	
 
"&'#5$$TXXq1 5hhoo##I))Y1135 55 ))00J	x  # $$!"# %.k$..!7dD*
oo(#
 
	&&**,
 	'>? 

d/00JN5$ 5$'1$8H'I'I!)","&))++/1	2 DNN,00@B? %.k$..!7dD*
oo(#
 
	&&**,
 	'>? 

d/00JN5$ 5$'1$8H'I'I!)","&))++/1	2 DNN,00@Bs   N. J7 I2N. 7
N+N. T N+"N&7LN&
M,AM'"N&'M,,3N&N. &N++N. .
O8OT OT D2X?)r   r  r  r[   r  r  rb  r  rT  rc  r  r!  r  r  rS  rj  )	r  r  r  r  r  r  r  r  rn  ro  s   @rS   rR  rR  
  s"    D $( :xyB yBrU   rR  c                   <    \ rS rSrSr          SS jrS rSrg)rJ  i  z3Pool of worker threads to which tasks can be added.Nc                    US L US L :w  d   eXl         Xl        Xl        Xl        U=(       d
    [	        5       U l        / U l        [        U5       Hs  n[        U R
                  UUUUUUU R                   U R                  U R                  U R                  S9nU R                  R                  U5        UR                  5         Mu     g )Nra  )r  r  r
  r  r   r  threadsr  r-  r   r  )r   r  rX   rb  r  r  r$  r  r  r  r  r
  r  r  r<  s                  rS   r  WorkerPool.__init__  s    , $**<===L,"$ 9$7$9DODL< "
//
+#;'#,,00&&((*m ll-( !rU   c                 :    U R                   R                  U5        g)zCAdds a task to the task queue; used only in the multi-process case.N)r  rF  )r   r>  s     rS   re  WorkerPool.AddTask  s    OOrU   )r  r  r  r  r
  r  )
NNNNr   NNNNN)r  r  r  r  r  r  re  r  rl   rU   rS   rJ  rJ    s0    ;
 !%(,"  $ ,\rU   rJ  c                   n   ^  \ rS rSrSr         S	U 4S jjr\S 5       r\S 5       rS r	S r
SrU =r$ )
r-  i  a.  Thread where all the work will be performed.

This makes the function calls for Apply and takes care of all error handling,
return value propagation, and shared_vars.

Note that this thread is NOT started upon instantiation because the function-
calling logic is also used in the single-threaded case.
c                   > [         [        U ]  5         [        R                  " 5       U l        [        R                  " 5       U l        Xl        X0l	        SU l
        0 U l        [        5       U l        Xl        Xl        Xl        Xl        SU l        U(       aG  U(       a?  ['        UUUUUU R                  U R                  U R                   U R"                  S9	U l        ggg)a6  Initializes the worker thread.

Args:
  task_queue: The thread-safe queue from which this thread should obtain
              its work.
  logger: Logger to use for this thread.
  worker_semaphore: threading.BoundedSemaphore to be released each time a
      task is completed, or None for single-threaded execution.
  bucket_storage_uri_class: Class to instantiate for cloud StorageUris.
                            Settable for testing/mocking.
  gsutil_api_map: Map of providers and API selector tuples to api classes
                  which can be used to communicate with those providers.
                  Used for the instantiating CloudApiDelegator class.
  debug: debug level for the CloudApiDelegator class.
  status_queue: Queue for reporting status updates.
  user_project: Project to be billed for this request.
TN)r  r	  r  r
  r  )r  r-  r  rb   getpidru  r  	init_timer  rb  r  cached_classesr  r9  r  r  r
  r  thread_gsutil_apir   )r   r  rX   rb  r  r$  r  r  r  r  r
  r  r5  s               rS   r  WorkerThread.__init__	  s    : 
,&(yy{DHYY[DN O,DKD68DL,"$
 "DN0
"


||00&&((	 *d %3rU   c                 \   [         R                  U R                  U R                  45      c2  [	        U R
                  5      [         U R                  U R                  4'   [         U R                  U R                  4   nUR                  5         U[         U R                  U R                  4'   g)zEUpdate the thread_stats AtomicDict before task_queue.get() is called.N)r   r   ru  ident_ThreadStatr  StartBlockedTimer   thread_stats     rS   _StartBlockedTimeWorkerThread._StartBlockedTimeG	  s~     4::./7-8-HlDHHdjj)* $**56K  "+6L$((DJJ'(rU   c                     [         U R                  U R                  4   nUR                  5         U[         U R                  U R                  4'   g)zDUpdate the thread_stats AtomicDict after task_queue.get() is called.N)r   ru  r  EndBlockedTimer  s     rS   _EndBlockedTimeWorkerThread._EndBlockedTimeS	  s>     $**56K +6L$((DJJ'(rU   c                 x   UR                   n UR                  X!R                  U R                  S9nUR                  (       a  [
        R                  X4// S9  U R                  (       a  U R                  R!                  5         U R"                  R%                  X25        [&        R                  US5      n[)        X75        g! [         a  n[        5         UR                  (       a  e  UR                  X%5         SnAN! [         a>  nUR                  R                  SU[        R                  " 5       5         SnA SnANSnAff = fSnAff = f! U R                  (       a  U R                  R!                  5         U R"                  R%                  X25        [&        R                  US5      n[)        X75        f = f)zMakes the function call for a task.

Args:
  task: The Task to perform.
  cls: The instance of a class which gives context to the functions called
       by the Task's function. E.g., see SetAclFuncWrapper.
rp   )default_valuer,  Nr   )r  r  r   r  r!  r   r  r1  r2  rb  r  rX   r  r3  r4  rb  rO  r9  r:  r   r  )r   r>  r[   r  resultsr\   r  num_dones           rS   r8  WorkerThread.PerformTaskZ	  s_    I)		#yyt7M7M	Ng		#	# **9i9; 	+ 	=  
		%%'
%%i5
 *33IqAhI(-  &				&

 
 
(
( 	& **

Et""$& &	&& 
		%%'
%%i5
 *33IqAhI(sU   A
C   
E
E'C=8E =
E0E 7E;E  EEEE A)F9c                     U R                  5         U R                  R                  5       nU R                  5         UR                  [
        :X  a  MQ  UR                  nU R                  R                  US 5      nU(       dE  [        R                  " [        U   5      n[        UR                  5      Ul        X0R                  U'   U R                  X5        M  rW   )r  r  r   r  r   r8   r  r  r  r   rT   rP   rX   r8  )r   r>  r  r[   s       rS   r  WorkerThread.run	  s    

__  "d
	/	/ 	..i ##It4cii	),-,S-=-=>
),I&
t!# rU   )r  r  r  r  r  ru  r9  r  r  r
  r  rb  )	NNNr   NNNNN)r  r  r  r  r  r  r   r  r  r8  r  r  rn  ro  s   @rS   r-  r-    sc    & !%(,"  $ 9*v 	7 	7 7 7$)L" "rU   r-  c                   0    \ rS rSrSrS rS rS rS rSr	g)	r  i	  z1Stores thread idle and execution time statistics.c                 `    SU l         Xl        [        R                  " 5       U l        SU l        g )Nr   )total_idle_timeend_block_timer  start_block_timetotal_execution_time)r   r  s     rS   r  _ThreadStat.__init__	  s*    D $ !IIKD !DrU   c                     [         R                   " 5       U l        U R                  U R                  -
  nU =R                  U-  sl        g rW   )r  r  r  r  )r   	exec_times     rS   r  _ThreadStat.StartBlockedTime	  s7     IIKD%%(;(;;I*rU   c                     [         R                   " 5       U l        U R                  U R                  -
  nU =R                  U-  sl        g rW   )r  r  r  r  )r   	idle_times     rS   r  _ThreadStat.EndBlockedTime	  s7    ))+D##d&;&;;II%rU   c                     U R                   U R                  :  a"  U =R                  XR                   -
  -  sl        gU =R                  XR                  -
  -  sl        g)z)Decide final stats upon Apply completion.Nr  r  r  r  )r   end_times     rS   AggregateStat_ThreadStat.AggregateStat	  sN    T222 8.A.A#AA h)>)>>>rU   r  N)
r  r  r  r  r  r  r  r  r  r  rl   rU   rS   r  r  	  s    9	"+
&
?rU   r  c                      [         R                   " 5       n S=p[        R                  5        H0  nUR                  U 5        XR                  -  nX#R
                  -  nM2     [        UUS9  g)zAt the end of the top-level Apply call, aggregate the thread stats dict.

This should only be called in the main process and thread because it logs to
the MetricsCollector.
r   )thread_idle_timethread_execution_timeN)r  r   valuesr  r  r  r   )cur_timer  r  r  s       rS   r  r  	  se     YY[(+,,/!((*kh'222O<<< + 4HJrU   c                   $    \ rS rSrSrS rS rSrg)r  i	  aB  Used to update shared variable for a class in the global map.

Note that each thread will have its own instance of the calling class for
context, and it will also have its own instance of a
_SharedVariablesUpdater.  This is used in the following way:

1. Before any tasks are performed, each thread will get a copy of the
   calling class, and the globally-consistent value of this shared variable
   will be initialized to whatever it was before the call to Apply began.

2. After each time a thread performs a task, it will look at the current
   values of the shared variables in its instance of the calling class.

   2.A. For each such variable, it computes the delta of this variable
        between the last known value for this class (which is stored in
        a dict local to this class) and the current value of the variable
        in the class.

   2.B. Using this delta, we update the last known value locally as well
        as the globally-consistent value shared across all classes (the
        globally consistent value is simply increased by the computed
        delta).
c                     0 U l         g rW   last_shared_var_valuesr   s    rS   r   _SharedVariablesUpdater.__init__	  s
    "$DrU   c                     [         R                  US5      nU(       a]  U HV  nX4nU R                  R                  US5      n[        X$5      U-
  nXv-   U R                  U'   [        R                  XW5        MX     gg)z.Update any shared variables with their deltas.Nr   )r   r   r  r}   r   r  )r   r  r[   shared_varsr#  key
last_valuedeltas           rS   r:  _SharedVariablesUpdater.Update	  sz    &**9d;K$0044S!<
 "Z/+0+=##C( 	!!#-  rU   r  N)r  r  r  r  r  r  r:  r  rl   rU   rS   r  r  	  s    0%.rU   r  c                     [         U    nX!:X  a4  US:  a-  [           S[        U '   [        R                  5         SSS5        ggg! , (       d  f       g= f)a  Notify any threads waiting for results that something has finished.

Each waiting thread will then need to check the call_completed_map to see if
its work is done.

Note that num_done could be calculated here, but it is passed in as an
optimization so that we have one less call to a globally-locked data
structure.

Args:
  caller_id: The caller_id of the function whose progress we're checking.
  num_done: The number of tasks currently completed for that caller_id.
r   TN)r   r   r   rM  )r  r  	num_to_dos      rS   r  r  	  sK     )$)yA~	&*#'') 
 	  .		s   A
Ac                      [          H  n  U R                  5         M     [         H  nUR                  5         M      [        R                  5         g!    MP  = f!    g= f)zEShut down all processes in consumer pools in preparation for exiting.N)r   cancel_join_threadr   rw  r   )qr  s     rS   r   r   
  s[     a 
 &m &	((*

	s   AA AAc                  *    [         R                  5       $ rW   )r   r  rl   rU   rS   rP  rP  !
  s    	$	-	-	//rU   c                  ,    [         R                  5         g rW   )r   r  rl   rU   rS   rQ  rQ  &
  s    '')rU   c                  ,    [         R                  5         g rW   )r   r  rl   rU   rS   r2  r2  +
      rU   c                  ,    [         R                  5         g rW   )r   	Decrementrl   rU   rS   DecrementFailureCountr  0
  r  rU   c                  *    [         R                  5       $ )zAReturns the number of failures processed during calls to Apply().)r   r  rl   rU   rS   GetFailureCountr  5
  s     
			!!rU   c                  ,    [         R                  5         g)zEResets the failure_count variable to 0 - useful if error is expected.N)r   rL  rl   rU   rS   ResetFailureCountr  ;
  s     rU   rW   )r  
__future__r   r   r   r   r  collectionsr   r  rA  r  rE   rb   rG  r&  r   r   r  r3  r   boto.storage_urir   r   gslib.cloud_apir	   r
   r   gslib.cloud_api_delegatorr   gslib.cs_api_mapr   r   gslib.exceptionr   gslib.help_providerr   gslib.metricsr   r   gslib.name_expansionr   r   r   r   r   "gslib.plurality_checkable_iteratorr   gslib.seek_ahead_threadr   gslib.sig_handlingr   r   r   r   r   gslib.storage_urlr   r    r!   r"   r#   "gslib.third_party.storage_apitoolsr$   r  gslib.thread_messager%   r&   r'   r(   gslib.ui_controllerr)   r*   r+   gslib.utils.boto_utilr,   r-   gslib.utils.constantsr.   r/   &gslib.utils.parallelism_framework_utilr0   r1   r2   r3   r4   r5   r6   r7   r8   gslib.utils.rsync_utilr9   gslib.utils.shim_utilr:   gslib.utils.system_utilr;   r<   gslib.utils.translation_helperr=   r>   r?   gslib.wildcard_iteratorr@   	six.movesrA   r   CryptorB   r|   ImportErrorr5  r6  rT   r]   rj   rn   rt   ry   r   r~   r   r   r   r   r   r  r   r   r   r   r   r   rm  r  r7  r|  ThreadrR  rJ  r-  r  r  r  r  r   rP  rQ  r2  r  r  r  rl   rU   rS   <module>r     s   ' %  '  "     	  
      '  1 - , 7 ( 0 , , 4 5 / 4 6 4 ? I 3 8 / * = 4 * . 2 6 ; W - 0 : 6 1 , ( < C ( & - = W J J H J P I L 3 ; 0 . 9 @ B : $+
 '( #&* #"JJ" 
 
 %* !?   T]enen4 E"E"/-e$"E*"E*<S+l	F +J >W#l5 W#x.F v	4,2xBY%% xBv3 3lW"9## W"t$?& $?NJ +.f +.\*.	 0
*


"_N  ,s   :K KK