3
O6b              &   @   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Zd dlZd dl	m
ZmZmZ d dlmZ d dlmZmZmZ d dlmZ d dlmZmZmZmZ d dlmZ d dlm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( d d	l)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 d d
l4m5Z5 d dl6m7Z7 d dl8m9Z9 d dl:m;Z< d dl=m>Z>m?Z? d dl@mAZAmBZB d dlCmDZD d dlEmFZF d dlGmHZH d dlImJZJ d dlKmLZL y$d dlMmMZMmNZNmOZOmPZP dd ZQW n eRk
r   dd ZQY nX dZSdZTdZUejdkryd dlVZWW n eRk
r   d dlWZWY nX dd ZXy6eWjYeWjZdZ[eXe[d d!Z\eXe[d"d#Z]W dQ R X W n e^k
rx   d!Z\d#Z]Y nX d$d% Z_nd&d' Z`d(d% Z_ed)ed\d,efgfgZaejjbd-r&ejcdd. d]k rd1jdd2d3 eje D Zfnejg Zfed4ejg fd*effd5ejh fd,eji fgead6< nNejd7krned4ejg fd*ejg fd5ejh fd,ejj d  fgead6< nejdkred4ejg fd*d1jdejg eji ffd5ejh fd,d8jdejk d9d/ fgead6< nejjbd:rejl d^ \ZfZmZned4effd*effd5enfd,emfgead6< nbejoejg eji ejp Zqed4ejg fd*d1jdd;d3 eqdd. D fd5ejh fd,eqd. fgead6< ejr jbd<rd1jdejr d=jdeesejtd>d=jdeesejc fead?< npejjbd:r
d1jdejr d=jdeesejcd@d1jdejg eji f fead?< n$d1jdejr d=jdeesejcfead?< dAjudB dCZvd_dDdEZwG dFdG dGexZydHdI ZzdJdK Z{G dLdM dMexZ|G dNdO dOexZ}dPdQ Z~dRdS ZG dTdU dUe3ZG dVdW dWexZG dXdY dYexZG dZd[ d[ZdS )`    N)SSLErrorHAS_SNIIPADDR_SAFE)DEFAULT_CODEC_OPTIONS)imap
itervalues_unicode)SON)authhelpersthread_util__version__)_validate_session_write_concern)	MAX_BSON_SIZEMAX_IDLE_TIME_SECMAX_MESSAGE_SIZEMAX_POOL_SIZEMAX_WIRE_VERSIONMAX_WRITE_BATCH_SIZEMIN_POOL_SIZEORDERED_TYPESWAIT_QUEUE_TIMEOUT)
AutoReconnectCertificateErrorConnectionFailureConfigurationErrorInvalidOperationDocumentTooLargeNetworkTimeoutNotPrimaryErrorOperationFailurePyMongoError)HelloCompat)is_ip_address)IsMaster)time)ConnectionCheckOutFailedReasonConnectionClosedReason)commandreceive_message)ReadPreference)_add_to_command)SERVER_TYPE)SocketChecker)match_hostname)fcntlF_GETFDF_SETFD
FD_CLOEXECc             C   s   t | t}t | t|tB  dS )z8Set the close-on-exec flag on the given file descriptor.N)r/   r0   r1   r2   )fdflags r5   K/var/www/html/sandeepIITI/myenv/lib/python3.6/site-packages/pymongo/pool.py_set_non_inheritable_non_atomicG   s    
r7   c             C   s   dS )z6Dummy function for platforms that don't provide fcntl.Nr5   )dummyr5   r5   r6   r7   O   s    x   
   	   win32c             C   s6   yt j| |\}}t|S  ttfk
r0   |S X d S )N)winregQueryValueExintOSError
ValueError)keynamedefaultvalue_r5   r5   r6   _query]   s
    rG   z2SYSTEM\CurrentControlSet\Services\Tcpip\ParametersZKeepAliveTimei m ZKeepAliveIntervali  c             C   sD   t ttd }t ttd }|tk s,|tk r@| jtjd||f d S )Ni     )min_WINDOWS_TCP_IDLE_MS_MAX_TCP_KEEPIDLE_WINDOWS_TCP_INTERVAL_MS_MAX_TCP_KEEPINTVLZioctlsocketZSIO_KEEPALIVE_VALS)sockZidle_msZinterval_msr5   r5   r6   _set_keepalive_timess   s    
rP   c             C   sZ   t t|rVtt|}y*| jtj|}||kr<| jtj|| W n tjk
rT   Y nX d S )N)hasattrrN   getattr
getsockoptIPPROTO_TCP
setsockopterror)rO   Z
tcp_optionZ	max_valueZsockoptrD   r5   r5   r6   _set_tcp_option|   s    

rW   c             C   s(   t | dt t | dt t | dt d S )NTCP_KEEPIDLETCP_KEEPINTVLTCP_KEEPCNT)rW   rK   rM   _MAX_TCP_KEEPCNT)rO   r5   r5   r6   rP      s    driverrC   PyMongoversionlinux          c             C   s   g | ]}|r|qS r5   r5   ).0partr5   r5   r6   
<listcomp>   s    rf   typearchitectureosdarwin-rH   javac             C   s   g | ]}|r|qS r5   r5   )rd   re   r5   r5   r6   rf      s    PyPy.z(Python %s)platformz(%s)ZfooidnaFc             C   sz   | \}}|dk	r d|||f }nd||f }|r8|| }t |tjrNt|n(t |trndt|krnt|nt|dS )z9Convert a socket.error to ConnectionFailure and raise it.Nz	%s:%d: %sz%s: %sz	timed out)
isinstancerN   timeoutr   	_SSLErrorstrr   )addressrV   Z
msg_prefixhostportmsgr5   r5   r6   _raise_connection_failure   s    

ry   c               @   s  e Zd Zd:ZeeeddeddddddddddfddZe	dd Z
e	dd Ze	dd Ze	dd Ze	dd Ze	d d! Ze	d"d# Ze	d$d% Ze	d&d' Ze	d(d) Ze	d*d+ Ze	d,d- Ze	d.d/ Ze	d0d1 Ze	d2d3 Ze	d4d5 Ze	d6d7 Ze	d8d9 ZdS );PoolOptions__max_pool_size__min_pool_size__max_idle_time_seconds__connect_timeout__socket_timeout__wait_queue_timeout__wait_queue_multiple__ssl_context__ssl_match_hostname__socket_keepalive__event_listeners	__appname__driver
__metadata__compression_settings__server_api__load_balancedNTc             C   s   || _ || _|| _|| _|| _|| _|| _|| _|	| _|
| _	|| _
|| _|| _|| _|| _|| _tjt| _|r~d|i| jd< |r|jrdtd d |jf | jd d< |jrdtd d |jf | jd d< |jrdtd |jf | jd< d S )NrC   Zapplicationz%s|%sr\   r^   ro   )_PoolOptions__max_pool_size_PoolOptions__min_pool_size#_PoolOptions__max_idle_time_seconds_PoolOptions__connect_timeout_PoolOptions__socket_timeout _PoolOptions__wait_queue_timeout!_PoolOptions__wait_queue_multiple_PoolOptions__ssl_context _PoolOptions__ssl_match_hostname_PoolOptions__socket_keepalive_PoolOptions__event_listeners_PoolOptions__appname_PoolOptions__driver"_PoolOptions__compression_settings_PoolOptions__server_api_PoolOptions__load_balancedcopydeepcopy	_METADATA_PoolOptions__metadatarC   r^   ro   )selfmax_pool_sizemin_pool_sizemax_idle_time_secondsconnect_timeoutsocket_timeoutwait_queue_timeoutwait_queue_multiplessl_contextssl_match_hostnamesocket_keepaliveevent_listenersappnamer\   compression_settings
server_apiload_balancedr5   r5   r6   __init__  s:    	
zPoolOptions.__init__c             C   s`   i }| j tkr| j |d< | jtkr,| j|d< | jtkrD| jd |d< | jtkr\| jd |d< |S )zqThe non-default options this pool was created with.

        Added for CMAP's :class:`PoolCreatedEvent`.
        ZmaxPoolSizeZminPoolSizei  ZmaxIdleTimeMSZwaitQueueTimeoutMS)r   r   r   r   r   r   r   r   )r   optsr5   r5   r6   non_default_options4  s    





