U
    ¹êW[‹B  ã                   @   st   d Z ddlZddlmZ ddlmZmZmZ G dd„ deƒZ	G dd„ de
ƒZG d	d
„ d
ƒZG dd„ dƒZd
dgZdS )zg
An asynchronous mapping to U{DB-API
2.0<http://www.python.org/topics/database/DatabaseAPI-2.0.html>}.
é    N)Úthreads)ÚreflectÚlogÚcompatc                   @   s   e Zd ZdZdS )ÚConnectionLostzb
    This exception means that a db connection has been lost.  Client code may
    try again.
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   ú;/usr/lib/python3/dist-packages/twisted/enterprise/adbapi.pyr      s   r   c                   @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )Ú
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                 C   s   || _ d | _|  ¡  d S ©N)Ú_poolÚ_connectionÚ	reconnect)ÚselfÚpoolr   r   r   Ú__init__!   s    zConnection.__init__c                 C   s   d S r   r   ©r   r   r   r   Úclose'   s    zConnection.closec                 C   s”   | j js| j ¡  d S z:| j ¡  | j ¡ }| | j j¡ | ¡  | j ¡  W d S    t	 
d d¡ Y nX | j  | j¡ | j jrŠt	 d¡ tƒ ‚d S )NúRollback failedzConnection lost.)r   r   r   ÚrollbackÚcursorÚexecuteÚgood_sqlr   Úcommitr   ÚerrÚ
disconnectÚnoisyÚmsgr   )r   Zcursr   r   r   r   2   s     




zConnection.rollbackc                 C   s(   | j d k	r| j | j ¡ | j ¡ | _ d S r   )r   r   r   Úconnectr   r   r   r   r   I   s    
zConnection.reconnectc                 C   s   t | j|ƒS r   )Úgetattrr   ©r   Únamer   r   r   Ú__getattr__O   s    zConnection.__getattr__N)	r   r   r	   r
   r   r   r   r   r%   r   r   r   r   r      s   r   c                   @   s<   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Z	dS )Ú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                 C   s   || _ || _|  ¡  d S r   )r   r   Úreopen)r   r   Z
connectionr   r   r   r   _   s    zTransaction.__init__c                 C   s   | j }d | _ | ¡  d S r   )Ú_cursorr   )r   r(   r   r   r   r   e   s    zTransaction.closec                 C   st   | j d k	r|  ¡  z| j ¡ | _ W d S    | jjs8‚ nt d d¡ Y nX | jjr\t 	d¡ |  ¡  | j ¡ | _ d S )NzCursor creation failedzConnection lost, reconnecting)
r(   r   r   r   r   r   r   r   r   r    r   r   r   r   r'   k   s    

zTransaction.reopenc                 C   s   | j  ¡  d | _d S r   )r   r   r(   r   r   r   r   r      s    
zTransaction.reconnectc                 C   s   t | j|ƒS r   )r"   r(   r#   r   r   r   r%   „   s    zTransaction.__getattr__)
r   r   r	   r
   r(   r   r   r'   r   r%   r   r   r   r   r&   T   s   r&   c                   @   sÔ   e Zd ZdZd ¡ ZdZdZdZdZ	dZ
dZdZdZeZeZ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 d!„ Zd"d#„ Z d$d%„ Z!d&d'„ Z"d(d)„ Z#d*d+„ Z$dS ),Ú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           	      O   s  || _ t |¡| _t| jddƒdkr.t d¡ t| jddƒdk rJt d¡ | d	d¡}|dkrjdd
lm	} || _
|| _|| _| jD ],}d|f }||kr‚t| ||| ƒ ||= q‚t| j| jƒ| _t| j| jƒ| _i | _ddlm} ddlm} |j| _| | j| j¡| _| j
 | j¡| _dS )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'})

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

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

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

        @param 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.

        @param 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.

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

        @param cp_reactor: use this reactor instead of the global reactor
            (added in Twisted 10.2).
        @type cp_reactor: L{IReactorCore} provider
        ZapilevelNz2.0z'DB API module not DB API 2.0 compliant.Zthreadsafetyr   é   z+DB API module not sufficiently thread-safe.Z
cp_reactor)Úreactorzcp_%s)Ú
threadpool)Ú
threadable)Ú	dbapiNamer   ZnamedModuleÚdbapir"   r   r    ÚpopÚtwisted.internetr-   Ú_reactorÚconnargsÚconnkwÚCP_ARGSÚsetattrÚminÚmaxÚconnectionsÚtwisted.pythonr.   r/   ZgetThreadIDÚthreadIDZ
ThreadPoolZcallWhenRunningÚ_startÚstartID)	r   r0   r5   r6   r-   ÚargZcpArgr.   r/   r   r   r   r   ¯   s2    #



zConnectionPool.__init__c                 C   s   d | _ |  ¡ S r   )r?   Ústartr   r   r   r   r>   ø   s    zConnectionPool._startc                 C   s.   | j s*| j ¡  | j dd| j¡| _d| _ dS )z
        Start the connection pool.

        If you are using the reactor normally, this function does *not*
        need to be called.
        ZduringZshutdownTN)Úrunningr.   rA   r4   ZaddSystemEventTriggerÚ
