U
    @f30                     @   s  d 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 ddl	m
Z
mZ ddlmZ ddlmZmZ ddlmZmZmZmZmZmZ dd	lmZmZ dd
lmZ ddlmZ ddlm Z  e!dj"Z#dddZ$e!dj"Z%efddZ&dZ'dd Z(esdd Z)ndd Z)dS )z&Internal network layer helper methods.    N)_decode_all_selective)PY3)helpersmessage)MAX_MESSAGE_SIZE)
decompress_NO_COMPRESSION)AutoReconnectNotPrimaryErrorOperationFailureProtocolErrorNetworkTimeout_OperationCancelled)_UNPACK_REPLY_OpMsg)_is_speculative_authenticate)time)_errno_from_exceptionz<iiiiTFc           *      C   s8  t t|}|d }|rdnd}d}|}|r<|s<t||}|rj|rJ|jsj|jrZ|j|d< |rj|||  |dk	rz||d< |dk	o|j}|rt	j	
 }t||}|r| tkrd}|r|jr|jjs|j|||| }}d}|rT|rtjnd}||rtjndO }tj||||||||d\}}} }!|rt|dk	rt|!|krtt|| | n t||dd	|d|||	\}}} |dk	r| |tj krt|| |tj  |rt	j	
 | }"|j||||| jd
 t	j	
 }z~| j| |r|rd}#ddi}$nTt| |}#|#j| _|#j||d}%|%d }$|r8||$| |	rRt j!|$| j"|
|d W nx t#k
r }& zX|rt	j	
 | |" }'t$|&t%t&fr|&j'}(n
t(|&}(|j)|'|(|||| jd
  W 5 d}&~&X Y nX |r t	j	
 | |" }'|j*|'|$|||| j|d |r4|jr4|#r4|j+|#, })t-|)||d }$|$S )ad  Execute a command over the socket, or raise socket.error.

    :Parameters:
      - `sock`: a raw socket instance
      - `dbname`: name of the database on which to run the command
      - `spec`: a command document as an ordered dict type, eg SON.
      - `secondary_ok`: whether to set the secondaryOkay wire protocol bit
      - `is_mongos`: are we connected to a mongos?
      - `read_preference`: a read preference
      - `codec_options`: a CodecOptions instance
      - `session`: optional ClientSession instance.
      - `client`: optional MongoClient instance for updating $clusterTime.
      - `check`: raise OperationFailure if there are errors
      - `allowable_errors`: errors to ignore if `check` is True
      - `address`: the (host, port) of `sock`
      - `check_keys`: if True, check `spec` for invalid keys
      - `listeners`: An instance of :class:`~pymongo.monitoring.EventListeners`
      - `max_bson_size`: The maximum encoded bson size for this server
      - `read_concern`: The read concern for this command.
      - `parse_write_concern_error`: Whether to parse the ``writeConcernError``
        field in the command response.
      - `collation`: The collation for this command.
      - `compression_ctx`: optional compression Context.
      - `use_op_msg`: True if we should use OP_MSG.
      - `unacknowledged`: True if this is an unacknowledged command.
      - `user_fields` (optional): Response fields that should be decoded
        using the TypeDecoders from codec_options, passed to
        bson._decode_all_selective.
      - `exhaust_allowed`: True if we should enable OP_MSG exhaustAllowed.
    z.$cmd   r   FZreadConcernN	collation)ctx)
service_idok   )codec_optionsuser_fields)parse_write_concern_error)r   speculative_hello).nextiterr   Z_maybe_add_read_preferenceZin_transactionleveldocumentZ_update_read_concernZenabled_for_commandsdatetimenowr   lowerr   Z
_encrypterZ_bypass_auto_encryptionZencryptr   ZMORE_TO_COMEZEXHAUST_ALLOWEDZ_op_msgZ_raise_document_too_largequeryZ_COMMAND_OVERHEADZpublish_command_startr   socksendallreceive_messageZmore_to_comeZunpack_responseZ_process_responser   Z_check_command_responseZmax_wire_version	Exception
isinstancer
   r   detailsZ_convert_exceptionZpublish_command_failureZpublish_command_successZdecryptZraw_command_responser   )*	sock_infoZdbnamespecZsecondary_okZ	is_mongosZread_preferencer   sessionclientcheckZallowable_errorsaddressZ
check_keysZ	listenersZmax_bson_sizeZread_concernr   r   Zcompression_ctxZ
use_op_msgZunacknowledgedr   Zexhaust_allowednamensflagsr   origpublishstart
request_idmsgsizeZmax_doc_sizeZencoding_durationZreplyZresponse_docZunpacked_docsexcdurationZfailureZ	decrypted r>   3/tmp/pip-unpacked-wheel-gs_301nf/pymongo/network.pycommand,   s    *



                

  


   

        r@   z<iiBc                 C   s  | j  }|rt | }nd}tt| d|\}}}}|dk	rV||krVtd||f |dkrltd|f ||krtd||f |dkrtt| d|\}}}	tt| |d ||	}
nt| |d |}
zt| }W n( t	k
r   td	|t
 f Y nX ||
S )
z1Receive a raw BSON message or raise socket.error.N   z"Got response id %r but expected %rzEMessage length (%r) not longer than standard message header size (16)z?Message length (%r) is larger than server max message size (%r)i  	      zGot opcode %r but expected %r)r'   
gettimeoutr   _UNPACK_HEADER_receive_data_on_socketr   _UNPACK_COMPRESSION_HEADERr   r   KeyErrorkeys)r-   r9   Zmax_message_sizetimeoutdeadlinelength_Zresponse_toZop_codeZcompressor_iddataZunpack_replyr>   r>   r?   r)      sH    




r)   g      ?c                 C   s   | j }|r| j}t|dr,| dkr,d}n2|rHtt|t  td}nt}| jj	|d|d}|j
rltd|rtdS |rt |krtdqdS )	zABlock until at least one byte is read, or a timeout, or a cancel.pendingr   TgMbP?)readrJ   zhello cancelledNz	timed out)Zcancel_contextr'   hasattrrO   maxminr   _POLL_TIMEOUTZsocket_checkerselectZ	cancelledr   socketrJ   )r-   rK   contextr'   readablerJ   r>   r>   r?   wait_for_read   s&      rY   c              
   C   s   t |}d}|rzt| | | j|}W n> ttfk
rh } zt|tjkrVW Y q W 5 d }~X Y nX |dkrzt	d||||t
| < |t
|7 }|t
|8 }qt|S )Nr       connection closed)	bytearrayrY   r'   recvIOErrorOSErrorr   errnoEINTRr	   lenbytes)r-   rL   rK   bufichunkr<   r>   r>   r?   rF     s     
rF   c              
   C   s   t |}t|}d}||k rz"t| | | j||d  }W n> ttfk
r| } zt|tj	krjW Y q W 5 d }~X Y nX |dkrt
d||7 }q|S )Nr   r[   )r\   
memoryviewrY   r'   	recv_intor^   r_   r   r`   ra   r	   )r-   rL   rK   rd   mv
bytes_readZchunk_lengthr<   r>   r>   r?   rF     s    

)TNNFNNNFNNFFNF)*__doc__r#   r`   rV   structZbsonr   Zbson.py3compatr   Zpymongor   r   Zpymongo.commonr   Zpymongo.compression_supportr   r   Zpymongo.errorsr	   r
   r   r   r   r   Zpymongo.messager   r   Zpymongo.monitoringr   Zpymongo.monotonicr   Zpymongo.socket_checkerr   StructunpackrE   r@   rG   r)   rT   rY   rF   r>   r>   r>   r?   <module>   sL                     
 &
