2017-01-15 15:08:03 +01:00
|
|
|
import math
|
2017-01-14 23:21:00 +01:00
|
|
|
import threading
|
|
|
|
import time
|
|
|
|
|
|
|
|
from configparser import BMConfigParser
|
|
|
|
from singleton import Singleton
|
|
|
|
import state
|
|
|
|
|
|
|
|
class Throttle(object):
|
2017-01-15 15:08:03 +01:00
|
|
|
minChunkSize = 4096
|
|
|
|
maxChunkSize = 131072
|
|
|
|
|
2017-01-14 23:21:00 +01:00
|
|
|
def __init__(self, limit=0):
|
|
|
|
self.limit = limit
|
|
|
|
self.speed = 0
|
2017-01-15 15:08:03 +01:00
|
|
|
self.chunkSize = Throttle.maxChunkSize
|
2017-01-14 23:21:00 +01:00
|
|
|
self.txTime = int(time.time())
|
|
|
|
self.txLen = 0
|
|
|
|
self.total = 0
|
|
|
|
self.timer = threading.Event()
|
|
|
|
self.lock = threading.RLock()
|
2017-01-15 15:08:03 +01:00
|
|
|
self.resetChunkSize()
|
2017-01-14 23:21:00 +01:00
|
|
|
|
|
|
|
def recalculate(self):
|
|
|
|
with self.lock:
|
|
|
|
now = int(time.time())
|
|
|
|
if now > self.txTime:
|
|
|
|
self.speed = self.txLen / (now - self.txTime)
|
|
|
|
self.txLen -= self.limit * (now - self.txTime)
|
|
|
|
self.txTime = now
|
|
|
|
if self.txLen < 0 or self.limit == 0:
|
|
|
|
self.txLen = 0
|
|
|
|
|
|
|
|
def wait(self, dataLen):
|
|
|
|
with self.lock:
|
|
|
|
self.txLen += dataLen
|
|
|
|
self.total += dataLen
|
|
|
|
while state.shutdown == 0:
|
|
|
|
self.recalculate()
|
|
|
|
if self.limit == 0:
|
|
|
|
break
|
|
|
|
if self.txLen < self.limit:
|
|
|
|
break
|
|
|
|
self.timer.wait(0.2)
|
|
|
|
|
|
|
|
def getSpeed(self):
|
|
|
|
self.recalculate()
|
|
|
|
return self.speed
|
|
|
|
|
2017-01-15 15:08:03 +01:00
|
|
|
def resetChunkSize(self):
|
|
|
|
with self.lock:
|
|
|
|
# power of two smaller or equal to speed limit
|
|
|
|
try:
|
|
|
|
self.chunkSize = int(math.pow(2, int(math.log(self.limit,2))))
|
|
|
|
except ValueError:
|
|
|
|
self.chunkSize = Throttle.maxChunkSize
|
|
|
|
# range check
|
|
|
|
if self.chunkSize < Throttle.minChunkSize:
|
|
|
|
self.chunkSize = Throttle.minChunkSize
|
|
|
|
elif self.chunkSize > Throttle.maxChunkSize:
|
|
|
|
self.chunkSize = Throttle.maxChunkSize
|
|
|
|
|
2017-01-14 23:21:00 +01:00
|
|
|
@Singleton
|
|
|
|
class SendThrottle(Throttle):
|
|
|
|
def __init__(self):
|
|
|
|
Throttle.__init__(self, BMConfigParser().safeGetInt('bitmessagesettings', 'maxuploadrate')*1024)
|
|
|
|
|
|
|
|
def resetLimit(self):
|
|
|
|
with self.lock:
|
|
|
|
self.limit = BMConfigParser().safeGetInt('bitmessagesettings', 'maxuploadrate')*1024
|
2017-01-15 15:08:03 +01:00
|
|
|
Throttle.resetChunkSize()
|
2017-01-14 23:21:00 +01:00
|
|
|
|
|
|
|
@Singleton
|
|
|
|
class ReceiveThrottle(Throttle):
|
|
|
|
def __init__(self):
|
|
|
|
Throttle.__init__(self, BMConfigParser().safeGetInt('bitmessagesettings', 'maxdownloadrate')*1024)
|
|
|
|
|
|
|
|
def resetLimit(self):
|
|
|
|
with self.lock:
|
|
|
|
self.limit = BMConfigParser().safeGetInt('bitmessagesettings', 'maxdownloadrate')*1024
|
2017-01-15 15:08:03 +01:00
|
|
|
Throttle.resetChunkSize()
|