zPoolOptions.non_default_optionsc             C   s   | j S )aQ  The maximum allowable number of concurrent connections to each
        connected server. Requests to a server will block if there are
        `maxPoolSize` outstanding connections to the requested server.
        Defaults to 100. Cannot be 0.

        When a server's pool has reached `max_pool_size`, operations for that
        server block waiting for a socket to be returned to the pool. If
        ``waitQueueTimeoutMS`` is set, a blocked operation will raise
        :exc:`~pymongo.errors.ConnectionFailure` after a timeout.
        By default ``waitQueueTimeoutMS`` is not set.
        )r   )r   r5   r5   r6   r   E  s    zPoolOptions.max_pool_sizec             C   s   | j S )zThe minimum required number of concurrent connections that the pool
        will maintain to each connected server. Default is 0.
        )r   )r   r5   r5   r6   r   T  s    zPoolOptions.min_pool_sizec             C   s   | j S )zThe maximum number of seconds that a connection can remain
        idle in the pool before being removed and replaced. Defaults to
        `None` (no limit).
        )r   )r   r5   r5   r6   r   [  s    z!PoolOptions.max_idle_time_secondsc             C   s   | j S )zGHow long a connection can take to be opened before timing out.
        )r   )r   r5   r5   r6   r   c  s    zPoolOptions.connect_timeoutc             C   s   | j S )zKHow long a send or receive on a socket can take before timing out.
        )r   )r   r5   r5   r6   r   i  s    zPoolOptions.socket_timeoutc             C   s   | j S )zhHow long a thread will wait for a socket from the pool if the pool
        has no free sockets.
        )r   )r   r5   r5   r6   r   o  s    zPoolOptions.wait_queue_timeoutc             C   s   | j S )ztMultiplied by max_pool_size to give the number of threads allowed
        to wait for a socket at one time.
        )r   )r   r5   r5   r6   r   v  s    zPoolOptions.wait_queue_multiplec             C   s   | j S )z(An SSLContext instance or None.
        )r   )r   r5   r5   r6   r   }  s    zPoolOptions.ssl_contextc             C   s   | j S )zCCall ssl.match_hostname if cert_reqs is not ssl.CERT_NONE.
        )r   )r   r5   r5   r6   r     s    zPoolOptions.ssl_match_hostnamec             C   s   | j S )zZWhether to send periodic messages to determine if a connection
        is closed.
        )r   )r   r5   r5   r6   r     s    zPoolOptions.socket_keepalivec             C   s   | j S )z;An instance of pymongo.monitoring._EventListeners.
        )r   )r   r5   r5   r6   r     s    zPoolOptions.event_listenersc             C   s   | j S )zJThe application name, for sending with hello in server handshake.
        )r   )r   r5   r5   r6   r     s    zPoolOptions.appnamec             C   s   | j S )zFDriver name and version, for sending with hello in handshake.
        )r   )r   r5   r5   r6   r\     s    zPoolOptions.driverc             C   s   | j S )N)r   )r   r5   r5   r6   r     s    z PoolOptions.compression_settingsc             C   s
   | j j S )zLA dict of metadata about the application, driver, os, and platform.
        )r   r   )r   r5   r5   r6   metadata  s    zPoolOptions.metadatac             C   s   | j S )z0A pymongo.server_api.ServerApi or None.
        )r   )r   r5   r5   r6   r     s    zPoolOptions.server_apic             C   s   | j S )z?True if this Pool is configured in load balanced mode.
        )r   )r   r5   r5   r6   r     s    zPoolOptions.load_balanced)r{   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   )__name__
