r343 - in /debtorrent/trunk: DebTorrent/BT1/track.py debian/changelog
camrdale-guest at users.alioth.debian.org
camrdale-guest at users.alioth.debian.org
Wed Jan 23 05:19:24 UTC 2008
Author: camrdale-guest
Date: Wed Jan 23 05:19:23 2008
New Revision: 343
URL: http://svn.debian.org/wsvn/debtorrent/?sc=1&rev=343
Log:
Report more and better statistics on the tracker's info page.
Modified:
debtorrent/trunk/DebTorrent/BT1/track.py
debtorrent/trunk/debian/changelog
Modified: debtorrent/trunk/DebTorrent/BT1/track.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/BT1/track.py?rev=343&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/BT1/track.py (original)
+++ debtorrent/trunk/DebTorrent/BT1/track.py Wed Jan 23 05:19:23 2008
@@ -160,12 +160,21 @@
raise ValueError
if type(info.get('requirecrypto')) not in (IntType,LongType):
raise ValueError
- elif cname == 'completed':
- if (type(cinfo) != DictType): # The 'completed' key is a dictionary of SHA hashes (torrent ids)
+ elif cname == 'stats':
+ if (type(cinfo) != DictType): # The 'stats' key is a dictionary of SHA hashes (torrent ids)
raise ValueError # ... for keeping track of the total completions per torrent
for y in cinfo.values(): # ... each torrent has an integer value
- if type(y) not in (IntType,LongType):
+ if type(y) != DictType:
raise ValueError # ... for the number of reported completions for that torrent
+ completed = y.get('completed')
+ if type(completed) not in (IntType,LongType) or completed < 0:
+ raise ValueError
+ uploaded = y.get('uploaded', 0)
+ if type(uploaded) not in (IntType,LongType) or uploaded < 0:
+ raise ValueError
+ downloaded = y.get('downloaded', 0)
+ if type(downloaded) not in (IntType,LongType) or downloaded < 0:
+ raise ValueError
elif cname == 'allowed':
if (type(cinfo) != DictType): # a list of info_hashes and included data
raise ValueError
@@ -359,9 +368,9 @@
@ivar downloads: keys are info hashes, values are dictionaries with keys the
peer IDs of peers connected to that torrent and values the dictionaries
of information about the peer
- @type completed: C{dictionary}
- @ivar completed: keys are info hashes, values are the number of peers that
- have completed downloading the entire torrent
+ @type stats: C{dictionary}
+ @ivar stats: keys are info hashes, values are dictionaries containing
+ statistics related to the torrent
@type becache: C{list} of C{list} of C{dictionary}
@ivar becache: keys are the infohashes, values are the cached peer data.
peer set format::
@@ -485,7 +494,7 @@
except:
logger.warning('statefile corrupt; resetting')
self.downloads = self.state.setdefault('peers', {})
- self.completed = self.state.setdefault('completed', {})
+ self.stats = self.state.setdefault('stats', {})
self.becache = {}
@@ -655,17 +664,21 @@
return (302, 'Found', {'Content-Type': 'text/html', 'Location': red},
'<A HREF="'+red+'">Click Here</A>')
+ # Write the document header
s = StringIO()
- s.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n' \
- '<html><head><title>DebTorrent download info</title>\n')
+ s.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" ' \
+ '"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n' \
+ '<html><head><title>DebTorrent tracker info</title>\n')
if self.favicon is not None:
s.write('<link rel="shortcut icon" href="/favicon.ico">\n')
s.write('</head>\n<body>\n' \
- '<h3>DebTorrent download info</h3>\n'\
- '<ul>\n'
- '<li><strong>tracker version:</strong> %s</li>\n' \
- '<li><strong>server time:</strong> %s</li>\n' \
- '</ul>\n' % (version, isotime()))
+ '<h3>DebTorrent tracker info</h3>\n'\
+ '<ul>\n'
+ '<li><strong>tracker version:</strong> %s</li>\n' \
+ '<li><strong>server time:</strong> %s</li>\n' \
+ '</ul>\n' % (version, isotime()))
+
+ # Collect the torrent hashes and names
if self.config['allowed_dir']:
if self.show_names:
names = [ (self.allowed[hash]['name'],hash)
@@ -678,66 +691,98 @@
names = [ ('\n<br>'.join(self.torrent_names[hash]),hash) for hash in self.downloads.keys() ]
else:
names = [ (None,hash) for hash in self.downloads.keys() ]
+
if not names:
s.write('<p>not tracking any files yet...</p>\n')
else:
names.sort()
- tn = 0
- tc = 0
- td = 0
- tt = 0 # Total transferred
- ts = 0 # Total size
- nf = 0 # Number of files displayed
- if self.config['allowed_dir'] and self.show_names:
- s.write('<table summary="files" border="1">\n' \
- '<tr><th>torrent name<br><code>info hash</code></th><th align="right">size</th><th align="right">complete</th><th align="right">downloading</th><th align="right">downloaded</th><th align="right">transferred</th></tr>\n')
- else:
- s.write('<table summary="files">\n' \
- '<tr><th>torrent name<br><code>info hash</code></th><th align="right">complete</th><th align="right">downloading</th><th align="right">downloaded</th></tr>\n')
+ number_files = 0
+ total_peers = 0
+ total_uploaded = 0L
+ total_downloaded = 0L
+ total_size = 0L
+
+ # Write the table headers
+ s.write('<table summary="files" border="1">\n\n' \
+ '<tr><th>torrent name/<br><code> info hash</code></th>\n')
+ if self.config['allowed_dir']:
+ s.write('<th align="right">size</th>\n')
+ s.write('<th align="right">peers</th>\n' \
+ '<th align="right">downloaded</th>\n' \
+ '<th align="right">uploaded</th>\n' \
+ '<th align="right">saved</th></tr>\n\n')
+
+ # Display a table row for each torrent
for name,hash in names:
- l = self.downloads[hash]
- n = self.completed.get(hash, 0)
- tn = tn + n
- c = self.seedcount[hash]
- tc = tc + c
- d = len(l) - c
- td = td + d
- if self.config['allowed_dir'] and self.show_names:
- if self.allowed.has_key(hash):
- nf = nf + 1
- sz = self.allowed[hash]['length'] # size
- ts = ts + sz
- szt = sz * n # Transferred for this torrent
- tt = tt + szt
- if self.allow_get == 1:
- linkname = '<a href="/file?info_hash=' + quote(hash) + '">' + name + '</a>'
- else:
- linkname = name
- s.write('<tr><td>%s<br><code>%s</code></td><td align="right">%s</td><td align="right">%i</td><td align="right">%i</td><td align="right">%i</td><td align="right">%s</td></tr>\n' \
- % (linkname, b2a_hex(hash), size_format(sz), c, d, n, size_format(szt)))
+ # Get the stats for this torrent
+ uploaded = self.stats.get(hash, {}).get('uploaded', 0)
+ total_uploaded += uploaded
+ downloaded = self.stats.get(hash, {}).get('downloaded', 0)
+ total_downloaded += downloaded
+ saved = 0.0
+ if downloaded > 0:
+ saved = 100.0 * float(uploaded) / float(downloaded)
+ peers = len(self.downloads[hash])
+ total_peers += peers
+
+ # Display is different if we are using allowed_dir
+ if self.config['allowed_dir'] and self.allowed.has_key(hash):
+ number_files += 1
+ size = self.allowed[hash]['length'] # size
+ total_size += long(size)
+ if self.allow_get == 1:
+ linkname = '<a href="/file?info_hash=' + quote(hash) + '">' + name + '</a>'
+ else:
+ linkname = name
+ s.write('<tr><td>%s<br><code> %s</code></td>\n' \
+ '<td align="right">%s</td>\n' \
+ '<td align="right">%i</td>\n' \
+ '<td align="right">%s</td>\n' \
+ '<td align="right">%s</td>\n' \
+ '<td align="right">%0.1f %%</td></tr>\n\n' \
+ % (linkname, b2a_hex(hash), size_format(size),
+ peers, size_format(downloaded),
+ size_format(uploaded), saved))
else:
+ number_files += 1
s.write('<tr><td>')
if name:
s.write('%s<br>' % name)
- s.write('<code>%s</code></td><td align="right"><code>%i</code></td><td align="right"><code>%i</code></td><td align="right"><code>%i</code></td></tr>\n' \
- % (b2a_hex(hash), c, d, n))
- if self.config['allowed_dir'] and self.show_names:
- s.write('<tr><td align="right">%i files</td><td align="right">%s</td><td align="right">%i</td><td align="right">%i</td><td align="right">%i</td><td align="right">%s</td></tr>\n'
- % (nf, size_format(ts), tc, td, tn, size_format(tt)))
- else:
- s.write('<tr><td align="right">%i files</td><td align="right">%i</td><td align="right">%i</td><td align="right">%i</td></tr>\n'
- % (nf, tc, td, tn))
+ s.write('<code> %s</code></td>\n' \
+ '<td align="right">%i</td>\n' \
+ '<td align="right">%s</td>\n' \
+ '<td align="right">%s</td>\n' \
+ '<td align="right">%0.1f %%</td></tr>\n\n' \
+ % (b2a_hex(hash), peers, size_format(downloaded),
+ size_format(uploaded), saved))
+
+ # The table footer with summary statistics
+ saved = 0.0
+ if total_downloaded > 0:
+ saved = 100.0 * float(total_uploaded) / float(total_downloaded)
+ s.write('<tr><td align="right">%i torrents</td>\n' % number_files)
+ if self.config['allowed_dir']:
+ s.write('<td align="right">%s</td>\n' % size_format(total_size))
+ s.write('<td align="right">%i</td>\n' \
+ '<td align="right">%s</td>\n' \
+ '<td align="right">%s</td>\n' \
+ '<td align="right">%0.1f %%</td></tr>\n\n'
+ % (total_peers, size_format(total_downloaded),
+ size_format(total_uploaded), saved))
+
+ # Write a rudimentary legend
s.write('</table>\n' \
'<ul>\n' \
- '<li><em>info hash:</em> SHA1 hash of the "info" section of the metainfo (*.dtorrent)</li>\n' \
- '<li><em>complete:</em> number of connected clients with the complete file</li>\n' \
- '<li><em>downloading:</em> number of connected clients still downloading</li>\n' \
- '<li><em>downloaded:</em> reported complete downloads</li>\n' \
- '<li><em>transferred:</em> torrent size * total downloaded (does not include partial transfers)</li>\n' \
+ '<li><em>torrent name:</em> possible names for the torrent</li>\n' \
+ '<li><em>info hash:</em> torrent identifier</li>\n' \
+ '<li><em>peers:</em> number of connected clients</li>\n' \
+ '<li><em>downloaded:</em> amount of data downloaded by all peers, this data may have been downloaded from a mirror or another peer</li>\n' \
+ '<li><em>uploaded:</em> amount of data uploaded by all peers, this is the amount of bandwidth that was saved from the mirrors</li>\n' \
+ '<li><em>saved:</em> percentage of data that was NOT downloaded from a mirror</li>\n' \
'</ul>\n')
s.write('</body>\n' \
- '</html>\n')
+ '</html>\n')
return (200, 'OK', {'Content-Type': 'text/html; charset=iso-8859-1'}, s.getvalue())
except:
logger.exception('Error generating info page')
@@ -758,7 +803,7 @@
"""
l = self.downloads[hash]
- n = self.completed.get(hash, 0)
+ n = self.stats.get(hash, {}).get('completed', 0)
c = self.seedcount[hash]
d = len(l) - c
f = {'complete': c, 'incomplete': d, 'downloaded': n}
@@ -896,7 +941,9 @@
peers = self.downloads.setdefault(infohash, {})
ts = self.times.setdefault(infohash, {})
- self.completed.setdefault(infohash, 0)
+ stats = self.stats.setdefault(infohash, {'completed': 0,
+ 'uploaded': 0L,
+ 'downloaded': 0L})
self.seedcount.setdefault(infohash, 0)
torrent_name = self.torrent_names.setdefault(infohash, [])
@@ -934,8 +981,8 @@
left = long(params('left',''))
if left < 0:
raise ValueError, 'invalid amount left'
- uploaded = long(params('uploaded',''))
- downloaded = long(params('downloaded',''))
+ uploaded = long(params('uploaded', 0L))
+ downloaded = long(params('downloaded', 0L))
if params('supportcrypto'):
supportcrypto = 1
try:
@@ -967,12 +1014,20 @@
if event == 'stopped':
if peer:
+ if uploaded > peer['uploaded']:
+ stats['uploaded'] += uploaded - peer['uploaded']
+ peer['uploaded'] = uploaded
+ if downloaded > peer['downloaded']:
+ stats['downloaded'] += downloaded - peer['downloaded']
+ peer['downloaded'] = downloaded
+
if auth:
self.delete_peer(infohash,myid)
elif not peer:
ts[myid] = clock()
peer = { 'ip': ip, 'port': port, 'left': left,
+ 'uploaded': uploaded, 'downloaded': downloaded,
'supportcrypto': supportcrypto,
'requirecrypto': requirecrypto }
if mykey:
@@ -994,7 +1049,7 @@
else:
peer['nat'] = 2**30
if event == 'completed':
- self.completed[infohash] += 1
+ stats['completed'] += 1
if not left:
self.seedcount[infohash] += 1
@@ -1006,7 +1061,7 @@
ts[myid] = clock()
if not left and peer['left']:
- self.completed[infohash] += 1
+ stats['completed'] += 1
self.seedcount[infohash] += 1
if not peer.get('nat', -1):
for bc in self.becache[infohash]:
@@ -1014,7 +1069,7 @@
bc[1][myid] = bc[0][myid]
del bc[0][myid]
elif left and not peer['left']:
- self.completed[infohash] -= 1
+ stats['completed'] -= 1
self.seedcount[infohash] -= 1
if not peer.get('nat', -1):
for bc in self.becache[infohash]:
@@ -1022,6 +1077,13 @@
bc[0][myid] = bc[1][myid]
del bc[1][myid]
peer['left'] = left
+
+ if uploaded > peer['uploaded']:
+ stats['uploaded'] += uploaded - peer['uploaded']
+ peer['uploaded'] = uploaded
+ if downloaded > peer['downloaded']:
+ stats['downloaded'] += downloaded - peer['downloaded']
+ peer['downloaded'] = downloaded
if port:
recheck = False
@@ -1608,8 +1670,16 @@
if (s < 1024):
r = str(s) + 'B'
+ elif (s < 10485):
+ r = str(int((s/1024.0)*100.0)/100.0) + 'KiB'
+ elif (s < 104857):
+ r = str(int((s/1024.0)*10.0)/10.0) + 'KiB'
elif (s < 1048576):
r = str(int(s/1024)) + 'KiB'
+ elif (s < 10737418L):
+ r = str(int((s/1048576.0)*100.0)/100.0) + 'MiB'
+ elif (s < 107374182L):
+ r = str(int((s/1048576.0)*10.0)/10.0) + 'MiB'
elif (s < 1073741824L):
r = str(int(s/1048576)) + 'MiB'
elif (s < 1099511627776L):
Modified: debtorrent/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/debian/changelog?rev=343&op=diff
==============================================================================
--- debtorrent/trunk/debian/changelog (original)
+++ debtorrent/trunk/debian/changelog Wed Jan 23 05:19:23 2008
@@ -6,7 +6,8 @@
- currently supported only by debian testing and unstable
- see http://wiki.debian.org/DebTorrent/UniquePieces for more info
* Add torrent names to the tracker display
- * Make the download/upload statistics last over restarts
+ * Make the download/upload statistics persist over restarts
+ * Report more and better statistics on the tracker's info page
-- Cameron Dale <camrdale at gmail.com> Tue, 22 Jan 2008 19:19:35 -0800
More information about the Debtorrent-commits
mailing list