
    \dc\                         d 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
 ddlmZ ddlmZmZ dZ G d	 d
e          Z G d de          Z G d de          Z G d d          Z G d dee
          Zg dZdS )ap  
Memcache client protocol. Memcached is a caching server, storing data in the
form of pairs key/value, and memcache is the protocol to talk with it.

To connect to a server, create a factory for L{MemCacheProtocol}::

    from twisted.internet import reactor, protocol
    from twisted.protocols.memcache import MemCacheProtocol, DEFAULT_PORT
    d = protocol.ClientCreator(reactor, MemCacheProtocol
        ).connectTCP("localhost", DEFAULT_PORT)
    def doSomething(proto):
        # Here you call the memcache operations
        return proto.set("mykey", "a lot of data")
    d.addCallback(doSomething)
    reactor.run()

All the operations of the memcache protocol are present, but
L{MemCacheProtocol.set} and L{MemCacheProtocol.get} are the more important.

See U{http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt} for
more information about the protocol.
    )deque)DeferredTimeoutErrorfail)LineReceiver)TimeoutMixin)log)nativeStringnetworkStringi+  c                       e Zd ZdZdS )NoSuchCommandzA
    Exception raised when a non existent command is called.
    N__name__
__module____qualname____doc__     :lib/python3.11/site-packages/twisted/protocols/memcache.pyr   r   (              r   r   c                       e Zd ZdZdS )ClientErrorz1
    Error caused by an invalid client call.
    Nr   r   r   r   r   r   .   r   r   r   c                       e Zd ZdZdS )ServerErrorz*
    Problem happening on the server.
    Nr   r   r   r   r   r   4   r   r   r   c                   $    e Zd ZdZd Zd Zd ZdS )Commanda8  
    Wrap a client action into an object, that holds the values used in the
    protocol.

    @ivar _deferred: the L{Deferred} object that will be fired when the result
        arrives.
    @type _deferred: L{Deferred}

    @ivar command: name of the command sent to the server.
    @type command: L{bytes}
    c                     || _         t                      | _        |                                D ]\  }}t	          | ||           dS )z
        Create a command.

        @param command: the name of the command.
        @type command: L{bytes}

        @param kwargs: this values will be stored as attributes of the object
            for future use
        N)commandr   	_deferreditemssetattr)selfr   kwargskvs        r   __init__zCommand.__init__G   sP     !LLNN 	  	 DAqD!Q	  	 r   c                 :    | j                             |           dS )zB
        Shortcut method to fire the underlying deferred.
        N)r   callback)r"   values     r   successzCommand.successV   s      	&&&&&r   c                 :    | j                             |           dS )z5
        Make the underlying deferred fails.
        N)r   errback)r"   errors     r   r   zCommand.fail\   s      	u%%%%%r   N)r   r   r   r   r&   r*   r   r   r   r   r   r   :   sK        
 
     ' ' '& & & & &r   r   c                      e Zd ZdZdZdZd-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d Zd.dZd.dZd Zd/dZd/dZd/d Zd/d!Z d" Z!d# Z"d$ Z#d0d%Z$d0d&Z%d' Z&d1d)Z'd* Z(d+ Z)d, Z*d(S )2MemCacheProtocola1  
    MemCache protocol: connect to a memcached server to store/retrieve values.

    @ivar persistentTimeOut: the timeout period used to wait for a response.
    @type persistentTimeOut: L{int}

    @ivar _current: current list of requests waiting for an answer from the
        server.
    @type _current: L{deque} of L{Command}

    @ivar _lenExpected: amount of data expected in raw mode, when reading for
        a value.
    @type _lenExpected: L{int}

    @ivar _getBuffer: current buffer of data, used to store temporary data
        when reading in raw mode.
    @type _getBuffer: L{list}

    @ivar _bufferLength: the total amount of bytes in C{_getBuffer}.
    @type _bufferLength: L{int}

    @ivar _disconnected: indicate if the connectionLost has been called or not.
    @type _disconnected: L{bool}
       F<   c                 r    t                      | _        d| _        d| _        d| _        |x| _        | _        dS )z
        Create the protocol.

        @param timeOut: the timeout to wait before detecting that the
            connection is dead and close it. It's expressed in seconds.
        @type timeOut: L{int}
        N)r   _current_lenExpected