__module____qualname__	__slots__r   r   r   r   r   propertyr   r   r   r   r   r   r   r   r   r   r   r   r   r\   r   r   r   r   r5   r5   r5   r6   rz      sD         (rz   c             C   s.   | r*x$| j  D ]}|jdkr|jr|S qW dS )zDReturn one credential that needs mechanism negotiation, if any.
    DEFAULTN)valuesZ	mechanismusername)all_credentialscredsr5   r5   r6   _negotiate_creds  s
    r   c             C   s,   | r(t | dkr(tt| }tjj|S dS )zAReturn the _AuthContext to use for speculative auth, if any.
    rH   N)lennextr   r
   Z_AuthContextZfrom_credentials)r   r   r5   r5   r6   _speculative_context  s    r   c               @   s(   e Zd Zdd Zdd Zedd ZdS )_CancellationContextc             C   s
   d| _ d S )NF)
_cancelled)r   r5   r5   r6   r     s    z_CancellationContext.__init__c             C   s
   d| _ dS )zCancel this context.TN)r   )r   r5   r5   r6   cancel  s    z_CancellationContext.cancelc             C   s   | j S )zWas cancel called?)r   )r   r5   r5   r6   	cancelled  s    z_CancellationContext.cancelledN)r   r   r   r   r   r   r   r5   r5   r5   r6   r     s   r   c               @   s&  e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdAddZ	dd Z
dd ZdejedddddddddddddfddZdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 Zd5d6 Zd7d8 Z d9d: Z!d;d< Z"d=d> Z#d?d@ Z$dS )B
SocketInfozStore a socket with some metadata.

    :Parameters:
      - `sock`: a raw socket object
      - `pool`: a Pool instance
      - `address`: the server's (host, port)
      - `id`: the id of this socket in it's pool
    c             C   s   t j|| _|| _|| _|| _t | _d| _t	 | _
d| _d| _t| _t| _t| _t| _d| _d | _d| _d| _|jj| _|j| _|jj| _d | _t | _ i | _!i | _"|j#| _$| j$j% | _&d| _'d | _(|j)st* | _(|j| _d| _+d | _,d| _-d| _.d| _/d S )NF)0weakrefrefpool_refrO   ru   idsetauthsetclosed_timelast_checkin_timeperformed_handshakeis_writabler   max_wire_versionr   max_bson_sizer   max_message_sizer   max_write_batch_sizesupports_sessionshello_ok	is_mongosop_msg_enabledr   r   	listenersenabled_for_cmapr   compression_contextr-   socket_checkernegotiated_mechanismsauth_ctxgenpool_genget_overall
generationreadycancel_context	handshaker   more_to_come
service_id
pinned_txnpinned_cursoractive)r   rO   poolru   r   r5   r5   r6   r     sH    