finalCloseÚ
shutdownIDr   r   r   r   rA   ý   s    
  ÿzConnectionPool.startc                 O   s   t j| j| j| j|f|ž|Ž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   ÚdeferToThreadPoolr4   r.   Ú_runWithConnection)r   ÚfuncÚargsÚkwr   r   r   ÚrunWithConnection  s    þþþz ConnectionPool.runWithConnectionc           	   
   O   sz   |   | ¡}z||f|ž|Ž}| ¡  |W S    t ¡ \}}}z| ¡  W n   t d d¡ Y nX t ||¡ Y nX d S ©Nr   )	ÚconnectionFactoryr   ÚsysÚexc_infor   r   r   r   Úreraise)	r   rG   rH   rI   ÚconnÚresultÚexcTypeÚexcValueÚexcTracebackr   r   r   rF   &  s    
z!ConnectionPool._runWithConnectionc                 O   s   t j| j| j| j|f|ž|Ž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   rE   r4   r.   Ú_runInteraction)r   ÚinteractionrH   rI   r   r   r   ÚrunInteraction5  s    þþþzConnectionPool.runInteractionc                 O   s   | j | jf|ž|Ž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}.
        )rW   Ú	_runQuery©r   rH   rI   r   r   r   ÚrunQueryV  s    zConnectionPool.runQueryc                 O   s   | j | jf|ž|Ž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}.
        )rW   Ú_runOperationrY   r   r   r   ÚrunOperationk  s    zConnectionPool.runOperationc                 C   s@   | j r| j | j ¡ d| _ | jr4| j | j¡ d| _|  ¡  dS )zC
        Close all pool connections and shutdown the pool.
        N)rD   r4   ZremoveSystemEventTriggerr?   rC   r   r   r   r   r     s    zConnectionPool.closec                 C   s>   d| _ | j ¡  d| _| j ¡ D ]}|  |¡ q | j ¡  dS )zE
        This should only be called by the shutdown trigger.
        NF)rD   r.   ÚstoprB   r;   ÚvaluesÚ_closeÚclear©r   rP   r   r   r   rC   Ž  s    
zConnectionPool.finalClosec                 C   sx   |   ¡ }| j |¡}|dkrt| jrDt d| j| jp4d| jp<df ¡ | j	j
| j| jŽ}| jdkrj|  |¡ || 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.
        Nzadbapi connecting: %s %s%sÚ )r=   r;   Úgetr   r   r    r0   r5   r6   r1   r!   Úopenfun)r   ÚtidrP   r   r   r   r!   š  s    
þ


zConnectionPool.connectc                 C   s>   |   ¡ }|| j |¡k	r tdƒ‚|dk	r:|  |¡ | j|= dS )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)r=   r;   rc   Ú	Exceptionr_   )r   rP   re   r   r   r   r   ´  s    
zConnectionPool.disconnectc                 C   sB   | j rt d| jf ¡ z| ¡  W n   t d d¡ Y nX d S )Nzadbapi closing: %szConnection close failed)r   r   r    r0   r   r   ra   r   r   r   r_   Ä  s    zConnectionPool._closec           
   
   O   sŽ   |   | ¡}|  | |¡}z&||f|ž|Ž}| ¡  | ¡  |W S    t ¡ \}}}	z| ¡  W n   t d d¡ Y nX t	 
||	¡ Y nX d S rK   )rL   ÚtransactionFactoryr   r   rM   rN   r   r   r   r   rO   )
r   rV   rH   rI   rP   ÚtransrQ   rR   rS   rT   r   r   r   rU   Í  s    
zConnectionPool._runInteractionc                 O   s   |j ||Ž | ¡ S r   )r   Zfetchall©r   rh   rH   rI   r   r   r   rX   Þ  s    zConnectionPool._runQueryc                 O   s   |j ||Ž d S r   )r   ri   r   r   r   r[   ã  s    zConnectionPool._runOperationc              	   C   s&   | j | j| j| j| j| j| j| jdœS )N©r0   r9   r:   r   r   r   r5   r6   rj   r   r   r   r   Ú__getstate__ç  s    ùzConnectionPool.__getstate__c                 C   s"   || _ | j| jf| jž| jŽ d S r   )Ú__dict__r   r0   r5   r6   )r   Ústater   r   r   Ú__setstate__ò  s    zConnectionPool.__setstate__)%r   r   r	   r
   Úsplitr7   r   r9   r:   r$   rd   r   r   rB   r   rL   r&   rg   rD   r   r>   rA   rJ   rF   rW   rZ   r\   r   rC   r!   r   r_   rU   rX   r[   rk   rn   r   r   r   r   r)   ‰   s>   I!	r)   )r
   rM   r3   r   r<   r   r   r   rf   r   Úobjectr   r&   r)   Ú__all__r   r   r   r   Ú<module>   s   <5  q