Blame | Last modification | View Log | Download
# Written by Bram Cohen# see LICENSE.txt for license informationfrom cStringIO import StringIOfrom urllib import quotefrom threading import Eventtry:Trueexcept:True = 1False = 0class DownloaderFeedback:def __init__(self, choker, httpdl, add_task, upfunc, downfunc,ratemeasure, leftfunc, file_length, finflag, sp, statistics,statusfunc = None, interval = None):self.choker = chokerself.httpdl = httpdlself.add_task = add_taskself.upfunc = upfuncself.downfunc = downfuncself.ratemeasure = ratemeasureself.leftfunc = leftfuncself.file_length = file_lengthself.finflag = finflagself.sp = spself.statistics = statisticsself.lastids = []self.spewdata = Noneself.doneprocessing = Event()self.doneprocessing.set()if statusfunc:self.autodisplay(statusfunc, interval)def _rotate(self):cs = self.choker.connectionsfor id in self.lastids:for i in xrange(len(cs)):if cs[i].get_id() == id:return cs[i:] + cs[:i]return csdef spews(self):l = []cs = self._rotate()self.lastids = [c.get_id() for c in cs]for c in cs:a = {}a['id'] = c.get_readable_id()a['ip'] = c.get_ip()a['optimistic'] = (c is self.choker.connections[0])if c.is_locally_initiated():a['direction'] = 'L'else:a['direction'] = 'R'u = c.get_upload()a['uprate'] = int(u.measure.get_rate())a['uinterested'] = u.is_interested()a['uchoked'] = u.is_choked()d = c.get_download()a['downrate'] = int(d.measure.get_rate())a['dinterested'] = d.is_interested()a['dchoked'] = d.is_choked()a['snubbed'] = d.is_snubbed()a['utotal'] = d.connection.upload.measure.get_total()a['dtotal'] = d.connection.download.measure.get_total()if len(d.connection.download.have) > 0:a['completed'] = float(len(d.connection.download.have)-d.connection.download.have.numfalse)/float(len(d.connection.download.have))else:a['completed'] = 1.0a['speed'] = d.connection.download.peermeasure.get_rate()l.append(a)for dl in self.httpdl.get_downloads():if dl.goodseed:a = {}a['id'] = 'http seed'a['ip'] = dl.baseurla['optimistic'] = Falsea['direction'] = 'L'a['uprate'] = 0a['uinterested'] = Falsea['uchoked'] = Falsea['downrate'] = int(dl.measure.get_rate())a['dinterested'] = Truea['dchoked'] = not dl.activea['snubbed'] = not dl.activea['utotal'] = Nonea['dtotal'] = dl.measure.get_total()a['completed'] = 1.0a['speed'] = Nonel.append(a)return ldef gather(self, displayfunc = None):s = {'stats': self.statistics.update()}if self.sp.isSet():s['spew'] = self.spews()else:s['spew'] = Nones['up'] = self.upfunc()if self.finflag.isSet():s['done'] = self.file_lengthreturn ss['down'] = self.downfunc()obtained, desired = self.leftfunc()s['done'] = obtaineds['wanted'] = desiredif desired > 0:s['frac'] = float(obtained)/desiredelse:s['frac'] = 1.0if desired == obtained:s['time'] = 0else:s['time'] = self.ratemeasure.get_time_left(desired-obtained)return sdef display(self, displayfunc):if not self.doneprocessing.isSet():returnself.doneprocessing.clear()stats = self.gather()if self.finflag.isSet():displayfunc(dpflag = self.doneprocessing,upRate = stats['up'],statistics = stats['stats'], spew = stats['spew'])elif stats['time'] is not None:displayfunc(dpflag = self.doneprocessing,fractionDone = stats['frac'], sizeDone = stats['done'],downRate = stats['down'], upRate = stats['up'],statistics = stats['stats'], spew = stats['spew'],timeEst = stats['time'])else:displayfunc(dpflag = self.doneprocessing,fractionDone = stats['frac'], sizeDone = stats['done'],downRate = stats['down'], upRate = stats['up'],statistics = stats['stats'], spew = stats['spew'])def autodisplay(self, displayfunc, interval):self.displayfunc = displayfuncself.interval = intervalself._autodisplay()def _autodisplay(self):self.add_task(self._autodisplay, self.interval)self.display(self.displayfunc)