zSocketInfo.__init__c             C   s   d| _ | j std S )NT)r   r   AssertionError)r   r5   r5   r6   pin_txn  s    zSocketInfo.pin_txnc             C   s   d| _ | j std S )NT)r   r   r   )r   r5   r5   r6   
pin_cursor  s    zSocketInfo.pin_cursorc             C   s(   | j  }|r|j|  n| jtj d S )N)r   return_socketclose_socketr'   STALE)r   r   r5   r5   r6   unpin  s    zSocketInfo.unpinc             C   s4   | j js| jrttjdfgS ttjdfdgS d S )NrH   helloOkT)r   T)r   r   r   r	   r"   ZCMDZ
LEGACY_CMD)r   r5   r5   r6   	hello_cmd!  s    zSocketInfo.hello_cmdNc             C   s   | j d d d |S )N)_hello)r   r   r5   r5   r6   hello'  s    zSocketInfo.helloc             C   s&  | j  }| j }d}|rNd| _| jj|d< | jr<| jj|d< | jjrd|d< n@|d k	r||d< t|d |d< d}| jjr| j	j
| jj|  | jd	kr|d k	r||d
< t|}|r|jd |j |d< t|}	|	r|	j |d< | jd|d|d}
| jjotr|
jdi jd}|
jd| | jjs4|
jdd  t|
|d}|j| _|j| _|j| _|j| _|j| _|jd k	| _|j| _|jtj k| _!|r| jr| jj"|j}|| _#|jd	k| _$|r|j%| j&|< |	r|	j'| |	j( r|	| j)|	j*< | jjr"|j+s
t,d|j+| _+| j-j| j+| _.|S )NFTclientcompressionZloadBalancedZtopologyVersioni  ZmaxAwaitTimeMS   z$clusterTimern   ZsaslSupportedMechsZspeculativeAuthenticateZadmin)publish_eventsexhaust_allowedZ	processId	serviceId)	awaitablez`Driver attempted to initialize in load balancing mode, but the server does not support this mode)/r   r   r   r   r   Zcompressorsr   r?   r   rO   
settimeoutr   r   sourcer   r   Zspeculate_commandr(   _MOCK_SERVICE_IDget
setdefaultpopr$   r   r   r   r   Zlogical_session_timeout_minutesr   r   Zserver_typer,   ZMongosr   Zget_compression_contextr   r   Zsasl_supported_mechsr   parse_responseZspeculate_succeededr   credentialsr   r   r   r   )r   Zcluster_timeZtopology_versionZheartbeat_frequencyr   cmdZperforming_handshaker   r   r   docZ
process_idr   ctxr5   r5   r6   r   *  sv    





zSocketInfo._helloc             C   sH   | j d }|j| _|j }|d }tj|| j | jjsD|jdd  |S )Nr   r   )	r)   r   Zunpack_responser   _check_command_responser   r   r   r  )r   replyZunpacked_docsZresponse_docr5   r5   r6   _next_replyr  s    
zSocketInfo._next_replyFTc             C   s  | j || t||
}t|ts(t|}|	rR| jdk rR|	j rRtd|	j| jf |
dkpf|
j	pf|dksptd| jdkr|
r|
j
 r|
j|d< n| jdk r|dk	rtd| j| |r|j||||  | j||| |r| jnd}|
o|
j	 }| jr| j| y@t| |||| j||||||| j||| j|	||| j| j|||dS  ttfk
r`    Y n. tk
r } z| j| W Y dd}~X nX dS )	aN  Execute a command or raise an error.

        :Parameters:
          - `dbname`: name of the database on which to run the command
          - `spec`: a command document as a dict, SON, or mapping object
          - `secondary_ok`: whether to set the secondaryOkay wire protocol bit
          - `read_preference`: a read preference
          - `codec_options`: a CodecOptions instance
          - `check`: raise OperationFailure if there are errors
          - `allowable_errors`: errors to ignore if `check` is True
          - `check_keys`: if True, check `spec` for invalid keys
          - `read_concern`: The read concern for this command.
          - `write_concern`: The write concern for this command.
          - `parse_write_concern_error`: Whether to parse the
            ``writeConcernError`` field in the command response.
          - `collation`: The collation for this command.
          - `session`: optional ClientSession instance.
          - `client`: optional MongoClient for gossipping $clusterTime.
          - `retryable_write`: True if this command is a retryable write.
          - `publish_events`: Should we publish events for this command?
          - `user_fields` (optional): Response fields that should be decoded
            using the TypeDecoders from codec_options, passed to
            bson._decode_all_selective.
           zDread concern level of %s is not valid with a max wire version of %d.Nz3Collation is unsupported for unacknowledged writes.rb   ZwriteConcernz5Must be connected to MongoDB 3.4+ to use a collation.)parse_write_concern_error	collationZcompression_ctxZ
use_op_msgunacknowledgeduser_fieldsr   )validate_sessionr   rq   r   r	   r   Zok_for_legacyr   levelZacknowledgedZis_server_defaultdocumentadd_server_apiZ	_apply_tosend_cluster_timer   r   _raise_if_not_writabler(   r   ru   r   r   r    r   BaseExceptionry   )r   ZdbnamespecZsecondary_okZread_preferenceZcodec_optionscheckZallowable_errorsZ
check_keysZread_concernZwrite_concernr  r  sessionr   Zretryable_writer   r  r   r   r  rV   r5   r5   r6   r(   }  s\    &






