| Index: third_party/twisted_8_1/twisted/protocols/htb.py
|
| diff --git a/third_party/twisted_8_1/twisted/protocols/htb.py b/third_party/twisted_8_1/twisted/protocols/htb.py
|
| deleted file mode 100644
|
| index 08d9626802563053d97e2d38a98c434bb3bfbaca..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/protocols/htb.py
|
| +++ /dev/null
|
| @@ -1,269 +0,0 @@
|
| -# -*- test-case-name: twisted.test.test_htb -*-
|
| -#
|
| -# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -
|
| -"""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: U{Kevin Turner<mailto:acapnotic@twistedmatrix.com>}
|
| -"""
|
| -
|
| -from __future__ import nested_scopes
|
| -
|
| -__version__ = '$Revision: 1.5 $'[11:-2]
|
| -
|
| -
|
| -# TODO: Investigate whether we should be using os.times()[-1] instead of
|
| -# time.time. time.time, it has been pointed out, can go backwards. Is
|
| -# the same true of os.times?
|
| -from time import time
|
| -from zope.interface import implements, Interface
|
| -
|
| -from twisted.protocols import pcp
|
| -
|
| -
|
| -class Bucket:
|
| - """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
|
| - """
|
| -
|
| - maxburst = None
|
| - rate = None
|
| -
|
| - _refcount = 0
|
| -
|
| - def __init__(self, parentBucket=None):
|
| - self.content = 0
|
| - self.parentBucket=parentBucket
|
| - self.lastDrip = time()
|
| -
|
| - def add(self, amount):
|
| - """Add tokens to me.
|
| -
|
| - @param amount: A quanity of tokens to add.
|
| - @type amount: int
|
| -
|
| - @returns: The number of tokens that fit.
|
| - @returntype: int
|
| - """
|
| - self.drip()
|
| - if self.maxburst is None:
|
| - allowable = amount
|
| - else:
|
| - allowable = min(amount, self.maxburst - self.content)
|
| -
|
| - if self.parentBucket is not None:
|
| - allowable = self.parentBucket.add(allowable)
|
| - self.content += allowable
|
| - return allowable
|
| -
|
| - def drip(self):
|
| - """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
|
| - """
|
| - if self.parentBucket is not None:
|
| - self.parentBucket.drip()
|
| -
|
| - if self.rate is None:
|
| - self.content = 0
|
| - return True
|
| - else:
|
| - now = time()
|
| - deltaT = now - self.lastDrip
|
| - self.content = long(max(0, self.content - deltaT * self.rate))
|
| - self.lastDrip = now
|
| - return False
|
| -
|
| -
|
| -class IBucketFilter(Interface):
|
| - def getBucketFor(*somethings, **some_kw):
|
| - """I'll give you a bucket for something.
|
| -
|
| - @returntype: L{Bucket}
|
| - """
|
| -
|
| -class HierarchicalBucketFilter:
|
| - """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
|
| - """
|
| -
|
| - implements(IBucketFilter)
|
| -
|
| - bucketFactory = Bucket
|
| - sweepInterval = None
|
| -
|
| - def __init__(self, parentFilter=None):
|
| - self.buckets = {}
|
| - self.parentFilter = parentFilter
|
| - self.lastSweep = time()
|
| -
|
| - def getBucketFor(self, *a, **kw):
|
| - """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}
|
| - """
|
| - if ((self.sweepInterval is not None)
|
| - and ((time() - self.lastSweep) > self.sweepInterval)):
|
| - self.sweep()
|
| -
|
| - if self.parentFilter:
|
| - parentBucket = self.parentFilter.getBucketFor(self, *a, **kw)
|
| - else:
|
| - parentBucket = None
|
| -
|
| - key = self.getBucketKey(*a, **kw)
|
| - bucket = self.buckets.get(key)
|
| - if bucket is None:
|
| - bucket = self.bucketFactory(parentBucket)
|
| - self.buckets[key] = bucket
|
| - return bucket
|
| -
|
| - def getBucketKey(self, *a, **kw):
|
| - """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.
|
| - """
|
| - return None
|
| -
|
| - def sweep(self):
|
| - """I throw away references to empty buckets."""
|
| - for key, bucket in self.buckets.items():
|
| - if (bucket._refcount == 0) and bucket.drip():
|
| - del self.buckets[key]
|
| -
|
| - self.lastSweep = time()
|
| -
|
| -
|
| -class FilterByHost(HierarchicalBucketFilter):
|
| - """A bucket filter with a bucket for each host.
|
| - """
|
| - sweepInterval = 60 * 20
|
| -
|
| - def getBucketKey(self, transport):
|
| - return transport.getPeer()[1]
|
| -
|
| -
|
| -class FilterByServer(HierarchicalBucketFilter):
|
| - """A bucket filter with a bucket for each service.
|
| - """
|
| - sweepInterval = None
|
| -
|
| - def getBucketKey(self, transport):
|
| - return transport.getHost()[2]
|
| -
|
| -
|
| -class ShapedConsumer(pcp.ProducerConsumerProxy):
|
| - """I wrap a Consumer and shape the rate at which it receives data.
|
| - """
|
| - # Providing a Pull interface means I don't have to try to schedule
|
| - # traffic with callLaters.
|
| - iAmStreaming = False
|
| -
|
| - def __init__(self, consumer, bucket):
|
| - pcp.ProducerConsumerProxy.__init__(self, consumer)
|
| - self.bucket = bucket
|
| - self.bucket._refcount += 1
|
| -
|
| - def _writeSomeData(self, data):
|
| - # In practice, this actually results in obscene amounts of
|
| - # overhead, as a result of generating lots and lots of packets
|
| - # with twelve-byte payloads. We may need to do a version of
|
| - # this with scheduled writes after all.
|
| - amount = self.bucket.add(len(data))
|
| - return pcp.ProducerConsumerProxy._writeSomeData(self, data[:amount])
|
| -
|
| - def stopProducing(self):
|
| - pcp.ProducerConsumerProxy.stopProducing(self)
|
| - self.bucket._refcount -= 1
|
| -
|
| -
|
| -class ShapedTransport(ShapedConsumer):
|
| - """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).
|
| - """
|
| - # Ugh. We only wanted to filter IConsumer, not ITransport.
|
| -
|
| - iAmStreaming = False
|
| - def __getattr__(self, name):
|
| - # Because people will be doing things like .getPeer and
|
| - # .loseConnection on me.
|
| - return getattr(self.consumer, name)
|
| -
|
| -
|
| -class ShapedProtocolFactory:
|
| - """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}.
|
| - """
|
| - def __init__(self, protoClass, bucketFilter):
|
| - """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}.
|
| - """
|
| - # More precisely, protoClass can be any callable that will return
|
| - # instances of something that implements IProtocol.
|
| - self.protocol = protoClass
|
| - self.bucketFilter = bucketFilter
|
| -
|
| - def __call__(self, *a, **kw):
|
| - """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}.
|
| - """
|
| - proto = self.protocol(*a, **kw)
|
| - origMakeConnection = proto.makeConnection
|
| - def makeConnection(transport):
|
| - bucket = self.bucketFilter.getBucketFor(transport)
|
| - shapedTransport = ShapedTransport(transport, bucket)
|
| - return origMakeConnection(shapedTransport)
|
| - proto.makeConnection = makeConnection
|
| - return proto
|
|
|