ó
[³XMc           @   s  d  Z  d d l m Z d d d !Z d d l m Z d d l m Z m Z d d l m	 Z	 d	 d d
 „  ƒ  YZ
 d e f d „  ƒ  YZ d d d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e	 j f d „  ƒ  YZ d e f d „  ƒ  YZ d d d „  ƒ  YZ d S(   sÑ  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>}
@author: Kevin Turner
iÿÿÿÿ(   t   nested_scopess   $Revision: 1.5 $i   iþÿÿÿ(   t   time(   t
   implementst	   Interface(   t   pcpt   Bucketc           B   s>   e  Z d  Z d Z d Z d Z d d „ Z d „  Z d „  Z	 RS(   sn  Token bucket, or something like it.

    I can hold up to a certain number of tokens, and I drain over time.

    @cvar maxburst: Size of the bucket, in bytes.  If None, the bucket is
        never full.
    @type maxburst: int
    @cvar rate: Rate the bucket drains, in bytes per second.  If None,
        the bucket drains instantaneously.
    @type rate: int
    i    c         C   s"   d |  _  | |  _ t ƒ  |  _ d  S(   Ni    (   t   contentt   parentBucketR   t   lastDrip(   t   selfR   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyt   __init__3   s    		c         C   sr   |  j  ƒ  |  j d k r" | } n t | |  j |  j ƒ } |  j d k	 r_ |  j j | ƒ } n  |  j | 7_ | S(   s³   Add tokens to me.

        @param amount: A quanity of tokens to add.
        @type amount: int

        @returns: The number of tokens that fit.
        @returntype: int
        N(   t   dript   maxburstt   Nonet   minR   R   t   add(   R	   t   amountt	   allowable(    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR   8   s    	
	c         C   sˆ   |  j  d k	 r |  j  j ƒ  n  |  j d k r; d |  _ t St ƒ  } | |  j } t t	 d |  j | |  j ƒ ƒ |  _ | |  _ t
 Sd S(   sÓ   Let some of the bucket drain.

        How much of the bucket drains depends on how long it has been
        since I was last called.

        @returns: True if I am now empty.
        @returntype: bool
        i    N(   R   R   R   t   rateR   t   TrueR   R   t   longt   maxt   False(   R	   t   nowt   deltaT(    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR   L   s    			&	N(
   t   __name__t
   __module__t   __doc__R   R   R   t	   _refcountR
   R   R   (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR   !   s   	t   IBucketFilterc           B   s   e  Z d  „  Z RS(   c          O   s   d S(   sN   I'll give you a bucket for something.

        @returntype: L{Bucket}
        N(    (   t
   somethingst   some_kw(    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyt   getBucketFord   s    (   R   R   R    (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR   c   s   t   HierarchicalBucketFilterc           B   sK   e  Z d  Z e e ƒ e Z d Z d d „ Z	 d „  Z
 d „  Z d „  Z RS(   s÷   I filter things into buckets, and I am nestable.

    @cvar bucketFactory: Class of buckets to make.
    @type bucketFactory: L{Bucket} class
    @cvar sweepInterval: Seconds between sweeping out the bucket cache.
    @type sweepInterval: int
    c         C   s"   i  |  _  | |  _ t ƒ  |  _ d  S(   N(   t   bucketst   parentFilterR   t	   lastSweep(   R	   R#   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR
   x   s    		c         O   s²   |  j  d k	 r5 t ƒ  |  j |  j  k r5 |  j ƒ  n  |  j rY |  j j |  | | Ž } n d } |  j | | Ž  } |  j j	 | ƒ } | d k r® |  j
 | ƒ } | |  j | <n  | S(   sÊ   You want a bucket for that?  I'll give you a bucket.

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

        @returntype: L{Bucket}
        N(   t   sweepIntervalR   R   R$   t   sweepR#   R    t   getBucketKeyR"   t   gett   bucketFactory(   R	   t   at   kwR   t   keyt   bucket(    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR    }   s    	c         O   s   d S(   s²   I determine who gets which bucket.

        Unless I'm overridden, everything gets the same bucket.

        @returns: something to be used as a key in the bucket cache.
        N(   R   (   R	   R*   R+   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR'   •   s    c         C   sX   xE |  j  j ƒ  D]4 \ } } | j d k r | j ƒ  r |  j  | =q q Wt ƒ  |  _ d S(   s)   I throw away references to empty buckets.i    N(   R"   t   itemsR   R   R   R$   (   R	   R,   R-   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR&   ž   s    N(   R   R   R   R   R   R   R)   R   R%   R
   R    R'   R&   (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR!   j   s   
			t   FilterByHostc           B   s   e  Z d  Z d Z d „  Z RS(   s1   A bucket filter with a bucket for each host.
    i<   i   c         C   s   | j  ƒ  d S(   Ni   (   t   getPeer(   R	   t	   transport(    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR'   ¬   s    i°  (   R   R   R   R%   R'   (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR/   §   s   t   FilterByServerc           B   s   e  Z d  Z d Z d „  Z RS(   s4   A bucket filter with a bucket for each service.
    c         C   s   | j  ƒ  d S(   Ni   (   t   getHost(   R	   R1   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR'   µ   s    N(   R   R   R   R   R%   R'   (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR2   °   s   t   ShapedConsumerc           B   s/   e  Z d  Z e Z d „  Z d „  Z d „  Z RS(   sD   I wrap a Consumer and shape the rate at which it receives data.
    c         C   s2   t  j j |  | ƒ | |  _ |  j j d 7_ d  S(   Ni   (   R   t   ProducerConsumerProxyR
   R-   R   (   R	   t   consumerR-   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR
   À   s    	c         C   s/   |  j  j t | ƒ ƒ } t j j |  | |  ƒ S(   N(   R-   R   t   lenR   R5   t   _writeSomeData(   R	   t   dataR   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR8   Å   s    c         C   s&   t  j j |  ƒ |  j j d 8_ d  S(   Ni   (   R   R5   t   stopProducingR-   R   (   R	   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR:   Í   s    (   R   R   R   R   t   iAmStreamingR
   R8   R:   (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR4   ¹   s
   		t   ShapedTransportc           B   s   e  Z d  Z e Z d „  Z RS(   s7  I wrap a Transport and shape the rate at which it receives data.

    I am a L{ShapedConsumer} with a little bit of magic to provide for
    the case where the consumer I wrap is also a Transport and people
    will be attempting to access attributes I do not proxy as a
    Consumer (e.g. loseConnection).
    c         C   s   t  |  j | ƒ S(   N(   t   getattrR6   (   R	   t   name(    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyt   __getattr__Ý   s    (   R   R   R   R   R;   R?   (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR<   Ò   s   t   ShapedProtocolFactoryc           B   s    e  Z d  Z d „  Z d „  Z RS(   sƒ  I dispense Protocols with traffic shaping on their transports.

    Usage::

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

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

        @param protoClass: The class of Protocol I 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(   t   protocolt   bucketFilter(   R	   t
   protoClassRB   (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR
   ï   s    	c            s:   ˆ  j  | | Ž  } | j ‰ ‡  ‡ f d †  } | | _ | S(   sÅ   Make a Protocol instance with a shaped transport.

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

        @returns: a Protocol instance with a L{ShapedTransport}.
        c            s+   ˆ  j  j |  ƒ } t |  | ƒ } ˆ | ƒ S(   N(   RB   R    R<   (   R1   R-   t   shapedTransport(   R	   t   origMakeConnection(    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyt   makeConnection  s    (   RA   RF   (   R	   R*   R+   t   protoRF   (    (   R	   RE   s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyt   __call__ÿ   s
    		(   R   R   R   R
   RH   (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyR@   ã   s   	N(    (    (    (   R   t
   __future__R    t   __version__R   t   zope.interfaceR   R   t   twisted.protocolsR   R   R   R!   R/   R2   R5   R4   R<   R@   (    (    (    s9   /usr/lib/python2.7/dist-packages/twisted/protocols/htb.pyt   <module>   s   B=		