zSocketInfo.commandc             C   sh   | j dk	r&|| j kr&td|| j f y| jj| W n, tk
rb } z| j| W Y dd}~X nX dS )z}Send a raw BSON message or raise ConnectionFailure.

        If a network exception is raised, the socket is closed.
        NzfBSON document too large (%d bytes) - the connected server supports BSON document sizes up to %d bytes.)r   r   rO   sendallr  ry   )r   messagemax_doc_sizerV   r5   r5   r6   send_message  s    

zSocketInfo.send_messagec             C   s@   yt | || jS  tk
r: } z| j| W Y dd}~X nX dS )zzReceive a raw BSON message or raise ConnectionFailure.

        If any exception is raised, the socket is closed.
        N)r)   r   r  ry   )r   
request_idrV   r5   r5   r6   r)     s    zSocketInfo.receive_messagec             C   s"   |r| j  rtddddddS )z^Raise NotPrimaryError on unacknowledged write if this socket is not
        writable.
        znot primaryr   i{'  )okerrmsgcodeN)r   r   )r   r  r5   r5   r6   r    s    z!SocketInfo._raise_if_not_writablec             C   s<   | j |  | j|| |r8| j|}tj|j | jS dS )a  Send OP_INSERT, etc., optionally returning response as a dict.

        Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `request_id`: an int.
          - `msg`: bytes, an OP_INSERT, OP_UPDATE, or OP_DELETE message,
            perhaps with a getlasterror command appended.
          - `max_doc_size`: size in bytes of the largest document in `msg`.
          - `with_last_error`: True if a getlasterror command is appended.
        N)r  r  r)   r   Z_check_gle_responsecommand_responser   )r   r   rx   r  Zwith_last_errorr  r5   r5   r6   legacy_write  s    

zSocketInfo.legacy_writec             C   s0   | j |d | j|}|j }tj|| j |S )zSend "insert" etc. command, returning response as a dict.

        Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `request_id`: an int.
          - `msg`: bytes, the command message.
        r   )r  r)   r$  r   r
  r   )r   r   rx   r  resultr5   r5   r6   write_command  s
    	
zSocketInfo.write_commandc             C   s   |s
| j rhtt|}| j j }x*|| D ]}tj|j|  | j j| q*W x|| D ]}| j| qVW | j	sd| _	| j
r| jj| j| j dS )a   Update this socket's authentication.

        Log in or out to bring this socket's credentials up to date with
        those provided. Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `all_credentials`: dict, maps auth source to MongoCredential.
        TN)r   r   r   r   r
   Zlogoutr   discardauthenticater   r   r   Zpublish_connection_readyru   r   )r   r   cachedr   r  r5   r5   r6   
check_auth!  s    	

zSocketInfo.check_authc             C   s8   t j||  | jj| | jj|d | jj|d dS )zLog in to the server and store these credentials in `authset`.

        Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `credentials`: A MongoCredential.
        N)r
   r)  r   addr   r  r   )r   r  r5   r5   r6   r)  =  s    zSocketInfo.authenticatec             C   s.   |r*|j |k	rtd|j| jkr*tddS )zValidate this session before use with client.

        Raises error if this session is logged in as a different user or
        the client is not the one that created the session.
        z9Can only use session with the MongoClient that started itzBCannot use session after authenticating with different credentialsN)Z_clientr   Z_authsetr   )r   r   r  r5   r5   r6   r  K  s    
zSocketInfo.validate_sessionc             C   s4   | j r
dS | j  |r0| jr0| jj| j| j| dS )z$Close this connection with a reason.N)r   _close_socketr   r   publish_connection_closedru   r   )r   reasonr5   r5   r6   r   [  s    
zSocketInfo.close_socketc             C   sH   | j r
dS d| _ | jr | jj  y| jj  W n tk
rB   Y nX dS )zClose this connection.NT)r   r   r   rO   close	Exception)r   r5   r5   r6   r-  d  s    
zSocketInfo._close_socketc             C   s   | j j| jS )z?Return True if we know socket has been closed, False otherwise.)r   socket_closedrO   )r   r5   r5   r6   r2  r  s    zSocketInfo.socket_closedc             C   s   | j dkr|r|j|| dS )z$Add cluster time for MongoDB >= 3.6.r   N)r   Z_send_cluster_time)r   r(   r  r   r5   r5   r6   r  v  s    zSocketInfo.send_cluster_timec             C   s   | j jrt|| j j dS )zAdd server_api parameters.N)r   r   r+   )r   r(   r5   r5   r6   r  {  s    zSocketInfo.add_server_apic             C   s   t  | _d S )N)r   r   )r   r5   r5   r6   update_last_checkin_time  s    z#SocketInfo.update_last_checkin_timec             C   s
   || _ d S )N)r   )r   r   r5   r5   r6   update_is_writable  s    zSocketInfo.update_is_writablec             C   s   t  | j S )z9Seconds since this socket was last checked into its pool.)r   r   )r   r5   r5   r6   idle_time_seconds  s    zSocketInfo.idle_time_secondsc             C   s@   | j rd }ntj}| j| t|tttfr:t| j	| n d S )N)
