
    "                         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rSSKrSSK	J
r
  SSKJr  SS	KJr   " S
 S\5      rg)z-Helper class for streaming resumable uploads.    )absolute_import)print_function)division)unicode_literalsN)CommandException)GetJsonResumableChunkSize)UTF8c                   n    \ rS rSrSrSS jr\S 5       rSS jrS r	S r
\R                  4S jrS	 rS
rg)#ResumableStreamingJsonUploadWrapper   a  Wraps an input stream in a buffer for resumable uploads.

This class takes a non-seekable input stream, buffers it, and exposes it
as a stream with limited seek capabilities such that it can be used in a
resumable JSON API upload.

max_buffer_size bytes of buffering is supported.
c                     Xl         U(       d*  U[        5       :  a  [        SU< S[        5       < S35      eX l        [        R
                  " 5       U l        SU l        SU l        SU l	        g)aZ  Initializes the wrapper.

Args:
  stream: Input stream.
  max_buffer_size: Maximum size of internal buffer; should be >= the chunk
      size of the resumable upload API to ensure that at least one full
      chunk write can be replayed in the event of a server error.
  test_small_buffer: Skip check for buffer size vs. chunk size, for testing.
z4Resumable streaming upload created with buffer size z#, JSON resumable upload chunk size z`. Buffer size must be >= JSON resumable upload chunk size to ensure that uploads can be resumed.r   N)
_orig_fpr   r   _max_buffer_sizecollectionsdeque_buffer_buffer_start_buffer_end	_position)selfstreammax_buffer_sizetest_small_buffers       3platform/gsutil/gslib/resumable_streaming_upload.py__init__,ResumableStreamingJsonUploadWrapper.__init__)   sf     M3L3N!N
 ./H/JL M M ,$$&DLDDDN    c                 0    [        U R                  SS5      $ )z<Returns the mode of the underlying file descriptor, or None.modeN)getattrr   r   s    r   r   (ResumableStreamingJsonUploadWrapper.modeC   s     4==&$//r   c                    USL =(       d    US:  nU(       a  U R                   nOUnSn/ nU R                  U R                  :  Ga)  U R                  nSnU[	        U R
                  U   5      -   U R                  :  aK  U[	        U R
                  U   5      -  nUS-  nU[	        U R
                  U   5      -   U R                  :  a  MK  X`R                  :  a  US:  a  [	        U R
                  U   5      nU R                  U-
  n	X-
  n
[        X5      nUR                  U R
                  U   XU-    5        X;-  nXh-  nUS-  nU =R                  U-  sl        X`R                  :  a  US:  a  M  U(       ai  U R                  R                  U5      n[	        U5      nU(       d  UnO"UR                  U5        SR                  U5      nU =R                  U-  sl        U$ U(       Ga  U R                  R                  U5      nU(       d  UnO"UR                  U5        SR                  U5      n[	        U5      nU(       Ga6  U =R                  U-  sl        U R
                  R                  U5        U =R                  U-  sl        SnU R                  U R                  -
  U R                   :  aa  U R
                  R                  5       nU =R                  [	        U5      -  sl        U R                  U R                  -
  U R                   :  a  Ma  U(       a`  U R                   U R                  U R                  -
  -
  nU(       a3  U R
                  R                  X* S 5        U =R                  U-  sl        U$ [        R                  (       aC  U(       a<  U Vs/ s H/  n[        U[         5      (       a  UR#                  [$        5      OUPM1     nnU(       a  SR                  U5      OSnU$ s  snf )z"Reads from the wrapped stream.

Args:
  size: The amount of bytes to read. If omitted or negative, the entire
      contents of the stream will be read and returned.

Returns:
  Bytes from the wrapped stream.
Nr   r      )r   r   r   r   lenr   minappendr   readjoinpopleft
appendleftsixPY3
isinstancestrencoder	   )r   sizeread_all_bytesbytes_remainingdatabuffered_datapos_in_bufferbuffer_index
buffer_lenoffset_from_positionbytes_available_this_buffer	read_sizenew_datadata_lenoldest_datarefill_amountbds                    r   r(   (ResumableStreamingJsonUploadWrapper.readH   sy    T\-TAXN--ooDM~~((( ((mlC\ :;;dnnL 	T\\,788 C\ :;;dnnL ,,,11Dl34
#~~=&0&G#3E	T\\,72'4() 	* 	$#)# ,,,11D"  ##D)hXhX&xx&
nn n@ K? 
##O4hX&xx&Xh	("H%H$!3!33d6K6KK,,.+


K 0
0
 !3!33d6K6KK //43C3C373E3E4F G-LL##K$@A-/ K 
 &%" ",B!4!4biio"<%   )6SXXm$3dKs   6O-c                     U R                   $ )z$Returns the current stream position.)r   r!   s    r   tell(ResumableStreamingJsonUploadWrapper.tell   s    >>r   c                     g)z/Returns true since limited seek support exists.T r!   s    r   seekable,ResumableStreamingJsonUploadWrapper.seekable   s    r   c           	      (   U[         R                  :X  aQ  XR                  :  d  XR                  :  a,  [	        SU< SU R                  < SU R                  < S35      eXl        gU[         R                  :X  a  XR                  :  a  [	        SU< SU R                  < S35      eU R                  U R                  5      (       a#   U R                  U R                  5      (       a  M#  U =R
                  U-  sl        g[	        SU< S	U< S
35      e)zSeeks on the buffered stream.

Args:
  offset: The offset to seek to; must be within the buffer bounds.
  whence: Must be os.SEEK_SET.

Raises:
  CommandException if an unsupported seek mode or position is used.
z]Unable to resume upload because of limited buffering available for streaming uploads. Offset z# was requested, but only data from z to z is buffered.zInvalid SEEK_END offset z on streaming upload. Only z can be buffered.z-Invalid seek mode on streaming upload. (mode z	, offset )N)	osSEEK_SETr   r   r   r   SEEK_ENDr   r(   )r   offsetwhences      r   seek(ResumableStreamingJsonUploadWrapper.seek   s     	$$	$1A1A(A !'(:(:D<L<L	 N O 	O n	2;;		''	' &(=(= ? @ 	@ IId++,, IId++,, nnn7=vG H Hr   c                 6    U R                   R                  5       $ )N)r   closer!   s    r   rS   )ResumableStreamingJsonUploadWrapper.close   s    ==  r   )r   r   r   r   r   r   N)F))__name__
__module____qualname____firstlineno____doc__r   propertyr   r(   rC   rG   rK   rL   rP   rS   __static_attributes__rF   r   r   r   r      sF    4 0 0cJ !# HB!r   r   )rZ   
__future__r   r   r   r   r   rK   r,   gslib.exceptionr   gslib.utils.boto_utilr   gslib.utils.constantsr	   objectr   rF   r   r   <module>rb      s6    4 & %  '  	 
 , ; &x!& x!r   