diff options
Diffstat (limited to 'BitTorrent/DownloaderFeedback.py')
-rw-r--r-- | BitTorrent/DownloaderFeedback.py | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/BitTorrent/DownloaderFeedback.py b/BitTorrent/DownloaderFeedback.py new file mode 100644 index 0000000..6c16c90 --- /dev/null +++ b/BitTorrent/DownloaderFeedback.py @@ -0,0 +1,139 @@ +# The contents of this file are subject to the BitTorrent Open Source License +# Version 1.1 (the License). You may not copy or use this file, in either +# source code or executable form, except in compliance with the License. You +# may obtain a copy of the License at http://www.bittorrent.com/license/. +# +# Software distributed under the License is distributed on an AS IS basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. + +# Written by Bram Cohen, Uoti Urpala + +from __future__ import division + + +class DownloaderFeedback(object): + + def __init__(self, choker, upfunc, upfunc2, downfunc, uptotal, downtotal, + remainingfunc, leftfunc, file_length, finflag, downloader, + files, ever_got_incoming, rerequester): + self.downloader = downloader + self.picker = downloader.picker + self.storage = downloader.storage + self.choker = choker + self.upfunc = upfunc + self.upfunc2 = upfunc2 + self.downfunc = downfunc + self.uptotal = uptotal + self.downtotal = downtotal + self.remainingfunc = remainingfunc + self.leftfunc = leftfunc + self.file_length = file_length + self.finflag = finflag + self.files = files + self.ever_got_incoming = ever_got_incoming + self.rerequester = rerequester + self.lastids = [] + + def _rotate(self): + cs = self.choker.connections + for peerid in self.lastids: + for i in xrange(len(cs)): + if cs[i].id == peerid: + return cs[i:] + cs[:i] + return cs + + def collect_spew(self): + l = [ ] + cs = self._rotate() + self.lastids = [c.id for c in cs] + for c in cs: + rec = {} + rec['id'] = c.id + rec["ip"] = c.ip + rec["is_optimistic_unchoke"] = (c is self.choker.connections[0]) + if c.locally_initiated: + rec["initiation"] = "L" + else: + rec["initiation"] = "R" + u = c.upload + rec["upload"] = (u.measure.get_total(), int(u.measure.get_rate()), + u.interested, u.choked) + + d = c.download + rec["download"] = (d.measure.get_total(),int(d.measure.get_rate()), + d.interested, d.choked, d.is_snubbed()) + rec['completed'] = 1 - d.have.numfalse / len(d.have) + rec['speed'] = d.connection.download.peermeasure.get_rate() + l.append(rec) + return l + + def get_statistics(self, spewflag=False, fileflag=False): + status = {} + numSeeds = 0 + numPeers = 0 + for d in self.downloader.downloads: + if d.have.numfalse == 0: + numSeeds += 1 + else: + numPeers += 1 + status['numSeeds'] = numSeeds + status['numPeers'] = numPeers + status['trackerSeeds'] = self.rerequester.tracker_num_seeds + status['trackerPeers'] = self.rerequester.tracker_num_peers + status['upRate'] = self.upfunc() + status['upRate2'] = self.upfunc2() + status['upTotal'] = self.uptotal() + status['ever_got_incoming'] = self.ever_got_incoming() + missingPieces = 0 + numCopyList = [] + numCopies = 0 + for i in self.picker.crosscount: + missingPieces += i + if missingPieces == 0: + numCopies += 1 + else: + fraction = 1 - missingPieces / self.picker.numpieces + numCopyList.append(fraction) + if fraction == 0 or len(numCopyList) >= 3: + break + numCopies -= numSeeds + if self.picker.numgot == self.picker.numpieces: + numCopies -= 1 + status['numCopies'] = numCopies + status['numCopyList'] = numCopyList + status['discarded'] = self.downloader.discarded_bytes + status['storage_numcomplete'] = self.storage.stat_numfound + \ + self.storage.stat_numdownloaded + status['storage_dirty'] = len(self.storage.stat_dirty) + status['storage_active'] = len(self.storage.stat_active) + status['storage_new'] = len(self.storage.stat_new) + status['storage_numflunked'] = self.storage.stat_numflunked + + if spewflag: + status['spew'] = self.collect_spew() + status['bad_peers'] = self.downloader.bad_peers + if fileflag: + undl = self.storage.storage.undownloaded + unal = self.storage.storage.unallocated + status['files_left'] = [undl[fname] for fname in self.files] + status['files_allocated'] = [not unal[fn] for fn in self.files] + if self.finflag.isSet(): + status['downRate'] = 0 + status['downTotal'] = self.downtotal() + status['fractionDone'] = 1 + return status + timeEst = self.remainingfunc() + status['timeEst'] = timeEst + + if self.file_length > 0: + fractionDone = 1 - self.leftfunc() / self.file_length + else: + fractionDone = 1 + status.update({ + "fractionDone" : fractionDone, + "downRate" : self.downfunc(), + "downTotal" : self.downtotal() + }) + return status |