
    0                         d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlZddl	Z	ddl
Z
ddlZddlZddlmZ dd	lmZmZ dd
lmZ  edd      Z G d de      Zd Zd Zd ZddZ	 ddZ	 ddZy)zAHelper functions for composite upload tracker file functionality.    )absolute_import)print_function)division)unicode_literals)
namedtupleN)CommandException)WriteJsonDataToTrackerFile#RaiseUnwritableTrackerFileException)UTF8ObjectFromTrackerzobject_name generationc                   $    e Zd ZdZdZdZdZdZdZy)_CompositeUploadTrackerEntryz7Enum class for composite upload tracker file JSON keys.
componentscomponent_namecomponent_generationencryption_key_sha256prefixN)	__name__
__module____qualname____doc__COMPONENTS_LISTCOMPONENT_NAMECOMPONENT_GENERATION
ENC_SHA256PREFIX     .platform/gsutil/gslib/parallel_tracker_file.pyr   r   &   s    ? /#./&*&r   r   c                    d}d}g }d}	 t        | d      }|j                         }t        j                  |      }|t        j
                     }|t        j                     }|t        j                     D ]?  }|j                  t        |t        j                     |t        j                                  A 	 |r|j)                          	 |||fS # t        $ rD}	|	j                  t        j                  k7  r|j                  d| |	j                          Y d}	~	`d}	~	wt"        t$        f$ r}	d}t'              \  }}Y d}	~	d}	~	ww xY w# |r|j)                          w w xY w)a  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   ReadParallelUploadTrackerFiler9   /   sS   , .&,)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
  sB   B,C 6E 	E:DE E)D>9E >EE Ec                     | j                  d      dd }d}g }|r[|d   }d}|t        |      dz
  k  rC||   ||dz      }}|sd}|j                  t        ||             |dz  }|t        |      dz
  k  rC||fS )at  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   )r5   old_tracker_datar   r3   iname
generations          r   r.   r.   k   s     "''-cr2&a F	A
c"#a'
',Q/1A!a%1HZt
  !24!DE1fa c"#a'
' %	&&r   c
                    t         j                  rJt        |t              r|j	                  t
              }t        |t              r|j	                  t
              }|r||k7  r	 |j                  d|        g }
|D ]4  }|j                         }|j                  |_        |j                  |_	        6 |j                  ||
|	t        j                  j                  |j                  j                         dg fS ||fS #  |D cg c]  }|j                   nc c}w }}|j                  ddj!                  |             Y dg fS xY w)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_namerD   ApplygslibcommandDummyArgCheckerParallelOverrideReasonSPEEDjoin)r0   existing_enc_sha256existing_prefixr3   current_enc_key_sha256
bucket_urlcommand_objr1   delete_funcdelete_exc_handlercomponents_to_deleter7   urlcomponent_namess                 r   $ValidateParallelCompositeTrackerDatar`      sR   > 	WW%s+/66t<(#.5<<TB,0FF&kk /	0
  *) #//"-- +
 


mm33'2'I'I'O'O  Q& ":
.	//	& 2E1DI)

1Do  kkB
))O
$& ":s   #BC: :E D)Ec                 ^    t        t        j                  dd      t        |       z   dz        S )aN  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(	 )rK   randomrandinthashr   s    r   GenerateComponentObjectPrefixrf      s1     
~~a&.C)DDN
P Pr   c           	          |5  t        | |      \  }}}||k7  rt        d|d|d|j                        |g}||z   }	t        | ||	|       ddd       y# 1 sw Y   yxY w)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 re   N)r9   r   rN   WriteParallelUploadTrackerFile)
r0   tracker_file_lockr7   r1   r   existing_enc_key_sha256r   r3   newly_completed_componentscompleted_componentss
             r   )WriteComponentToParallelUploadTrackerFilerm      s      :	F$f"77 #$9  "# #
 #,.1KK"#4#)#79NP s   AAA c                 ~   t         j                  r!t        |t              r|j	                  d      }g }|D ]G  }|j                  t        j                  |j                  t        j                  |j                  i       I t        j                  |t        j                  |t        j                  |i}t        | |       y)a  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)rH   rI   rJ   bytesdecoder&   r   r   rN   r   rD   r   r   r   r	   )r0   r   r   r   tracker_componentsr7   tracker_file_datas          r   rh   rh     s    : 	WW'/3::7Ci$33Y5J5J$999;O;O   #224F"--/D"))6
 .0ABr   )N)r   
__future__r   r   r   r   collectionsr   r(   r$   rb   rH   rP   gslib.exceptionr   gslib.tracker_filer	   r
   gslib.utils.constantsr   r   objectr   r9   r.   r`   rf   rm   rh   r   r   r   <module>rz      s    H & %  ' "    
  ,E &24LM 6 97x'>F0RP& EI	PJ :>,Cr   