_getBuffer_bufferLengthpersistentTimeOuttimeOut)r"   r8   s     r   r&   zMemCacheProtocol.__init__   s9      !077r   c                     | j         r7| j                                         }|                    |           | j         5dS dS )zW
        Cancel all the outstanding commands, making them fail with C{reason}.
        N)r3   popleftr   )r"   reasoncmds      r   _cancelCommandsz MemCacheProtocol._cancelCommands   sS     m 	-''))CHHV m 	 	 	 	 	r   c                 |    |                      t          d                     | j                                         dS )z:
        Close the connection in case of timeout.
        zConnection timeoutN)r=   r   	transportloseConnectionr"   s    r   timeoutConnectionz"MemCacheProtocol.timeoutConnection   s;     	\*>??@@@%%'''''r   c                 h    d| _         |                     |           t          j        | |           dS )z9
        Cause any outstanding commands to fail.
        TN)_disconnectedr=   r   connectionLost)r"   r;   s     r   rE   zMemCacheProtocol.connectionLost   s9     "V$$$#D&11111r   c                 r    | j         s|                     | j                   t          j        | |           dS )zA
        Override sendLine to add a timeout to response.
        N)r3   
setTimeoutr7   r   sendLine)r"   lines     r   rH   zMemCacheProtocol.sendLine   s<     } 	4OOD2333dD)))))r   c                    |                                   | j                            |           | xj        t	          |          z  c_        | j        | j        dz   k    rd                    | j                  }|d| j                 }|| j        dz   d         }|}d| _        d| _        d| _        | j        d         }|j        r(|j	        |j
                 \  }}|||f|j	        |j
        <   n||_        |                     |           dS dS )z)
        Collect data for a get.
           r   Nr   )resetTimeoutr5   appendr6   lenr4   joinr3   multiplevalues
currentKeyr)   setLineMode)r"   databufremvalr<   flagscass           r   rawDataReceivedz MemCacheProtocol.rawDataReceived   s    	t$$$c$ii'!2Q!66688DO,,D***+Ct(1,../CC $D"DO!%D-"C|   Z7
s.3S#->
3>**	S!!!!! 76r   c                 ^    | j                                                             d           dS )z?
        Manage a success response to a set operation.
        TNr3   r:   r*   rA   s    r   
cmd_STOREDzMemCacheProtocol.cmd_STORED   ,     	''-----r   c                 ^    | j                                                             d           dS )z
        Manage a specific 'not stored' response to a set operation: this is not
        an error, but some condition wasn't met.
        FNr\   rA   s    r   cmd_NOT_STOREDzMemCacheProtocol.cmd_NOT_STORED   s,    
 	''.....r   c                 v   | j                                         }|j        dk    rd|j        r:d |j                                        D             }|                    |           dS |                    |j        |j        f           dS |j        dk    rL|j        r|                    |j                   dS |                    |j        |j	        |j        f           dS |j        dk    r|                    |j                   dS t          d                    t          |j                                      )zB
        This the end token to a get or a stat operation.
           getc                 ,    i | ]\  }}||d d d         S )NrK   r   ).0keyrW   s      r   
<dictcomp>z,MemCacheProtocol.cmd_END.<locals>.<dictcomp>   s(    KKKHC#s33Q3xKKKr      gets   statsz%Unexpected END response to {} commandN)r3   r:   r   rP   rQ   r    r*   rX   r)   rY   RuntimeErrorformatr
   )r"   r<   rQ   s      r   cmd_ENDzMemCacheProtocol.cmd_END   s7    m##%%;&  | 4KK
8H8H8J8JKKKF#####SY	233333[G##| =CJ'''''SY;<<<<<[H$$KK
#####7>> --   r   c                 ^    | j                                                             d           dS )z=
        Manage error response for incr/decr/delete.
        FNr\   rA   s    r   cmd_NOT_FOUNDzMemCacheProtocol.cmd_NOT_FOUND   ,     	''.....r   c                    | j         d         }|j        dk    r|                                \  }}}d}n|                                \  }}}}t          |          | _        g | _        d| _        |j        r9||j        vrt          d          ||_
        t          |          |g|j        |<   n5|j        |k    rt          d          t          |          |_        ||_        |                                  dS )z:
        Prepare the reading a value after a get.
        r   rb   r   zUnexpected commands answer.N)r3   r   splitintr4   r5   r6   rP   keysri   rR   rQ   re   rX   rY   
