
    0                         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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Jr  SS	KJrJr  SS
KJr  \" SS5      r " S S\5      rS rS rS rSS jr SS jr SS jrg)zAHelper functions for composite upload tracker file functionality.    )absolute_import)print_function)division)unicode_literals)
namedtupleN)CommandException)WriteJsonDataToTrackerFile#RaiseUnwritableTrackerFileException)UTF8ObjectFromTrackerzobject_name generationc                   ,    \ rS rSrSrSrSrSrSrSr	Sr
g	)
_CompositeUploadTrackerEntry&   z7Enum class for composite upload tracker file JSON keys.
componentscomponent_namecomponent_generationencryption_key_sha256prefix N)__name__
__module____qualname____firstlineno____doc__COMPONENTS_LISTCOMPONENT_NAMECOMPONENT_GENERATION
ENC_SHA256PREFIX__static_attributes__r       .platform/gsutil/gslib/parallel_tracker_file.pyr   r   &   s    ? /#./&*&r!   r   c                    SnSn/ nSn [        U S5      nUR                  5       n[        R                  " U5      nU[        R
                     nU[        R                     nU[        R                      H@  nUR                  [        U[        R                     U[        R                     5      5        MB     U(       a  UR)                  5         X#U4$ ! [         aE  n	U	R                  [        R                  :w  a  UR                  SU U	R                   5         Sn	A	NeSn	A	f["        [$        4 a  n	Sn['        W5      u  p4 Sn	A	NSn	A	ff = f! U(       a  UR)                  5         f f = f)az  Read the tracker file from the last parallel composite upload attempt.

If it exists, the tracker file is of the format described in
WriteParallelUploadTrackerFile or a legacy format. If the file doesn't exist
or is formatted incorrectly, then the upload will start from the beginning.

This function is not thread-safe and must be protected by a lock if
called within Command.Apply.

Args:
  tracker_file_name: The name of the tracker file to read parse.
  logger: logging.Logger for outputting log messages.

Returns:
  enc_key_sha256: Encryption key SHA256 used to encrypt the existing
      components, or None if an encryption key was not used.
  component_prefix: String prefix used in naming the existing components, or
      None if no prefix was found.
  existing_components: A list of ObjectFromTracker objects representing
      the set of files that have already been uploaded.
Nrz^Couldn't read upload tracker file (%s): %s. Restarting parallel composite upload from scratch.)openreadjsonloadsr   r   r   r   appendr   r   r   IOErrorerrnoENOENTwarnstrerrorKeyError
ValueError_ParseLegacyTrackerDataclose)
tracker_file_nameloggerenc_key_sha256r   existing_componentstracker_filetracker_datatracker_json	componentes
             r"   ReadParallelUploadTrackerFiler<   /   sQ   , .&,)3/L$$&L::l+L!">"I"IJN6==>F!">"N"NO	  
4CCD4IIJLM P& 
"5	66# 
  	ww%,,kk45F
** J	 JN$;L$I!V J
  s<   B/C 
E
;DE E
1E E E

E E'c                    U R                  S5      SS nSn/ nU(       a_  US   nSnU[        U5      S-
  :  aF  X   XS-      peU(       d  SnUR                  [        XV5      5        US-  nU[        U5      S-
  :  a  MF  X#4$ )ad  Parses a legacy parallel composite upload tracker file.

Args:
  tracker_data: Legacy tracker file contents.

Returns:
  component_prefix: The prefix used in naming the existing components, or
      None if no prefix was found.
  existing_components: A list of ObjectFromTracker objects representing
      the set of files that have already been uploaded.

Nr         )splitlenr)   r   )r8   old_tracker_datar   r6   iname
generations          r"   r1   r1   k   s     "''-cr2&a F	A
c"#a'
',/1Aa%1HZ
  !24!DE1fa c"#a'
' 	&&r!   c
                    [         R                  (       aT  [        U[        5      (       a  UR	                  [
        5      n[        U[        5      (       a  UR	                  [
        5      nU(       a  X:w  a   UR                  SU 5        / n
U H5  nUR                  5       nUR                  Ul        UR                  Ul	        M7     UR                  UU
U	[        R                  R                  UR                  R                  S9  S/ 4$ X#4$ !   U Vs/ s H  oR                  PM     Os  snf nnUR                  SSR!                  U5      5         S/ 4$ = f)a  Validates that tracker data matches the current encryption key.

If the data does not match, makes a best-effort attempt to delete existing
temporary component objects encrypted with the old key.

Args:
  tracker_file_name: String file name of tracker file.
  existing_enc_sha256: Encryption key SHA256 used to encrypt the existing
      components, or None if an encryption key was not used.
  existing_prefix: String prefix used in naming the existing components, or
      None if no prefix was found.
  existing_components: A list of ObjectFromTracker objects representing
      the set of files that have already been uploaded.
  current_enc_key_sha256: Current Encryption key SHA256 that should be used
      to encrypt objects.
  bucket_url: Bucket URL in which the components exist.
  command_obj: Command class for calls to Apply.
  logger: logging.Logger for outputting log messages.
  delete_func: command.Apply-callable function for deleting objects.
  delete_exc_handler: Exception handler for delete_func.

Returns:
  prefix: existing_prefix, or None if the encryption key did not match.
  existing_components: existing_components, or empty list if the encryption
      key did not match.
zUpload tracker file (%s) does not match current encryption key. Deleting old components and restarting upload from scratch with a new tracker file that uses the current encryption key.)arg_checkerparallel_operations_overridezrFailed to delete some of the following temporary objects:
%s
(Continuing on to re-upload components from scratch.)r>   N)sixPY3
isinstancestrencoder   r-   Cloneobject_namerG   ApplygslibcommandDummyArgCheckerParallelOverrideReasonSPEEDjoin)r3   existing_enc_sha256existing_prefixr6   current_enc_key_sha256
bucket_urlcommand_objr4   delete_funcdelete_exc_handlercomponents_to_deleter:   urlcomponent_namess                 r"   $ValidateParallelCompositeTrackerDatarc      sP   > 	WW%s++/66t<(#..5<<TB,F&kk /	0
  *) #//"-- +
 


mm33'2'I'I'O'O  Q& ":
	//	& 2E1DI

1Do  kkB
))O
$& ":s   7BD ED(')Ec                 `    [        [        R                  " SS5      [        U 5      -   S-  5      $ )a@  Generates a random prefix for component objects.

Args:
  encryption_key_sha256: Encryption key SHA256 that will be used to encrypt
      the components. This is hashed into the prefix to avoid collision
      during resumption with a different encryption key.

Returns:
  String prefix for use in the composite upload.
r@   l   c(	 l    d(	 )rN   randomrandinthashr   s    r"   GenerateComponentObjectPrefixri      s1     
~~a&.C)DDN
P Pr!   c           	          U   [        X5      u  pVnXT:w  a!  [        SU< SU< SUR                  < 35      eU/nXx-   n	[        U UU	US9  SSS5        g! , (       d  f       g= f)a  Rewrites an existing tracker file with info about the uploaded component.

Follows the format described in _CreateParallelUploadTrackerFile.

Args:
  tracker_file_name: Tracker file to append to.
  tracker_file_lock: Thread and process-safe Lock protecting the tracker file.
  component: ObjectFromTracker describing the object that was uploaded.
  logger: logging.Logger for outputting log messages.
  encryption_key_sha256: Encryption key SHA256 for use in this upload, if any.
z,gsutil client error: encryption key SHA256 (z8) in tracker file does not match encryption key SHA256 (z) of component rh   N)r<   r   rQ   WriteParallelUploadTrackerFile)
r3   tracker_file_lockr:   r4   r   existing_enc_key_sha256r   r6   newly_completed_componentscompleted_componentss
             r"   )WriteComponentToParallelUploadTrackerFilerp      sz      :	$7 #$9  "# #
 #,.K"#4#)#79NP s   AA
A"c                    [         R                  (       a&  [        U[        5      (       a  UR	                  S5      n/ nU HH  nUR                  [        R                  UR                  [        R                  UR                  05        MJ     [        R                  U[        R                  U[        R                  U0n[        X5        g)al  Writes information about components that were successfully uploaded.

The tracker file is serialized JSON of the form:
{
  "encryption_key_sha256": sha256 hash of encryption key (or null),
  "prefix": Prefix used for the component objects,
  "components": [
    {
     "component_name": Component object name,
     "component_generation": Component object generation (or null),
    }, ...
  ]
}
where N is the number of components that have been successfully uploaded.

This function is not thread-safe and must be protected by a lock if
called within Command.Apply.

Args:
  tracker_file_name: The name of the parallel upload tracker file.
  prefix: The generated prefix that used for uploading any existing
      components.
  components: A list of ObjectFromTracker objects that were uploaded.
  encryption_key_sha256: Encryption key SHA256 for use in this upload, if any.
asciiN)rK   rL   rM   bytesdecoder)   r   r   rQ   r   rG   r   r   r   r	   )r3   r   r   r   tracker_componentsr:   tracker_file_datas          r"   rk   rk     s    : 	WW'//3::7Ci$33Y5J5J$999;O;O   #224F"--/D"))6
 .Br!   )N)r   
__future__r   r   r   r   collectionsr   r+   r'   re   rK   rS   gslib.exceptionr   gslib.tracker_filer	   r
   gslib.utils.constantsr   r   objectr   r<   r1   rc   ri   rp   rk   r   r!   r"   <module>r}      s    H & %  ' "    
  ,E &24LM 6 97x'>F0RP& EI	PJ :>,Cr!   