ó
č?F[c           @   sö   d  d l  Z  d  d l 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 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 m Z d e f d	     YZ e d
  Z d e f d     YZ d S(   i’’’’N(   t   configt   storage_uri_for_key(   t   AWSAuthConnection(   t   ResumableDownloadException(   t   ResumableTransferDisposition(   t   KeyFile(   t   Keyt   ByteTranslatingCallbackHandlerc           B   s    e  Z d  Z d   Z d   Z RS(   s   
    Proxy class that translates progress callbacks made by
    boto.s3.Key.get_file(), taking into account that we're resuming
    a download.
    c         C   s   | |  _  | |  _ d  S(   N(   t
   proxied_cbt   download_start_point(   t   selfR   R	   (    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyt   __init__?   s    	c         C   s   |  j  |  j | |  d  S(   N(   R   R	   (   R
   t   total_bytes_uploadedt
   total_size(    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyt   callC   s    (   t   __name__t
   __module__t   __doc__R   R   (    (    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyR   9   s   	c         C   sw   t  |  t  r# | r# |  j   j S| s8 |  j   } n  |  j d t j  |  j   } | ss |  j | t j  n  | S(   sH   
    Returns size of file, optionally leaving fp positioned at EOF.
    i    (	   t
   isinstanceR   t   getkeyt   sizet   tellt   seekt   ost   SEEK_ENDt   SEEK_SET(   t   fpt   position_to_eoft   cur_post   cur_file_size(    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyt   get_cur_file_sizeH   s    t   ResumableDownloadHandlerc           B   sz   e  Z d  Z d Z e j e e j e j	 f Z
 d	 d	 d  Z d   Z d   Z d   Z d   Z d	 d e d	 d	 d  Z RS(
   s*   
    Handler for resumable downloads.
    i   c         C   s;   | |  _  | |  _ d |  _ | r. |  j   n  d |  _ d S(   s  
        Constructor. Instantiate once for each downloaded file.

        :type tracker_file_name: string
        :param tracker_file_name: optional file name to save tracking info
            about this download. If supplied and the current process fails
            the download, it can be retried in a new process. If called
            with an existing file containing an unexpired timestamp,
            we'll resume the transfer for this file; else we'll start a
            new resumable download.

        :type num_retries: int
        :param num_retries: the number of times we'll re-try a resumable
            download making no progress. (Count resets every time we get
            progress, so download can span many more than this number of
            retries.)
        N(   t   tracker_file_namet   num_retriest   Nonet   etag_value_for_current_downloadt   _load_tracker_file_etagR	   (   R
   R    R!   (    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyR   b   s    			c         C   sŗ   d  } z yU t |  j d  } | j   j d  |  _ t |  j  |  j k  r] d |  j GHn  Wn= t k
 r } | j	 t	 j
 k r d |  j | j f GHq n XWd  | rµ | j   n  Xd  S(   Nt   rs   
sJ   Couldn't read etag in tracker file (%s). Restarting download from scratch.sJ   Couldn't read URI tracker file (%s): %s. Restarting download from scratch.(   R"   t   openR    t   readlinet   rstripR#   t   lent   MIN_ETAG_LENt   IOErrort   errnot   ENOENTt   strerrort   close(   R
   t   ft   e(    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyR$   ~   s     c         C   s©   | j  j d  |  _ |  j s" d  Sd  } zf y* t |  j d  } | j d |  j  Wn5 t k
 r } t d |  j | j	 f t
 j   n XWd  | r¤ | j   n  Xd  S(   Ns   "'t   ws   %s
s·   Couldn't write tracker file (%s): %s.
This can happenif you're using an incorrectly configured download tool
(e.g., gsutil configured to save tracker files to an unwritable directory)(   t   etagt   stripR#   R    R"   R&   t   writeR+   R   R.   R   t   ABORTR/   (   R
   t   keyR0   R1   (    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyt   _save_tracker_info   s    	 c         C   s5   |  j  r1 t j j |  j   r1 t j |  j   n  d  S(   N(   R    R   t   patht   existst   unlink(   R
   (    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyt   _remove_tracker_fileŖ   s    	c	   
      C   s¾  t  | d t }	 |	 r|  j r|  j | j j d  k r|	 | j k r t d | j |	 t t	 |   | j f t
 j   n0 |	 | j k r² | j j j d k r® d GHn  d S| j j j d k rĻ d GHn  | j   } d |	 | j d f | d	 <t | |	  j } |	 |  _ n@ | j j j d k r1d
 GHn  |  j |  d |  _ | j d  t | t  r| j | | | | | | d d d | n" | j | | | | | | d d | j   d S(   sr   
        Attempts a resumable download.

        Raises ResumableDownloadException if any problems occur.
        R   s   "'sp   %s is larger (%d) than %s (%d).
Deleting tracker file, so if you re-try this download it will start from scratchi   s   Download complete.Ns   Resuming download.s   bytes=%d-%dt   Ranges    Starting new resumable download.i    t   override_num_retriest	   hash_algs(   R   t   TrueR#   R3   R4   R   R   t   namet   strR   R   R6   t   buckett
   connectiont   debugt   copyR   R   R	   R8   t   truncateR   t   GSKeyt   get_filet   flush(
   R
   R7   R   t   headerst   cbt   num_cbt   torrentt
   version_idR?   R   (    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyt   _attempt_resumable_downloadÆ   s<    		i
   c	         C   sŖ  | j  j j }	 | s i  } n  |  j d k rH t j d d d  |  _ n  d }
 xUt r„t |  } yH |  j	 | | | | | | | |  |  j
   |	 d k r¦ d GHn  d SWnQ|  j k
 ra} |	 d k rŽ d | j   GHn  t | t  r’| j t j k r’t | t  r9| j | | | | | | d	 d d
 | q^| j | | | | | | d	 d q’n t k
 rž} | j t j k r£|	 d k rd | j GHn    q’| j t j k rą|	 d k rŠd | j GHn  |  j
     q’|	 d k r’d | j GHq’n Xt |  | k rd }
 n
 |
 d 7}
 |
 |  j k rHt d t j   n  y | j   Wn t j k
 rln Xd |
 } |	 d k rd |
 | f GHn  t j |  qQ Wd S(   s  
        Retrieves a file from a Key
        :type key: :class:`boto.s3.key.Key` or subclass
        :param key: The Key object from which upload is to be downloaded
        
        :type fp: file
        :param fp: File pointer into which data should be downloaded
        
        :type headers: string
        :param: headers to send when retrieving the files
        
        :type cb: function
        :param cb: (optional) a callback function that will be called to report
             progress on the download.  The callback should accept two integer
             parameters, the first representing the number of bytes that have
             been successfully transmitted from the storage service and
             the second representing the total number of bytes that need
             to be transmitted.
        
        :type num_cb: int
        :param num_cb: (optional) If a callback is specified with the cb
             parameter this parameter determines the granularity of the callback
             by defining the maximum number of times the callback will be
             called during the file transfer.
             
        :type torrent: bool
        :param torrent: Flag for whether to get a torrent for the file

        :type version_id: string
        :param version_id: The version ID (optional)

        :type hash_algs: dictionary
        :param hash_algs: (optional) Dictionary of hash algorithms and
            corresponding hashing class that implements update() and digest().
            Defaults to {'md5': hashlib/md5.md5}.

        Raises ResumableDownloadException if a problem occurs during
            the transfer.
        t   BotoR!   i   i    i   s   Resumable download complete.Ns   Caught exception (%s)R>   R?   s4   Caught non-retryable ResumableDownloadException (%s)sX   Caught non-retryable ResumableDownloadException (%s); aborting and removing tracker files3   Caught ResumableDownloadException (%s) - will retryse   Too many resumable download attempts failed without progress. You might try this download again lateri   sW   Got retryable failure (%d progress-less in a row).
Sleeping %d seconds before re-trying(   RC   RD   RE   R!   R"   R    t   getintR@   R   RP   R<   t   RETRYABLE_EXCEPTIONSt   __repr__R   R+   R,   t   EPIPERH   RI   R   t   dispositionR   t   ABORT_CUR_PROCESSt   messageR6   R/   t   httplibt   IncompleteReadt   timet   sleep(   R
   R7   R   RK   RL   RM   RN   RO   R?   RE   t   progress_less_iterationst   had_file_bytes_before_attemptR1   t   sleep_time_secs(    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyRI   ß   sr    *		
!
	

N(   R   R   R   R*   RY   t   HTTPExceptionR+   t   sockett   errort   gaierrorRS   R"   R   R$   R8   R<   RP   t   FalseRI   (    (    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyR   X   s   				0	(   R,   RY   R   t   reRa   R[   t   botoR    R   t   boto.connectionR   t   boto.exceptionR   R   t   boto.s3.keyfileR   t   boto.gs.keyR   RH   t   objectR   Rd   R   R   (    (    (    sA   lib/python2.7/site-packages/boto/s3/resumable_download_handler.pyt   <module>   s   