setRawMode)r"   rI   r<   re   rX   lengthrY   s          r   	cmd_VALUEzMemCacheProtocol.cmd_VALUE   s     mA;&  !%CCC&*jjll#CKK< 		#("""#@AAA CN"5zz3/CJsOOw#~~"#@AAAE

CICGr   c                 f    | j         d         }|                    dd          \  }}||j        |<   dS )z-
        Reception of one stat line.
        r          N)r3   rp   rQ   )r"   rI   r<   re   rW   s        r   cmd_STATzMemCacheProtocol.cmd_STAT	  s6     mA::dA&&S
3r   c                 ^    | j                                                             |           dS )z%
        Read version token.
        Nr\   )r"   versionDatas     r   cmd_VERSIONzMemCacheProtocol.cmd_VERSION  s,     	''44444r   c                     t          j        d           | j                                        }|                    t                                 dS )z7
        A non-existent command has been sent.
        zNon-existent command sent.N)r	   errr3   r:   r   r   )r"   r<   s     r   	cmd_ERRORzMemCacheProtocol.cmd_ERROR  sD     	,---m##%%!!!!!r   c                     t          |          }t          j        d|z              | j                                        }|                    t          |                     dS )z0
        An invalid input as been sent.
        zInvalid input: N)reprr	   r~   r3   r:   r   r   r"   errTextr<   s      r   cmd_CLIENT_ERRORz!MemCacheProtocol.cmd_CLIENT_ERROR  sX     w--!G+,,,m##%%W%%&&&&&r   c                     t          |          }t          j        d|z              | j                                        }|                    t          |                     dS )z4
        An error has happened server-side.
        zServer error: N)r   r	   r~   r3   r:   r   r   r   s      r   cmd_SERVER_ERRORz!MemCacheProtocol.cmd_SERVER_ERROR(  sX     w-- 7*+++m##%%W%%&&&&&r   c                 ^    | j                                                             d           dS )z>
        A delete command has completed successfully.
        TNr\   rA   s    r   cmd_DELETEDzMemCacheProtocol.cmd_DELETED1  r^   r   c                 ^    | j                                                             d           dS )z6
        The last command has been completed.
        TNr\   rA   s    r   cmd_OKzMemCacheProtocol.cmd_OK7  r^   r   c                 ^    | j                                                             d           dS )z5
        A C{checkAndSet} update has failed.
        FNr\   rA   s    r   
cmd_EXISTSzMemCacheProtocol.cmd_EXISTS=  rn   r   c                 d   |                                   |                    dd          d         }t          | dt          |          z   d          }|=|                    dd          dd         }|r ||d                    n |             n|                    dd          }t          | dt          |          z   d          }| |             n=| j                                        }t          |          }|                    |           | j        s| 	                    d           dS dS )z8
        Receive line commands from the server.
        rw   rx   r   cmd_N   _)
rL   rp   getattrr
   replacer3   r:   rq   r*   rG   )r"   rI   tokenr<   argsrW   s         r   lineReceivedzMemCacheProtocol.lineReceivedC  s8    	

