
    ϪfA                     ~    d Z ddlmZ ddlmZmZ  G d de      Z G d d      Z G d d	      Z	 G d
 d      Z
d	dgZy)zg
An asynchronous mapping to U{DB-API
2.0<http://www.python.org/topics/database/DatabaseAPI-2.0.html>}.
    )threads)logreflectc                       e Zd ZdZy)ConnectionLostzb
    This exception means that a db connection has been lost.  Client code may
    try again.
    N)__name__
__module____qualname____doc__     ;/usr/lib/python3/dist-packages/twisted/enterprise/adbapi.pyr   r      s    r   r   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)
Connectiona  
    A wrapper for a DB-API connection instance.

    The wrapper passes almost everything to the wrapped connection and so has
    the same API. However, the L{Connection} knows about its pool and also
    handle reconnecting should when the real connection dies.
    c                 @    || _         d | _        | j                          y N)_pool_connection	reconnect)selfpools     r   __init__zConnection.__init__   s    
r   c                      y r   r   r   s    r   closezConnection.close$   s     	r   c                 l   | j                   j                  s| j                  j                          y 	 | j                  j                          | j                  j	                         }|j                  | j                   j                         |j                          | j                  j                          y # t        $ r t        j                  d d       Y nw xY w| j                   j                  | j                         | j                   j                  rt        j                  d       t               )NRollback failedzConnection lost.)r   r   r   rollbackcursorexecutegood_sqlr   commitBaseExceptionr   err
disconnectnoisymsgr   )r   curss     r   r   zConnection.rollback.   s    zz##%%'	-%%'##**,DLL,,-JJL##% 	-GGD+,	- 	

d../::GG&'s   BB7 7CCc                     | j                   %| j                  j                  | j                          | j                  j                         | _         y r   )r   r   r%   connectr   s    r   r   zConnection.reconnectD   s;    'JJ!!$"2"23::--/r   c                 .    t        | j                  |      S r   )getattrr   r   names     r   __getattr__zConnection.__getattr__I   s    t''..r   N)	r   r	   r
   r   r   r   r   r   r/   r   r   r   r   r      s     
,0
/r   r   c                   2    e Zd ZdZdZd Zd Zd Zd Zd Z	y)Transactiona  
    A lightweight wrapper for a DB-API 'cursor' object.

    Relays attribute access to the DB cursor. That is, you can call
    C{execute()}, C{fetchall()}, etc., and they will be called on the
    underlying DB-API cursor object. Attributes will also be retrieved from
    there.
    Nc                 @    || _         || _        | j                          y r   )r   r   reopen)r   r   
connections      r   r   zTransaction.__init__Y   s    
%r   c                 J    | j                   }d | _         |j                          y r   )_cursorr   )r   r6   s     r   r   zTransaction.close^   s    ,,r   c                    | j                   | j                          	 | j                  j                         | _         y # t        $ r0 | j
                  j                  s t        j                  d d       Y nw xY w| j
                  j                  rt        j                  d       | j                          | j                  j                         | _         y )NzCursor creation failedzConnection lost, reconnecting)r6   r   r   r   r#   r   r   r   r$   r&   r'   r   s    r   r3   zTransaction.reopenc   s    <<#JJL	8++224DL 	8::''67		8 ::GG34''..0s   > 6A76A7c                 F    | j                   j                          d | _        y r   )r   r   r6   r   s    r   r   zTransaction.reconnectv   s    ""$r   c                 .    t        | j                  |      S r   )r,   r6   r-   s     r   r/   zTransaction.__getattr__z   s    t||T**r   )
r   r	   r
   r   r6   r   r   r3   r   r/   r   r   r   r1   r1   M   s'     G

