
    Ϫf$                        d Z ddlmZ ddlmZ ddlmZmZ ddlmZ  G d d      Z	 G d d	e      Z
 ee
       G d
 d             Z G d de      Z G d de      Z G d dej                        Z G d de      Z G d d      Zy)a  
Hierarchical Token Bucket traffic shaping.

Patterned after U{Martin Devera's Hierarchical Token Bucket traffic
shaper for the Linux kernel<http://luxik.cdi.cz/~devik/qos/htb/>}.

@seealso: U{HTB Linux queuing discipline manual - user guide
  <http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm>}
@seealso: U{Token Bucket Filter in Linux Advanced Routing & Traffic Control
    HOWTO<http://lartc.org/howto/lartc.qdisc.classless.html#AEN682>}
    )time)Optional)	Interfaceimplementer)pcpc                   R    e Zd ZU dZdZee   ed<   dZee   ed<   dZ	d	dZ
d Zd Zy)
Bucketa  
    Implementation of a Token bucket.

    A bucket can hold a certain number of tokens and it drains over time.

    @cvar maxburst: The maximum number of tokens that the bucket can
        hold at any given time. If this is L{None}, the bucket has
        an infinite size.
    @type maxburst: C{int}
    @cvar rate: The rate at which the bucket drains, in number
        of tokens per second. If the rate is L{None}, the bucket
        drains instantaneously.
    @type rate: C{int}
    Nmaxburstrater   c                 >    d| _         || _        t               | _        y)a(  
        Create a L{Bucket} that may have a parent L{Bucket}.

        @param parentBucket: If a parent Bucket is specified,
            all L{add} and L{drip} operations on this L{Bucket}
            will be applied on the parent L{Bucket} as well.
        @type parentBucket: L{Bucket}
        r   N)contentparentBucketr   lastDrip)selfr   s     7/usr/lib/python3/dist-packages/twisted/protocols/htb.py__init__zBucket.__init__3   s     (    c                    | j                          | j                  |}n#t        || j                  | j                  z
        }| j                  | j                  j                  |      }| xj                  |z  c_        |S )at  
        Adds tokens to the L{Bucket} and its C{parentBucket}.

        This will add as many of the C{amount} tokens as will fit into both
        this L{Bucket} and its C{parentBucket}.

        @param amount: The number of tokens to try to add.
        @type amount: C{int}

        @returns: The number of tokens that actually fit.
        @returntype: C{int}
        )dripr
   minr   r   add)r   amount	allowables      r   r   z
Bucket.add@   sk     			== IFDMMDLL$@AI())--i8I	!r   c                 .   | j                   | j                   j                          | j                  d| _        nMt	               }|| j
                  z
  }|| j                  z  }t        d| j                  |z
        | _        || _        | j                  dk(  S )z
        Let some of the bucket drain.

        The L{Bucket} drains at the rate specified by the class
        variable C{rate}.

        @returns: C{True} if the bucket is empty after this drip.
        @returntype: C{bool}
        r   )r   r   r   r   r   r   max)r   now	deltaTimedeltaTokenss       r   r   zBucket.dripX   s     (""$99DL&Cdmm+I#dii/Kq$,,"<=DLDM||q  r   N)__name__
__module____qualname____doc__r
   r   int__annotations__r   	_refcountr   r   r    r   r   r	   r	      s9     #Hhsm"D(3-I0!r   r	   c                       e Zd Zd Zy)IBucketFilterc                       y)zn
        Return a L{Bucket} corresponding to the provided parameters.

        @returntype: L{Bucket}
        Nr'   )
somethingssome_kws     r   getBucketForzIBucketFilter.getBucketForq   s    r   N)r    r!   r"   r-   r'   r   r   r)   r)   p   s    r   r)   c                   D    e Zd ZU dZeZdZee   e	d<   ddZ
d Zd Zd Zy)	HierarchicalBucketFilterz
    Filter things into buckets that can be nested.

    @cvar bucketFactory: Class of buckets to make.
    @type bucketFactory: L{Bucket}
    @cvar sweepInterval: Seconds between sweeping out the bucket cache.
    @type sweepInterval: C{int}
    NsweepIntervalc                 >    i | _         || _        t               | _        y r   )bucketsparentFilterr   	lastSweep)r   r3   s     r   r   z!HierarchicalBucketFilter.__init__   s    (r   c                    | j                   4t               | j                  z
  | j                   kD  r| j                          | j                  r! | j                  j
                  | g|i |}nd} | j                  |i |}| j                  j                  |      }| | j                  |      }|| j                  |<   |S )z
        Find or create a L{Bucket} corresponding to the provided parameters.

        Any parameters are passed on to L{getBucketKey}, from them it
        decides which bucket you get.

        @returntype: L{Bucket}
        N)
