This repository has been archived on 2024-05-09. You can view files and clone it, but cannot push or open issues/pull-requests.
ipodderx-core/BitTorrent/DownloaderFeedback.py

140 lines
5.3 KiB
Python

# 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