4##A&dF\%%8%88$???::dA&&qrr*D DG <<d++D$d);); ;TBBC m++--$iiC   } 	"OOD!!!!!	" 	"r   rx   c                 0    |                      d||          S )a  
        Increment the value of C{key} by given value (default to 1).
        C{key} must be consistent with an int. Return the new value.

        @param key: the key to modify.
        @type key: L{bytes}

        @param val: the value to increment.
        @type val: L{int}

        @return: a deferred with will be called back with the new value
            associated with the key (after the increment).
        @rtype: L{Deferred}
        s   incr	_incrdecrr"   re   rW   s      r   	incrementzMemCacheProtocol.increment`  s     ~~gsC000r   c                 0    |                      d||          S )a  
        Decrement the value of C{key} by given value (default to 1).
        C{key} must be consistent with an int. Return the new value, coerced to
        0 if negative.

        @param key: the key to modify.
        @type key: L{bytes}

        @param val: the value to decrement.
        @type val: L{int}

        @return: a deferred with will be called back with the new value
            associated with the key (after the decrement).
        @rtype: L{Deferred}
        s   decrr   r   s      r   	decrementzMemCacheProtocol.decrementq  s      ~~gsC000r   c                    | j         rt          t          d                    S t          |t                    s-t          t          dt          |           d                    S t          |          | j        k    rt          t          d                    S d	                    ||dt          |          fz  g          }|                     |           t          ||          }| j                            |           |j        S )z1
        Internal wrapper for incr/decr.
        not connectedInvalid type for key: , expecting bytesKey too longrw   s   %dre   )rD   r   ri   
isinstancebytesr   typerN   MAX_KEY_LENGTHrO   rq   rH   r   r3   rM   r   )r"   r<   re   rW   fullcmdcmdObjs         r   r   zMemCacheProtocol._incrdecr  s      	7_55666#u%% 	QT#YYQQQRR   s88d)))N33444))S#uC{':;<<g#&&&V$$$r   r   c                 6    |                      d||||d          S )a  
        Replace the given C{key}. It must already exist in the server.

        @param key: the key to replace.
        @type key: L{bytes}

        @param val: the new value associated with the key.
        @type val: L{bytes}

        @param flags: the flags to store with the key.
        @type flags: L{int}

        @param expireTime: if different from 0, the relative time in seconds
            when the key will be deleted from the store.
        @type expireTime: L{int}

        @return: a deferred that will fire with C{True} if the operation has
            succeeded, and C{False} with the key didn't previously exist.
        @rtype: L{Deferred}
        s   replacer   _setr"   re   rW   rX   
expireTimes        r   r   zMemCacheProtocol.replace  s     * yyS#uj#FFFr   c                 6    |                      d||||d          S )a  
        Add the given C{key}. It must not exist in the server.

        @param key: the key to add.
        @type key: L{bytes}

        @param val: the value associated with the key.
        @type val: L{bytes}

        @param flags: the flags to store with the key.
        @type flags: L{int}

        @param expireTime: if different from 0, the relative time in seconds
            when the key will be deleted from the store.
        @type expireTime: L{int}

        @return: a deferred that will fire with C{True} if the operation has
            succeeded, and C{False} with the key already exists.
        @rtype: L{Deferred}
        s   addr   r   r   s        r   addzMemCacheProtocol.add       * yyc5*cBBBr   c                 6    |                      d||||d          S )a9  
        Set the given C{key}.

        @param key: the key to set.
        @type key: L{bytes}

        @param val: the value associated with the key.
        @type val: L{bytes}

        @param flags: the flags to store with the key.
        @type flags: L{int}

        @param expireTime: if different from 0, the relative time in seconds
            when the key will be deleted from the store.
        @type expireTime: L{int}

        @return: a deferred that will fire with C{True} if the operation has
            succeeded.
        @rtype: L{Deferred}
        s   setr   r   r   s        r   setzMemCacheProtocol.set  r   r   c                 6    |                      d|||||          S )am  
        Change the content of C{key} only if the C{cas} value matches the
        current one associated with the key. Use this to store a value which
        hasn't been modified since last time you fetched it.

        @param key: The key to set.
        @type key: L{bytes}

        @param val: The value associated with the key.
        @type val: L{bytes}

        @param cas: Unique 64-bit value returned by previous call of C{get}.
        @type cas: L{bytes}

        @param flags: The flags to store with the key.
        @type flags: L{int}

        @param expireTime: If different from 0, the relative time in seconds
            when the key will be deleted from the store.
        @type expireTime: L{int}

        @return: A deferred that will fire with C{True} if the operation has
            succeeded, C{False} otherwise.
        @rtype: L{Deferred}
        s   casr   )r"   re   rW   rY   rX   r   s         r   checkAndSetzMemCacheProtocol.checkAndSet  s     4 yyc5*cBBBr   c           
         | j         rt          t          d                    S t          |t                    s-t          t          dt          |           d                    S t          |          | j        k    rt          t          d                    S t          |t                    s-t          t          dt          |           d                    S |rd|z   }t          |          }d	                    ||t          d|||fz            g          |z   }|                     |           |                     |           t          ||||          }	| j                            |	           |	j        S )	z6
        Internal wrapper for setting values.
        r   r   r   r   zInvalid type for value: rw   z%d %d %d)re   rX   rt   )rD   r   ri   r   r   r   r   rN   r   rO   r   rH   r   r3   rM   r   )
