U
    W¨+d¦  ã                   @   s‚   d dl Z d dlZd dlZd dlmZ dZde ZdZefdd„Zefdd	„Z	d
d„ Z
ddd„Zdd„ Zdd„ ZG dd„ deƒZdS )é    N)Úsixé   é   é'  c                 C   sh   t }|t | k r`| dt  d kr,td|  ƒ‚| d }d}||k rVt t |¡}|d7 }q8t|ƒ}n|}|S )a"  Calculate the minimum part size needed for a multipart upload.

    Glacier allows a maximum of 10,000 parts per upload.  It also
    states that the maximum archive size is 10,000 * 4 GB, which means
    the part size can range from 1MB to 4GB (provided it is one 1MB
    multiplied by a power of 2).

    This function will compute what the minimum part size must be in
    order to upload a file of size ``size_in_bytes``.

    It will first check if ``default_part_size`` is sufficient for
    a part size given the ``size_in_bytes``.  If this is not the case,
    then the smallest part size than can accomodate a file of size
    ``size_in_bytes`` will be returned.

    If the file size is greater than the maximum allowed archive
    size of 10,000 * 4GB, a ``ValueError`` will be raised.

    i   r   zFile size too large: %sé   é   )Ú	_MEGABYTEÚMAXIMUM_NUMBER_OF_PARTSÚ
ValueErrorÚmathÚldexpÚint)Zsize_in_bytesZdefault_part_sizeZ	part_sizeZmin_part_sizeÚpower© r   ú6/tmp/pip-unpacked-wheel-dlxw5sjy/boto/glacier/utils.pyÚminimum_part_size"   s    

r   c                 C   st   t t t| ƒt|ƒ ¡ƒ}g }t|ƒD ]4}|| }|d | }| t | ||… ¡ 	¡ ¡ q&|spt d¡ 	¡ gS |S )Nr   ó    )
r   r   ÚceilÚlenÚfloatÚrangeÚappendÚhashlibÚsha256Údigest)Z
bytestringÚ
chunk_sizeZchunk_countÚhashesÚiÚstartÚendr   r   r   Úchunk_hashesJ   s    r    c                 C   s’   g }|  | ¡ t|ƒdkrŠg }t|ƒdkrX| d¡}| d¡}| t || ¡ ¡ ¡ qt|ƒdkr~| d¡}| |¡ qq~q|  |¡ q|d S )z¤
    Given a hash of each 1MB chunk (from chunk_hashes) this will hash
    together adjacent hashes until it ends up with one big one. So a
    tree of hashes.
    r   r   )Úextendr   Úpopr   r   r   r   )Úfor   Z
new_hashesÚfirstÚsecondÚonlyr   r   r   Ú	tree_hashV   s    



r'   c                 C   s®   t jr"t| dƒr"d| jkr"tdƒ‚t ¡ }g }|  |¡}|r†t|t	ƒs\| 
t| ddƒpXd¡}| |¡ | t |¡ ¡ ¡ |  |¡}q8|sšt d¡ ¡ g}| ¡ tt|ƒƒfS )aÎ  Compute the linear and tree hash from a fileobj.

    This function will compute the linear/tree hash of a fileobj
    in a single pass through the fileobj.

    :param fileobj: A file like object.

    :param chunk_size: The size of the chunks to use for the tree
        hash.  This is also the buffer size used to read from
        `fileobj`.

    :rtype: tuple
    :return: A tuple of (linear_hash, tree_hash).  Both hashes
        are returned in hex.

    ÚmodeÚbz/File-like object must be opened in binary mode!ÚencodingÚ zutf-8r   )r   ÚPY3Úhasattrr(   r
   r   r   ÚreadÚ
isinstanceÚbytesÚencodeÚgetattrÚupdater   r   Ú	hexdigestÚbytes_to_hexr'   )Úfileobjr   Zlinear_hashÚchunksÚchunkr   r   r   Úcompute_hashes_from_fileobjn   s    


r9   c                 C   s
   t  | ¡S ©N)ÚbinasciiÚhexlify©Zstr_as_bytesr   r   r   r5   ”   s    r5   c                 C   s   t tt| ƒƒƒS )z²

    :type str_as_bytes: str
    :param str_as_bytes: The string for which to compute the tree hash.

    :rtype: str
    :return: The computed tree hash, returned as hex.

    )r5   r'   r    r=   r   r   r   Útree_hash_from_str˜   s    
r>   c                   @   s   e Zd Zdd„ Zdd„ ZdS )ÚResettingFileSenderc                 C   s   || _ | ¡ | _d S r:   )Ú_archiveÚtellÚ_starting_offset)ÚselfÚarchiver   r   r   Ú__init__¦   s    zResettingFileSender.__init__c              	   C   s4   z| ||| j |¡ | ¡ W ¢S | j  | j¡ X d S r:   )r@   ÚseekrB   ÚrequestÚgetresponse)rC   Ú
connectionÚmethodÚpathÚbodyÚheadersr   r   r   Ú__call__ª   s    zResettingFileSender.__call__N)Ú__name__Ú
__module__Ú__qualname__rE   rN   r   r   r   r   r?   ¥   s   r?   )r   )r   r   r;   Zboto.compatr   r   ZDEFAULT_PART_SIZEr	   r   r    r'   r9   r5   r>   Úobjectr?   r   r   r   r   Ú<module>   s   (
&