r   r'   ERRORr   rq   IOErrorr@   rs   ry   ru   )r   rV   r/  r5   r5   r6   ry     s    
z$SocketInfo._raise_connection_failurec             C   s   | j |j kS )N)rO   )r   otherr5   r5   r6   __eq__  s    zSocketInfo.__eq__c             C   s
   | |k S )Nr5   )r   r8  r5   r5   r6   __ne__  s    zSocketInfo.__ne__c             C   s
   t | jS )N)hashrO   )r   r5   r5   r6   __hash__  s    zSocketInfo.__hash__c             C   s"   dt | j| jrdpdt| f S )NzSocketInfo(%s)%s at %sz CLOSED )reprrO   r   r   )r   r5   r5   r6   __repr__  s    zSocketInfo.__repr__)N)%r   r   r   __doc__r   r   r   r   r   r   r   r  r*   ZPRIMARYr   r(   r  r)   r  r%  r'  r+  r)  r  r   r-  r2  r  r  r3  r4  r5  ry   r9  r:  r<  r?  r5   r5   r5   r6   r     sX   /
HN
		r   c          !   C   s  | \}}|j drlttds$tdtjtj}t|j  y|j| |S  tjk
rj   |j	   Y nX tj
}tjr|dkrtj}d} xtj|||tjD ]}|\}}	}
}}ytj||	ttddB |
}W n$ tjk
r   tj||	|
}Y nX t|j  yP|jtjtjd |j|j |jtjtj|j |jrFt| |j| |S  tjk
r } z|}|j	  W Y dd}~X qX qW |dk	r|n
tjd	dS )
zGiven (host, port) and PoolOptions, connect and return a socket object.

    Can raise socket.error.

    This is a modified version of create_connection from CPython >= 2.7.
    z.sockAF_UNIXz-UNIX-sockets are not supported on this system	localhostNSOCK_CLOEXECr   rH   zgetaddrinfo failed)endswithrQ   rN   r   rA  r7   filenoconnectrV   r0  AF_INEThas_ipv6	AF_UNSPECgetaddrinfoSOCK_STREAMrR   rU   rT   TCP_NODELAYr   r   
SOL_SOCKETSO_KEEPALIVEr   rP   )ru   optionsrv   rw   rO   familyerrresafsocktypeprotor8   saer5   r5   r6   _create_connection  sN    




rX  c             C   s  t | |}|j}|dk	r| d }y0trDt| s4trD|j||d}n
|j|}W nX tk
rn   |j   Y n< tt	t
fk
r } z|j  t| |d W Y dd}~X nX |jrt|dd r|jryt|j |d W n tk
r   |j   Y nX |j|j |S )zGiven (host, port) and PoolOptions, return a configured socket.

    Can raise socket.error, ConnectionFailure, or CertificateError.

    Sets socket's SSL and timeout options.
    Nr   )server_hostnamezSSL handshake failed: check_hostnameF)hostname)rX  r   	_HAVE_SNIr#   _IPADDR_SAFEwrap_socketr   r0  r7  r@   rs   ry   verify_moderR   r   r.   getpeercertr   r   )ru   rO  rO   r   rv   excr5   r5   r6   _configured_socket  s0    
