home *** CD-ROM | disk | FTP | other *** search
/ Chip 2006 June / CHIP 2006-06.2.iso / program / freeware / Democracy-0.8.2.exe / xulrunner / python / BitTorrent / RateLimiter.py < prev    next >
Encoding:
Python Source  |  2006-04-10  |  3.5 KB  |  102 lines

  1. # The contents of this file are subject to the BitTorrent Open Source License
  2. # Version 1.0 (the License).  You may not copy or use this file, in either
  3. # source code or executable form, except in compliance with the License.  You
  4. # may obtain a copy of the License at http://www.bittorrent.com/license/.
  5. #
  6. # Software distributed under the License is distributed on an AS IS basis,
  7. # WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
  8. # for the specific language governing rights and limitations under the
  9. # License.
  10.  
  11. # Written by Uoti Urpala
  12.  
  13. from time import time
  14.  
  15. class RateLimiter(object):
  16.  
  17.     def __init__(self, sched):
  18.         self.sched = sched
  19.         self.last = None
  20.         self.upload_rate = 1e10
  21.         self.unitsize = 1e10
  22.         self.offset_amount = 0
  23.  
  24.     def set_parameters(self, rate, unitsize):
  25.         if rate == 0:
  26.             rate = 1e10
  27.             unitsize = 17000
  28.         if unitsize > 17000:
  29.             # Since data is sent to peers in a round-robin fashion, max one
  30.             # full request at a time, setting this higher would send more data
  31.             # to peers that use request sizes larger than standard 16 KiB.
  32.             # 17000 instead of 16384 to allow room for metadata messages.
  33.             unitsize = 17000
  34.         self.upload_rate = rate * 1024
  35.         self.unitsize = unitsize
  36.         self.lasttime = time()
  37.         self.offset_amount = 0
  38.  
  39.     def queue(self, conn):
  40.         assert conn.next_upload is None
  41.         if self.last is None:
  42.             self.last = conn
  43.             conn.next_upload = conn
  44.             self.try_send(True)
  45.         else:
  46.             conn.next_upload = self.last.next_upload
  47.             self.last.next_upload = conn
  48.             self.last = conn
  49.  
  50.     def try_send(self, check_time=False):
  51.         t = time()
  52.         self.offset_amount -= (t - self.lasttime) * self.upload_rate
  53.         self.lasttime = t
  54.         if check_time:
  55.             self.offset_amount = max(self.offset_amount, 0)
  56.         cur = self.last.next_upload
  57.         while self.offset_amount <= 0:
  58.             try:
  59.                 bytes = cur.send_partial(self.unitsize)
  60.             except KeyboardInterrupt:
  61.                 raise
  62.             except Exception, e:
  63.                 cur.encoder.context.got_exception(e)
  64.                 bytes = 0
  65.  
  66.             self.offset_amount += bytes
  67.             if bytes == 0 or not cur.connection.is_flushed():
  68.                 if self.last is cur:
  69.                     self.last = None
  70.                     cur.next_upload = None
  71.                     break
  72.                 else:
  73.                     self.last.next_upload = cur.next_upload
  74.                     cur.next_upload = None
  75.                     cur = self.last.next_upload
  76.             else:
  77.                 self.last = cur
  78.                 cur = cur.next_upload
  79.         else:
  80.             self.sched(self.try_send, self.offset_amount / self.upload_rate)
  81.  
  82.     def clean_closed(self):
  83.         if self.last is None:
  84.             return
  85.         class Dummy(object):
  86.             def __init__(self, next):
  87.                 self.next_upload = next
  88.             def send_partial(self, size):
  89.                 return 0
  90.             closed = False
  91.         orig = self.last
  92.         if self.last.closed:
  93.             self.last = Dummy(self.last.next_upload)
  94.         c = self.last
  95.         while True:
  96.             if c.next_upload is orig:
  97.                 c.next_upload = self.last
  98.                 break
  99.             if c.next_upload.closed:
  100.                 c.next_upload = Dummy(c.next_upload.next_upload)
  101.             c = c.next_upload
  102.