r0   r   r4   sweepr3   r-   getBucketKeyr2   getbucketFactory)r   akwr   keybuckets         r   r-   z%HierarchicalBucketFilter.getBucketFor   s     *Vdnn$(:(::JJL94,,99$IIbILLd)b)!!#&>''5F &DLLr   c                      y)a%  
        Construct a key based on the input parameters to choose a L{Bucket}.

        The default implementation returns the same key for all
        arguments. Override this method to provide L{Bucket} selection.

        @returns: Something to be used as a key in the bucket cache.
        Nr'   )r   r:   r;   s      r   r7   z%HierarchicalBucketFilter.getBucketKey   s     r   c                     | j                   j                         D ]5  \  }}|j                         }|j                  dk(  s&|s)| j                   |= 7 t	               | _        y)z'
        Remove empty buckets.
        r   N)r2   itemsr   r&   r   r4   )r   r<   r=   bucket_is_emptys       r   r6   zHierarchicalBucketFilter.sweep   sV      <<--/ 	&KC$kkmO  A%?LL%	&
 r   r   )r    r!   r"   r#   r	   r9   r0   r   r$   r%   r   r-   r7   r6   r'   r   r   r/   r/   y   s0     M#'M8C=' 
4		 r   r/   c                       e Zd ZdZdZd Zy)FilterByHostzF
    A Hierarchical Bucket filter with a L{Bucket} for each host.
    i  c                 (    |j                         d   S N   )getPeerr   	transports     r   r7   zFilterByHost.getBucketKey         "1%%r   Nr    r!   r"   r#   r0   r7   r'   r   r   rC   rC      s     M&r   rC   c                       e Zd ZdZdZd Zy)FilterByServerzI
    A Hierarchical Bucket filter with a L{Bucket} for each service.
    Nc                 (    |j                         d   S )N   )getHostrH   s     r   r7   zFilterByServer.getBucketKey   rJ   r   rK   r'   r   r   rM   rM      s     M&r   rM   c                   &    e Zd ZdZdZd Zd Zd Zy)ShapedConsumerzL
    Wraps a C{Consumer} and shapes the rate at which it receives data.
    Fc                     t         j                  j                  | |       || _        | j                  xj                  dz  c_        y rE   )r   ProducerConsumerProxyr   r=   r&   )r   consumerr=   s      r   r   zShapedConsumer.__init__   s4    !!**4:"r   c                     | j                   j                  t        |            }t        j                  j                  | |d |       S r   )r=   r   lenr   rT   _writeSomeData)r   datar   s      r   rX   zShapedConsumer._writeSomeData   s9    
 T+((77d7FmLLr   c                     t         j                  j                  |        | j                  xj                  dz  c_        y rE   )r   rT   stopProducingr=   r&   )r   s    r   r[   zShapedConsumer.stopProducing   s+    !!//5"r   N)r    r!   r"   r#   iAmStreamingr   rX   r[   r'   r   r   rR   rR      s     L#
M#r   rR   c                       e Zd ZdZdZd Zy)ShapedTransportaR  
    Wraps a C{Transport} and shapes the rate at which it receives data.

    This is a L{ShapedConsumer} with a little bit of magic to provide for
    the case where the consumer it wraps is also a C{Transport} and people
    will be attempting to access attributes this does not proxy as a
    C{Consumer} (e.g. C{loseConnection}).
    Fc                 .    t        | j                  |      S r   )getattrrU   )r   names     r   __getattr__zShapedTransport.__getattr__   s     t}}d++r   N)r    r!   r"   r#   r\   rb   r'   r   r   r^   r^      s     L,r   r^   c                       e Zd ZdZd Zd Zy)ShapedProtocolFactorya  
    Dispense C{Protocols} with traffic shaping on their transports.

    Usage::

        myserver = SomeFactory()
        myserver.protocol = ShapedProtocolFactory(myserver.protocol,
                                                  bucketFilter)

    Where C{SomeServerFactory} is a L{twisted.internet.protocol.Factory}, and
    C{bucketFilter} is an instance of L{HierarchicalBucketFilter}.
    c                      || _         || _        y)a  
        Tell me what to wrap and where to get buckets.

        @param protoClass: The class of C{Protocol} this will generate
          wrapped instances of.
        @type protoClass: L{Protocol<twisted.internet.interfaces.IProtocol>}
          class
        @param bucketFilter: The filter which will determine how
          traffic is shaped.
        @type bucketFilter: L{HierarchicalBucketFilter}.
        N)protocolbucketFilter)r   
protoClassrg   s      r   r   zShapedProtocolFactory.__init__  s     #(r   c                 `       j                   |i |}|j                   fd}||_        |S )z
        Make a C{Protocol} instance with a shaped transport.

        Any parameters will be passed on to the protocol's initializer.

        @returns: A C{Protocol} instance with a L{ShapedTransport}.
        c                 b    j                   j                  |       }t        | |      } |      S r   )rg   r-   r^   )rI   r=   shapedTransportorigMakeConnectionr   s      r   makeConnectionz6ShapedProtocolFactory.__call__.<locals>.makeConnection,  s0    &&33I>F-i@O%o66r   )rf   rm   )r   r:   r;   protorm   rl   s   `    @r   __call__zShapedProtocolFactory.__call__!  s:     q'B'"11	7
  .r   N)r    r!   r"   r#   r   ro   r'   r   r   rd   rd     s    )"r   rd   N)r#   r   typingr   zope.interfacer   r   twisted.protocolsr   r	   r)   r/   rC   rM   rT   rR   r^   rd   r'   r   r   <module>rs      s   
    1 !O! O!dI  ]@  @  @ F&+ &&- &#S.. #6,n ,(0 0r   