rb  c               @   s   e Zd ZdZdS )_PoolClosedErrorzZInternal error raised when a thread tries to get a connection from a
    closed pool.
    N)r   r   r   r@  r5   r5   r5   r6   rc  +  s   rc  c               @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )_PoolGenerationc             C   s   t jt| _d| _d S )Nr   )collectionsdefaultdictr?   _generations_generation)r   r5   r5   r6   r   3  s    z_PoolGeneration.__init__c             C   s   |dkr| j S | j| S )z,Get the generation for the given service_id.N)rh  rg  )r   r   r5   r5   r6   r  9  s    z_PoolGeneration.getc             C   s   | j S )z"Get the Pool's overall generation.)rh  )r   r5   r5   r6   r   ?  s    z_PoolGeneration.get_overallc             C   sP   |  j d7  _ |dkr:x4| jD ]}| j|  d7  < qW n| j|  d7  < dS )z2Increment the generation for the given service_id.rH   N)rh  rg  )r   r   r5   r5   r6   incC  s
    z_PoolGeneration.incc             C   s   || j |kS )z?Return if the given generation for a given service_id is stale.)r  )r   r   r   r5   r5   r6   staleL  s    z_PoolGeneration.staleN)r   r   r   r   r  r   ri  rj  r5   r5   r5   r6   rd  2  s
   	rd  c               @   s   e Zd ZdZdZdZdS )	PoolStaterH   r`   ra   N)r   r   r   ZPAUSEDZREADYZCLOSEDr5   r5   r5   r6   rk  Q  s   rk  c               @   s   e Zd ZdddZd ddZdd Zd!d	d
Zdd Zdd Zdd Z	d"ddZ
ejd#ddZdd Zdd Zdd Zdd Zdd ZdS )$PoolTc             C   s   d| _ tj | _tj | _d| _d| _d| _	d| _
t | _tj | _|| _|| _|| _| jop| jjdk	op| jjj| _| jjdks| jjdkrd}n| jj| jj }tj| jj|| _| jr| jjj| j| jj t | _d| _d| _dS )z
        :Parameters:
          - `address`: a (hostname, port) tuple
          - `options`: a PoolOptions instance
          - `handshake`: whether to call hello for each new SocketInfo
        rH   r   FN) _check_interval_secondsre  dequesockets	threadingLocklockactive_socketsnext_connection_idr   r   rd  r   ri   getpidpidru   r   r   r   r   r   r   r   Zcreate_semaphore_socket_semaphoreZpublish_pool_createdr   r   _Pool__pinned_socketsncursorsntxns)r   ru   rO  r   Zmax_waitersr5   r5   r6   r   Z  s6    	


zPool.__init__Nc       	      C   s(  | j  | jrd S | jj| tj }| j|kr<|| _d| _|d krX| jt	j
  }| _nJt	j
 }t	j
 }x.| jD ]$}|j|kr|j| qp|j| qpW |}|| _|rd| _W d Q R X | jj}|rx|D ]}|jtj qW | jr|j| j n4| jr|j| j|d x|D ]}|jtj qW d S )Nr   T)r   )rr  r   r   ri  ri   ru  rv  rs  ro  re  rn  r   appendr   r   r   r'   POOL_CLOSEDr   Zpublish_pool_closedru   Zpublish_pool_clearedr   )	r   r0  r   Znewpidro  r(  Zkeep	sock_infor   r5   r5   r6   _reset  s>    



zPool._resetc          
   C   s8   || _ | j" x| jD ]}|j| j  qW W dQ R X dS )zXUpdates the is_writable attribute on all sockets currently in the
        Pool.
        N)r   rr  ro  r4  )r   r   rN   r5   r5   r6   r4    s    zPool.update_is_writablec             C   s   | j d|d d S )NF)r0  r   )r~  )r   r   r5   r5   r6   reset  s    z
Pool.resetc             C   s   | j dd d S )NT)r0  )r~  )r   r5   r5   r6   r0    s    z
Pool.closec             C   s   | j j||S )N)r   rj  )r   r   r   r5   r5   r6   stale_generation  s    zPool.stale_generationc             C   s   | j jdk	rV| j> x6| jrJ| jd j | j jkrJ| jj }|jtj qW W dQ R X x| j  t	| j| j
 | j jkrzP W dQ R X | jjdsP zH| j|}| j. | jj |kr|jtj P | jj| W dQ R X W d| jj  X qXW dS )zRemoves stale sockets then adds new ones if pool is too small and
        has not been reset. The `reference_generation` argument specifies the
        `generation` at the point in time this operation was requested on the
        pool.
        NrH   F)r   r   rr  ro  r5  r  r   r'   IDLEr   rs  r   rw  acquirerF  r   r   r   
appendleftrelease)r   Zreference_generationr   r}  r5   r5   r6   remove_stale_sockets  s*    


zPool.remove_stale_socketsc              C   s  | j  | j}|  jd7  _W dQ R X | jj}| jrB|j| j| yt| j| j}W nX tk
r } z<| jr~|j	| j|t
j t|tttfrt| j|  W Y dd}~X nX t|| | j|}y&| jr|j| |j| _|j| W n$ tk
r   |jt
j  Y nX |S )zConnect to Mongo and return a new SocketInfo.

        Can raise ConnectionFailure or CertificateError.

        Note that the pool does not keep a reference to the socket -- you
        must call return_socket() when you're done with it.
        rH   N)rr  rt  r   r   r   Zpublish_connection_createdru   rb  r  r.  r'   r6  rq   r7  r@   rs   ry   r   r   r   r   r+  r   )r   r   Zconn_idr   rO   rV   r}  r5   r5   r6   rF    s2    
zPool.connectc       	      c   s  | j j}| jr|j| j | j|}| jr:|j| j|j y
|V  W nN   |jpV|j	}|rvt
j \}}}|j|| | r|jr| j|  Y nX |jr| j  | jj| |  jd7  _W dQ R X nF|j	r| j  | jj| |  jd7  _W dQ R X n|jr| j| dS )a$  Get a socket from the pool. Use with a "with" statement.

        Returns a :class:`SocketInfo` object wrapping a connected
        :class:`socket.socket`.

        This method should always be used in a with-statement::

            with pool.get_socket(credentials) as socket_info:
                socket_info.send_message(msg)
                data = socket_info.receive_message(op_code, request_id)

        The socket is logged in or out as needed to match ``all_credentials``
        using the correct authentication mechanism for the server's wire
        protocol version.

        Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `all_credentials`: dict, maps auth source to MongoCredential.
          - `handler` (optional): A _MongoClientErrorHandler.
        rH   N)r   r   r   Z$publish_connection_check_out_startedru   _get_socketZpublish_connection_checked_outr   r   r   sysexc_infohandler   r   rr  rx  r,  rz  ry  )	r   r   handlerr   r}  pinnedexc_typeexc_valrF   r5   r5   r6   
get_socket  s6    


zPool.get_socketc             C   sp  | j tj kr| j  | jr>| jr6| jjj| j	t
j td| jjd| jjsX| j  d}d}y| j |  jd7  _d}W dQ R X xZ|dkry | j | jj }W dQ R X W n tk
r   | j|}Y qX | j|rd}qW |j| W nv tk
rd   |r|jtj | jj  |rB| j |  jd8  _W dQ R X | jr^| jjj| j	t
j  Y nX d|_|S )z8Get or create a SocketInfo. Can raise ConnectionFailure.z?Attempted to check out a connection from closed connection poolTNFrH   ) rv  ri   ru  r  r   r   r   r   #publish_connection_check_out_failedru   r&   r|  rc  rw  r  r   _raise_wait_queue_timeoutrr  rs  ro  popleft
IndexErrorrF  	_perishedr+  r  r   r'   r6  r  Z
CONN_ERRORr   )r   r   r}  Zincrementedr5   r5   r6   r  R  sN    


zPool._get_socketc             C   s>  |j }|j}d|_d|_ d|_| jj| | jj}| jrH|j| j	|j
 | jtj kr`| j  n| jrt|jtj nr|jr| jr|j| j	|j