1&+r   r1   c                       e Zd ZdZdj	                         ZdZdZdZdZ	dZ
dZdZdZeZeZdZd Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$y)ConnectionPoola  
    Represent a pool of connections to a DB-API 2.0 compliant database.

    @ivar connectionFactory: factory for connections, default to L{Connection}.
    @type connectionFactory: any callable.

    @ivar transactionFactory: factory for transactions, default to
        L{Transaction}.
    @type transactionFactory: any callable

    @ivar shutdownID: L{None} or a handle on the shutdown event trigger which
        will be used to stop the connection pool workers when the reactor
        stops.

    @ivar _reactor: The reactor which will be used to schedule startup and
        shutdown events.
    @type _reactor: L{IReactorCore} provider
    z-min max name noisy openfun reconnect good_sqlF      Nzselect 1c                 :   || _         t        j                  |      | _        t	        | j                  dd      dk7  rt        j                  d       t	        | j                  dd      dk  rt        j                  d       |j                  d	d      }|dd
lm	} || _
        || _        || _        | j                  D ]  }d| }||v st        | |||          ||= ! t        | j                  | j                         | _        t!        | j                  | j                         | _        i | _        ddlm}m} |j*                  | _        |j/                  | j                  | j                         | _        | j                  j1                  | j2                        | _        y)a  
        Create a new L{ConnectionPool}.

        Any positional or keyword arguments other than those documented here
        are passed to the DB-API object when connecting. Use these arguments to
        pass database names, usernames, passwords, etc.

        @param dbapiName: an import string to use to obtain a DB-API compatible
            module (e.g. C{'pyPgSQL.PgSQL'})

        @keyword cp_min: the minimum number of connections in pool (default 3)

        @keyword cp_max: the maximum number of connections in pool (default 5)

        @keyword cp_noisy: generate informational log messages during operation
            (default C{False})

        @keyword cp_openfun: a callback invoked after every C{connect()} on the
            underlying DB-API object. The callback is passed a new DB-API
            connection object. This callback can setup per-connection state
            such as charset, timezone, etc.

        @keyword cp_reconnect: detect connections which have failed and reconnect
            (default C{False}). Failed connections may result in
            L{ConnectionLost} exceptions, which indicate the query may need to
            be re-sent.

        @keyword cp_good_sql: an sql query which should always succeed and change
            no state (default C{'select 1'})

        @keyword cp_reactor: use this reactor instead of the global reactor
            (added in Twisted 10.2).
        @type cp_reactor: L{IReactorCore} provider
        apilevelNz2.0z'DB API module not DB API 2.0 compliant.threadsafetyr      z+DB API module not sufficiently thread-safe.
cp_reactor)reactorcp_)
threadable
threadpool)	dbapiNamer   namedModuledbapir,   r   r'   poptwisted.internetrC   _reactorconnargsconnkwCP_ARGSsetattrminmaxconnectionstwisted.pythonrE   rF   getThreadIDthreadID
ThreadPoolcallWhenRunning_startstartID)	r   rG   rM   rN   rC   argcpArgrE   rF   s	            r   r   zConnectionPool.__init__   sK   F #((3
4::z40E9GG=>4::~q1A5GGAB**\40?0 << 	"C#KEc6%=15M		" txx*txx*  	:"..$//$((C}}44T[[Ar   c                 0    d | _         | j                         S r   )rZ   startr   s    r   rY   zConnectionPool._start   s    zz|r   c                     | j                   sN| j                  j                          | j                  j	                  dd| j
                        | _        d| _         yy)z
        Start the connection pool.

        If you are using the reactor normally, this function does *not*
        need to be called.
        duringshutdownTN)runningrF   r^   rL   addSystemEventTrigger
