U
    
W[o$                     @   s   d Z ddlmZ ddlmZmZ ddlmZ G dd dZG dd deZeeG d	d
 d
Z	G dd de	Z
G dd de	ZG dd dejZG dd deZG dd dZdS )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)implementer	Interface)pcpc                   @   s6   e Zd ZdZdZdZdZd
ddZdd Zdd	 Z	dS )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}
    Nr   c                 C   s   d| _ || _t | _dS )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    r   7/usr/lib/python3/dist-packages/twisted/protocols/htb.py__init__1   s    	zBucket.__init__c                 C   sR   |    | jdkr|}nt|| j| j }| jdk	r@| j|}|  j|7  _|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}
        N)dripmaxburstminr   r   add)r
   amountZ	allowabler   r   r   r   ?   s    

z
Bucket.addc                 C   sb   | j dk	r| j   | jdkr&d| _n2t }|| j }|| j }td| j| | _|| _| 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}
        Nr   )r   r   rater   r   r	   max)r
   ZnowZ	deltaTimeZdeltaTokensr   r   r   r   X   s    





zBucket.drip)N)
__name__
__module____qualname____doc__r   r   	_refcountr   r   r   r   r   r   r   r      s   
r   c                   @   s   e Zd Zdd ZdS )IBucketFilterc                  O   s   dS )zn
        Return a L{Bucket} corresponding to the provided parameters.

        @returntype: L{Bucket}
        Nr   )Z
somethingsZsome_kwr   r   r   getBucketForq   s    zIBucketFilter.getBucketForN)r   r   r   r   r   r   r   r   r   p   s   r   c                   @   s:   e Zd ZdZeZdZdddZdd Zdd Z	d	d
 Z
dS )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}
    Nc                 C   s   i | _ || _t | _d S N)bucketsparentFilterr   	lastSweep)r
   r   r   r   r   r      s    z!HierarchicalBucketFilter.__init__c                 O   s|   | j dk	r$t | j | j kr$|   | jr@| jj| f||}nd}| j||}| j|}|dkrx| 	|}|| 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)
sweepIntervalr   r    sweepr   r   getBucketKeyr   getbucketFactory)r
   akwr   keybucketr   r   r   r      s    	


z%HierarchicalBucketFilter.getBucketForc                 O   s   dS )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'   r   r   r   r#      s    	z%HierarchicalBucketFilter.getBucketKeyc                 C   s>   | j  D ]&\}}| }|jdkr
|r
| j |= q
t | _dS )z'
        Remove empty buckets.
        r   N)r   itemsr   r   r   r    )r
   r(   r)   Zbucket_is_emptyr   r   r   r"      s
    
zHierarchicalBucketFilter.sweep)N)r   r   r   r   r   r%   r!   r   r   r#   r"   r   r   r   r   r   x   s   
r   c                   @   s   e Zd ZdZdZdd ZdS )FilterByHostzF
    A Hierarchical Bucket filter with a L{Bucket} for each host.
    i  c                 C   s   |  d S N   )ZgetPeerr
   	transportr   r   r   r#      s    zFilterByHost.getBucketKeyN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S )FilterByServerzI
    A Hierarchical Bucket filter with a L{Bucket} for each service.
    Nc                 C   s   |  d S )N   )ZgetHostr.   r   r   r   r#      s    zFilterByServer.getBucketKeyr0   r   r   r   r   r1      s   r1   c                   @   s,   e Zd ZdZdZdd Zdd Zdd Zd	S )
ShapedConsumerzL
    Wraps a C{Consumer} and shapes the rate at which it receives data.
    Fc                 C   s(   t j| | || _| j jd7  _d S r,   )r   ProducerConsumerProxyr   r)   r   )r
   consumerr)   r   r   r   r      s    zShapedConsumer.__init__c                 C   s&   | j t|}tj| |d | S r   )r)   r   lenr   r4   _writeSomeData)r
   datar   r   r   r   r7      s    zShapedConsumer._writeSomeDatac                 C   s    t j|  | j jd8  _d S r,   )r   r4   stopProducingr)   r   )r
   r   r   r   r9      s    zShapedConsumer.stopProducingN)r   r   r   r   iAmStreamingr   r7   r9   r   r   r   r   r3      s
   r3   c                   @   s   e Zd ZdZdZdd ZdS )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                 C   s   t | j|S r   )getattrr5   )r
   namer   r   r   __getattr__   s    zShapedTransport.__getattr__N)r   r   r   r   r:   r>   r   r   r   r   r;      s   
r;   c                   @   s    e Zd ZdZdd Zdd ZdS )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                 C   s   || _ || _dS )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
   Z
protoClassrA   r   r   r   r     s    zShapedProtocolFactory.__init__c                    s*   j ||}|j  fd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                    s   j | }t| |} |S r   )rA   r   r;   )r/   r)   ZshapedTransportZorigMakeConnectionr
   r   r   makeConnection"  s    
z6ShapedProtocolFactory.__call__.<locals>.makeConnection)r@   rC   )r
   r&   r'   protorC   r   rB   r   __call__  s
    zShapedProtocolFactory.__call__N)r   r   r   r   r   rE   r   r   r   r   r?      s   r?   N)r   r   Zzope.interfacer   r   Ztwisted.protocolsr   r   r   r   r+   r1   r4   r3   r;   r?   r   r   r   r   <module>   s   TA