tj nP| jD | j|j|jr|jtj n |j  |j| j | jj| W dQ R X | jj   | j> |r|  j!d8  _!n|r"|  j"d8  _"|  j#d8  _#W dQ R X dS )zReturn the socket to the pool, or if it's closed discard it.

        :Parameters:
          - `sock_info`: The socket to check into the pool.
        FNrH   )$r   r   r   rx  r(  r   r   r   Zpublish_connection_checked_inru   r   rv  ri   ru  r  r   r   r'   r|  r.  r6  rr  r  r   r   r   r3  r4  r   ro  r  rw  r  rz  ry  rs  )r   r}  Ztxncursorr   r5   r5   r6   r     s@    


zPool.return_socketc             C   s   |j  }| jjdk	r0|| jjkr0|jtj dS | jdk	rfd| jksN|| jkrf|j rf|jtj dS | j	|j
|jr|jtj dS dS )a  Return True and close the connection if it is "perished".

        This side-effecty function checks if this socket has been idle for
        for longer than the max idle time, or if the socket has been closed by
        some external network error, or if the socket's generation is outdated.

        Checking sockets lets us avoid seeing *some*
        :class:`~pymongo.errors.AutoReconnect` exceptions on server
        hiccups, etc. We only check if the socket was closed by an external
        error if it has been > 1 second since the socket was checked into the
        pool, to keep performance reasonable - we can't avoid AutoReconnects
        completely anyway.
        NTr   F)r5  r   r   r   r'   r  rm  r2  r6  r  r   r   r   )r   r}  r5  r5   r5   r6   r    s    


zPool._perishedc             C   sv   | j j}| jr|j| jtj | j jrZ| j| j	 | j
 }td| j j| j	| j
|| j jf td| j j| j jf d S )NzTimeout waiting for connection from the connection pool. maxPoolSize: %s, connections in use by cursors: %s, connections in use by transactions: %s, connections in use by other operations: %s, wait_queue_timeout: %szgTimed out while checking out a connection from connection pool. maxPoolSize: %s, wait_queue_timeout: %s)r   r   r   r  ru   r&   TIMEOUTr   rs  ry  rz  r   r   r   )r   r   Z	other_opsr5   r5   r6   r    s    zPool._raise_wait_queue_timeoutc             C   s   x| j D ]}|jd  qW d S )N)ro  r   )r   r}  r5   r5   r6   __del__  s    zPool.__del__)T)N)N)N)N)r   r   r   r   r~  r4  r  r0  r  r  rF  
contextlibcontextmanagerr  r  r   r  r  r  r5   r5   r5   r6   rl  Y  s   
7
)	
#
)9:."rl  )rC   r]   )ra   rb   r  )N)r  r   ri   ro   rN   r  rp  re  r   Zpymongo.ssl_supportr   rs   r   r\  r   r]  Zbsonr   Zbson.py3compatr   r   r   Zbson.sonr	   Zpymongor
   r   r   r   Zpymongo.client_sessionr   Zpymongo.commonr   r   r   r   r   r   r   r   r   Zpymongo.errorsr   r   r   r   r   r   r   r   r    r!   Zpymongo.hello_compatr"   Zpymongo._ipaddressr#   Zpymongo.ismasterr$   Zpymongo.monotonicr%   r   Zpymongo.monitoringr&   r'   Zpymongo.networkr(   r)   Zpymongo.read_preferencesr*   Zpymongo.server_apir+   Zpymongo.server_typer,   Zpymongo.socket_checkerr-   Zpymongo.ssl_match_hostnamer.   r/   r0   r1   r2   r7   ImportErrorrK   rM   r[   _winregr=   rG   OpenKeyHKEY_LOCAL_MACHINErB   rJ   rL   r@   rP   rW   r   
startswithversion_infojoinlinux_distribution_namesystemmachiner  mac_ver	win32_verjava_ver_verZ_archsystem_aliasr^   Z_aliasedpython_implementationrt   pypy_version_infoencoder  ry   objectrz   r   r   r   r   rX  rb  rc  rd  rk  rl  r5   r5   r5   r6   <module>   s   ,	0



	







$

 $

 @
	   _E0