finalClose
shutdownIDr   s    r   r^   zConnectionPool.start   sJ     ||OO!!#"mmAA*dooDO  DL r   c                 v    t        j                  | j                  | j                  | j                  |g|i |S )a  
        Execute a function with a database connection and return the result.

        @param func: A callable object of one argument which will be executed
            in a thread with a connection from the pool. It will be passed as
            its first argument a L{Connection} instance (whose interface is
            mostly identical to that of a connection object for your DB-API
            module of choice), and its results will be returned as a
            L{Deferred}. If the method raises an exception the transaction will
            be rolled back. Otherwise, the transaction will be committed.
            B{Note} that this function is B{not} run in the main thread: it
            must be threadsafe.

        @param args: positional arguments to be passed to func

        @param kw: keyword arguments to be passed to func

        @return: a L{Deferred} which will fire the return value of
            C{func(Transaction(...), *args, **kw)}, or a
            L{twisted.python.failure.Failure}.
        )r   deferToThreadPoolrL   rF   _runWithConnection)r   funcargskws       r   runWithConnectionz ConnectionPool.runWithConnection   s>    , ((MM4??D,C,CT
LP
TV
 	
r   c                     | j                  |       }	  ||g|i |}|j                          |S # t        $ r8 	 |j                           # t        $ r t	        j
                  d d       Y  w xY ww xY wNr   )connectionFactoryr"   r#   r   r   r$   )r   ri   rj   rk   connresults         r   rh   z!ConnectionPool._runWithConnection  s~    %%d+		$,,,FKKMM 	1  ! 1/01	s,   1 	A2AA2A.+A2-A..A2c                 v    t        j                  | j                  | j                  | j                  |g|i |S )a  
        Interact with the database and return the result.

        The 'interaction' is a callable object which will be executed in a
        thread using a pooled connection. It will be passed an L{Transaction}
        object as an argument (whose interface is identical to that of the
        database cursor for your DB-API module of choice), and its results will
        be returned as a L{Deferred}. If running the method raises an
        exception, the transaction will be rolled back. If the method returns a
        value, the transaction will be committed.

        NOTE that the function you pass is *not* run in the main thread: you
        may have to worry about thread-safety in the function you pass to this
        if it tries to use non-local objects.

        @param interaction: a callable object whose first argument is an
            L{adbapi.Transaction}.

        @param args: additional positional arguments to be passed to
            interaction

        @param kw: keyword arguments to be passed to interaction

        @return: a Deferred which will fire the return value of
            C{interaction(Transaction(...), *args, **kw)}, or a
            L{twisted.python.failure.Failure}.
        )r   rg   rL   rF   _runInteraction)r   interactionrj   rk   s       r   runInteractionzConnectionPool.runInteraction$  sE    8 ((MMOO  	

 
 
 	
r   c                 B     | j                   | j                  g|i |S )aY  
        Execute an SQL query and return the result.

        A DB-API cursor which will be invoked with C{cursor.execute(*args,
        **kw)}. The exact nature of the arguments will depend on the specific
        flavor of DB-API being used, but the first argument in C{*args} be an
        SQL statement. The result of a subsequent C{cursor.fetchall()} will be
        fired to the L{Deferred} which is returned. If either the 'execute' or
        'fetchall' methods raise an exception, the transaction will be rolled
        back and a L{twisted.python.failure.Failure} returned.

        The C{*args} and C{**kw} arguments will be passed to the DB-API
        cursor's 'execute' method.

        @return: a L{Deferred} which will fire the return value of a DB-API
            cursor's 'fetchall' method, or a L{twisted.python.failure.Failure}.
        )ru   	_runQueryr   rj   rk   s      r   runQueryzConnectionPool.runQueryI  s%    $ #t""4>>?D?B??r   c                 B     | j                   | j                  g|i |S )aK  
        Execute an SQL query and return L{None}.

        A DB-API cursor which will be invoked with C{cursor.execute(*args,
        **kw)}. The exact nature of the arguments will depend on the specific
        flavor of DB-API being used, but the first argument in C{*args} will be
        an SQL statement. This method will not attempt to fetch any results
        from the query and is thus suitable for C{INSERT}, C{DELETE}, and other
        SQL statements which do not return values. If the 'execute' method
        raises an exception, the transaction will be rolled back and a
        L{Failure} returned.

        The C{*args} and C{*kw} arguments will be passed to the DB-API cursor's
        'execute' method.

        @return: a L{Deferred} which will fire with L{None} or a
            L{twisted.python.failure.Failure}.
        )ru   _runOperationrx   s      r   runOperationzConnectionPool.runOperation]  s'    & #t""4#5#5CCCCr   c                    | j                   r,| j                  j                  | j                          d| _         | j                  r,| j                  j                  | j                         d| _        | j	                          y)zC
        Close all pool connections and shutdown the pool.
        N)re   rL   removeSystemEventTriggerrZ   rd   r   s    r   r   zConnectionPool.closer  sV     ??MM224??C"DO<<MM224<<@DLr   c                     d| _         | j                  j                          d| _        | j                  j                         D ]  }| j                  |        | j                  j                          y)zE
        This should only be called by the shutdown trigger.
        NF)re   rF   stoprb   rS   values_closeclearr   rp   s     r   rd   zConnectionPool.finalClose~  s^     $$++- 	DKK	 r   c                 t   | j                         }| j                  j                  |      }|| j                  r"t	        j
                  d| j                           | j                  j                  | j                  i | j                  }| j                  | j                  |       || j                  |<   |S )a  
        Return a database connection when one becomes available.

        This method blocks and should be run in a thread from the internal
        threadpool. Don't call this method directly from non-threaded code.
        Using this method outside the external threadpool may exceed the
        maximum number of connections in the pool.

        @return: a database connection from the pool.
        zadbapi connecting: )rV   rS   getr&   r   r'   rG   rI   r*   rM   rN   openfun)r   tidrp   s      r   r*   zConnectionPool.connect  s     mmo##C(<zz-dnn-=>?%4::%%t}}DDD||'T"$(DS!r   c                     | j                         }|| j                  j                  |      urt        d      || j	                  |       | j                  |= yy)a  
        Disconnect a database connection associated with this pool.

        Note: This function should only be used by the same thread which called
        L{ConnectionPool.connect}. As with C{connect}, this function is not
        used in normal non-threaded Twisted code.
        zwrong connection for threadN)rV   rS   r   	Exceptionr   )r   rp   r   s      r   r%   zConnectionPool.disconnect  sY     mmot''++C009::KK  % r   c                     | j                   r"t        j                  d| j                          	 |j	                          y # t
        $ r t        j                  d d       Y y w xY w)Nzadbapi closing: zConnection close failed)r&   r   r'   rG   r   r#   r$   r   s     r   r   zConnectionPool._close  sN    ::GG&t~~&678	5JJL 	5GGD34	5s   A A#"A#c                 .   | j                  |       }| j                  | |      }	  ||g|i |}|j                          |j                          |S # t        $ r8 	 |j                           # t        $ r t        j                  d d       Y  w xY ww xY wrn   )ro   transactionFactoryr   r"   r#   r   r   r$   )r   rt   rj   rk   rp   transrq   s          r   rs   zConnectionPool._runInteraction  s    %%d+''d3
	 444FKKMKKMM 	1  ! 1/01	s/   -A 	BA.-B.BBBBc                 F     |j                   |i | |j                         S r   )r    fetchallr   r   rj   rk   s       r   rw   zConnectionPool._runQuery  s"    t"r"~~r   c                 (     |j                   |i | y r   )r    r   s       r   r{   zConnectionPool._runOperation  s    t"r"r   c           	          | j                   | j                  | j                  | j                  | j                  | j
                  | j                  | j                  dS )NrG   rQ   rR   r&   r   r!   rM   rN   r   r   s    r   __getstate__zConnectionPool.__getstate__  sD    8888ZZkk	
 		
r   c                 z    || _          | j                  | j                  g| j                  i | j                   y r   )__dict__r   rG   rM   rN   )r   states     r   __setstate__zConnectionPool.__setstate__  s-    dnnDt}}DDr   )%r   r	   r
   r   splitrO   r&   rQ   rR   r.   r   r   r!   rb   r   ro   r1   r   re   r   rY   r^   rl   rh   ru   ry   r|   r   rd   r*   r%   r   rs   rw   r{   r   r   r   r   r   r;   r;   ~   s    & >CCEGE
C
CDGIHG"$ JEBN 
4#
J@(D*
	!.&5 #

Er   r;   N)r   rK   r   rT   r   r   r   r   r   r1   r;   __all__r   r   r   <module>r      sP   
 % 'Y 4/ 4/n.+ .+b]E ]E@ *
+r   