r"   r<   re   rW   rX   r   rY   rt   r   r   s
             r   r   zMemCacheProtocol._set  s     	7_55666#u%% 	QT#YYQQQRR   s88d)))N33444#u%% 	StCyySSSTT    	*CSIIc=uj&6Q)QRRS   	 	gc#U6BBBV$$$r   c                 6    |                      d||ddd          S )a  
        Append given data to the value of an existing key.

        @param key: The key to modify.
        @type key: L{bytes}

        @param val: The value to append to the current value associated with
            the key.
        @type val: L{bytes}

        @return: A deferred that will fire with C{True} if the operation has
            succeeded, C{False} otherwise.
        @rtype: L{Deferred}
        s   appendr   r   r   r   s      r   rM   zMemCacheProtocol.append  s       yyCaC888r   c                 6    |                      d||ddd          S )a  
        Prepend given data to the value of an existing key.

        @param key: The key to modify.
        @type key: L{bytes}

        @param val: The value to prepend to the current value associated with
            the key.
        @type val: L{bytes}

        @return: A deferred that will fire with C{True} if the operation has
            succeeded, C{False} otherwise.
        @rtype: L{Deferred}
        s   prependr   r   r   r   s      r   prependzMemCacheProtocol.prepend'  s       yyS#q!S999r   c                 2    |                      |g|d          S )a  
        Get the given C{key}. It doesn't support multiple keys. If
        C{withIdentifier} is set to C{True}, the command issued is a C{gets},
        that will return the current identifier associated with the value. This
        identifier has to be used when issuing C{checkAndSet} update later,
        using the corresponding method.

        @param key: The key to retrieve.
        @type key: L{bytes}

        @param withIdentifier: If set to C{True}, retrieve the current
            identifier along with the value and the flags.
        @type withIdentifier: L{bool}

        @return: A deferred that will fire with the tuple (flags, value) if
            C{withIdentifier} is C{False}, or (flags, cas identifier, value)
            if C{True}.  If the server indicates there is no value
            associated with C{key}, the returned value will be L{None} and
            the returned flags will be C{0}.
        @rtype: L{Deferred}
        F_get)r"   re   withIdentifiers      r   getzMemCacheProtocol.get9  s    , yy#666r   c                 0    |                      ||d          S )a  
        Get the given list of C{keys}.  If C{withIdentifier} is set to C{True},
        the command issued is a C{gets}, that will return the identifiers
        associated with each values. This identifier has to be used when
        issuing C{checkAndSet} update later, using the corresponding method.

        @param keys: The keys to retrieve.
        @type keys: L{list} of L{bytes}

        @param withIdentifier: If set to C{True}, retrieve the identifiers
            along with the values and the flags.
        @type withIdentifier: L{bool}

        @return: A deferred that will fire with a dictionary with the elements
            of C{keys} as keys and the tuples (flags, value) as values if
            C{withIdentifier} is C{False}, or (flags, cas identifier, value) if
            C{True}.  If the server indicates there is no value associated with
            C{key}, the returned values will be L{None} and the returned flags
            will be C{0}.
        @rtype: L{Deferred}

        @since: 9.0
        Tr   )r"   rr   r   s      r   getMultiplezMemCacheProtocol.getMultipleQ  s    0 yy~t444r   c           	         t          |          }| j        rt          t          d                    S |D ]|}t	          |t
                    s/t          t          dt          |           d                    c S t          |          | j	        k    rt          t          d                    c S }|rd}nd}d
                    |g|z             }|                     |           |r d |D             }t          |||d	
          }nt          ||d         dddd          }| j                            |           |j        S )z>
        Helper method for C{get} and C{getMultiple}.
        r   r   r   r   rg   rb   rw   c                     i | ]}|d S ))r   r   Nr   )rd   re   s     r   rf   z)MemCacheProtocol._get.<locals>.<dictcomp>  s    :::cc>:::r   T)rr   rQ   rP   r   Nr   F)re   r)   rX   rY   rP   )listrD   r   ri   r   r   r   r   rN   r   rO   rH   r   r3   rM   r   )	r"   rr   r   rP   re   r<   r   rQ   r   s	            r   r   zMemCacheProtocol._getk  sw    Dzz 	7_55666 	9 	9Cc5))  Uc U U UVV     3xx$---K7788888 . 	CCC))SEDL))g 	::T:::FStFTJJJFFaA3  F 	V$$$r   Nc                     |rd|z   }nd}| j         rt          t          d                    S |                     |           t	          di           }| j                            |           |j        S )a  
        Get some stats from the server. It will be available as a dict.

        @param arg: An optional additional string which will be sent along
            with the I{stats} command.  The interpretation of this value by
            the server is left undefined by the memcache protocol
            specification.
        @type arg: L{None} or L{bytes}

        @return: a deferred that will fire with a L{dict} of the available
            statistics.
        @rtype: L{Deferred}
        s   stats rh   r   )rQ   rD   r   ri   rH   r   r3   rM   r   )r"   argr<   r   s       r   statszMemCacheProtocol.stats  s      	c/CCC 	7_55666c"---V$$$r   c                     | j         rt          t          d                    S |                     d           t	          d          }| j                            |           |j        S )z
        Get the version of the server.

        @return: a deferred that will fire with the string value of the
            version.
        @rtype: L{Deferred}
        r   s   versionr   r"   r   s     r   versionzMemCacheProtocol.version  sc      	7_55666j!!!$$V$$$r   c                 `   | j         rt          t          d                    S t          |t                    s-t          t          dt          |           d                    S |                     d|z              t          d|          }| j	        
                    |           |j        S )a  
        Delete an existing C{key}.

        @param key: the key to delete.
        @type key: L{bytes}

        @return: a deferred that will be called back with C{True} if the key
            was successfully deleted, or C{False} if not.
        @rtype: L{Deferred}
        r   r   r   s   delete s   deleter   )rD   r   ri   r   r   r   r   rH   r   r3   rM   r   )r"   re   r   s      r   deletezMemCacheProtocol.delete  s      	7_55666#u%% 	QT#YYQQQRR   	j3&''',,,V$$$r   c                     | j         rt          t          d                    S |                     d           t	          d          }| j                            |           |j        S )z
        Flush all cached values.

        @return: a deferred that will be called back with C{True} when the
            operation has succeeded.
        @rtype: L{Deferred}
        r   s	   flush_allr   r   s     r   flushAllzMemCacheProtocol.flushAll  sc      	7_55666l###&&V$$$r   )r1   )rx   )r   r   )F)N)+r   r   r   r   r   rD   r&   r=   rB   rE   rH   rZ   r]   r`   rk   rm   ru   ry   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rM   r   r   r   r   r   r   r   r   r   r   r   r/   r/   c   s        2 NM8 8 8 8  ( ( (2 2 2* * *" " ".. . ./ / /  2/ / /  2  5 5 5" " "' ' '' ' '. . .. . ./ / /" " ":1 1 1 1"1 1 1 1$     $G G G G.C C C C.C C C C.C C C C8     >9 9 9$: : :$7 7 7 705 5 5 54     <       2          ,         r   r/   )r/   DEFAULT_PORTr   r   r   N)r   collectionsr   twisted.internet.deferr   r   r   twisted.protocols.basicr   twisted.protocols.policiesr   twisted.pythonr	   twisted.python.compatr
   r   r   	Exceptionr   r   r   r   r/   __all__r   r   r   <module>r      s  
 0       ? ? ? ? ? ? ? ? ? ? 0 0 0 0 0 0 3 3 3 3 3 3       = = = = = = = =    I       )       )   && && && && && && && &&Rq	  q	  q	  q	  q	 |\ q	  q	  q	 h  r   