tags 488415 + patch thanks The attached patch adds the total amount downloaded via HTTP to the status page like this:
--------------------------------- ... s|download/|downloaded (HTTP)/| ... | upload| uploaded| -+---------+------------------+-- ... 4| 0.0K/s| 15.0MiB (317KiB)|12 ... | 0.0K/s| 4.24MiB| -+---------+------------------+-- ... 1| 0.0K/s| 104MiB (0B)|1. ... | 0.0K/s| 9.63MiB| --------------------------------- HTTP downloading increases both the main "downloaded" stat and the one in brackets. Downgrading back to debtorrent-0.1.8 works fine. It will lose the HTTP count, but leave everything else OK. I haven't changed the version number of the state file to reflect the extra data. This patch and the one for #487829 should be able to go in either order; but for my development I've done this on top of #487829. Steve
Mon Jun 30 00:28:28 BST 2008 Steve Cotton <[EMAIL PROTECTED]> * #488415 Unnecessary but tidy correction to handling state files from 0.1.8 Mon Jun 30 00:09:54 BST 2008 Steve Cotton <[EMAIL PROTECTED]> * #488415 tiny bit of spelling and grammar Sun Jun 29 23:56:33 BST 2008 Steve Cotton <[EMAIL PROTECTED]> * #488415 Call a subtotal a subtotal Sun Jun 29 23:30:35 BST 2008 Steve Cotton <[EMAIL PROTECTED]> * #488415 Show the amount downloaded via HTTP Sun Jun 29 18:26:13 BST 2008 Steve Cotton <[EMAIL PROTECTED]> * #488415 debugging: remove debug code (still needs the implementation to be tidied) Sun Jun 29 18:13:42 BST 2008 Steve Cotton <[EMAIL PROTECTED]> * #488415 debugging: split the download total in to (downloaded by torrent) and (downloaded by HTTP) Partial change only - this has the initial (functional) prototype code, along with a lot of debugging. Need to remove the debugging. diff -rN -u old-debtorrent/debian/changelog new-debtorrent/debian/changelog --- old-debtorrent/debian/changelog 2008-06-30 00:31:03.000000000 +0100 +++ new-debtorrent/debian/changelog 2008-06-30 00:31:03.000000000 +0100 @@ -1,3 +1,9 @@ +debtorrent (0.1.8.steve2.2) norelease; urgency=low + + * Show the amount of data downloaded via HTTP (Closes: #488415) + + -- Steve Cotton <[EMAIL PROTECTED]> Sun, 29 Jun 2008 22:08:52 +0100 + debtorrent (0.1.8.steve2.1) norelease; urgency=low * Fix: download / upload stats are correct after diff -rN -u old-debtorrent/DebTorrent/BT1/AptListener.py new-debtorrent/DebTorrent/BT1/AptListener.py --- old-debtorrent/DebTorrent/BT1/AptListener.py 2008-06-30 00:31:03.000000000 +0100 +++ new-debtorrent/DebTorrent/BT1/AptListener.py 2008-06-30 00:31:03.000000000 +0100 @@ -275,7 +275,7 @@ '<th align="right">distributed copies</th>\n' \ '<th align="right">download/<br>\n' \ 'upload</th>\n' \ - '<th align="right">downloaded/<br>\n' \ + '<th align="right">downloaded (HTTP)/<br>\n' \ 'uploaded</th>\n' \ '<th align="right">size</th>\n' \ '<th align="right">time remaining</th>\n' \ @@ -289,13 +289,10 @@ # Display a table row for each running torrent for x in data: - ( name, hash, status, progress, peers, seeds, seedsmsg, dist, - uprate, dnrate, upamt, dnamt, size, t, msg ) = x - if self.allow_get: - linkname = '<a href="/file?info_hash=' + quote(hash) + '">' + name + '</a>' + linkname = '<a href="/file?info_hash=' + quote(x.id) + '">' + x.name + '</a>' else: - linkname = name + linkname = x.name s.write('<tr>\n' '<td>%s<br>\n' \ @@ -307,14 +304,14 @@ '<td align="right">%.3f</td>\n' \ '<td align="right">%0.1fK/s<br>\n' \ '%0.1fK/s</td>\n' \ - '<td align="right">%s<br>\n' \ + '<td align="right">%s (%s)<br>\n' \ '%s</td>\n' \ '<td align="right">%s</td>\n' \ '<td align="right">%s</td>\n' \ '<td>%s</td></tr>\n' \ - % (linkname, b2a_hex(hash), status, progress, peers, seeds, - dist, dnrate/1000, uprate/1000, size_format(dnamt), - size_format(upamt), size_format(size), hours(t), msg)) + % (linkname, b2a_hex(x.id), x.status, x.progress, x.numPeers, x.numSeeds, + x.numCopies, x.downRate/1000, x.upRate/1000, size_format(x.downTotal), size_format(x.httpDownTotal), + size_format(x.upTotal), size_format(x.size), hours(x.timeRemaining), x.errorMessage)) s.write('</table>\n' \ '<ul>\n' \ @@ -559,11 +556,8 @@ total_dnrate = 0 for x in data: - ( name, hash, status, progress, peers, seeds, seedsmsg, dist, - uprate, dnrate, upamt, dnamt, size, t, msg ) = x - - total_size += size - total_dnrate += dnrate + total_size += x.size + total_dnrate += x.downRate message += ' at ' + size_format(total_dnrate) + '/s' if total_dnrate > 0: diff -rN -u old-debtorrent/DebTorrent/BT1/Statistics.py new-debtorrent/DebTorrent/BT1/Statistics.py --- old-debtorrent/DebTorrent/BT1/Statistics.py 2008-06-30 00:31:03.000000000 +0100 +++ new-debtorrent/DebTorrent/BT1/Statistics.py 2008-06-30 00:31:03.000000000 +0100 @@ -1,5 +1,6 @@ # Written by Edward Keyes # Modified by Cameron Dale +# Modified by Steve Cotton # see LICENSE.txt for license information # # $Id: Statistics.py 266 2007-08-18 02:06:35Z camrdale-guest $ @@ -12,6 +13,71 @@ """Empty class to add arbitrary variables to.""" pass +class CookedStatistics: + """Information returned from LaunchMany.gather_statistics. + + These map to the similarly-named stats on the local HTTP + status page. + + The class is named "cooked" because much of this comes from + the raw data in C{Statistics_Response}. + + @type name: C{string} + @ivar name: The torrent name (dists_stable_main_binary-all etc.) + @type id: C{string} + @ivar id: Torrent identifier (the long-lived one). + @type status: C{string} + @ivar status: Local status message. + @type progress: C{string} + @ivar progress: This is a percentage, expressed as a string. + @type numPeers: C{int} + @ivar numPeers: Number of peers (excluding seeds). + @type numSeeds: C{int} + @ivar numSeeds: Number of seeds. + @type numCopies: C{float} + @ivar numCopies: Number of distributed copies. + @type upRate: C{float} + @ivar upRate: The rate that data is being uploaded. + @type downRate: C{float} + @ivar downRate: The rate that data is being downloaded, via any method. + @type upTotal: C{long} + @ivar upTotal: The amount uploaded. + @type downTotal: C{long} + @ivar downTotal: The amount downloaded, via any method. + @type downHttpTotal: C{long} + @ivar downHttpTotal: The amount downloaded via HTTP, this is also included in the downTotal. + @type size: C{long} + @ivar size: The size of the files already on disk, plus the amount queued for download. + @type timeRemaining: C{float} + @ivar timeRemaining: Estimated time for the download to complete (in hours). + @type errorMessage: C{string} + @ivar errorMessage: Last error message, if any. + + """ + + def __init__(self, name, id): + """Initialize. + + The torrent name and id always need to be supplied, + everything else can have sensible defaults. + + """ + + self.name = name + self.id = id + self.status = "" + self.progress = "0.0%" + self.numPeers = 0 + self.numSeeds = 0 + self.numCopies = 0 + self.upRate = 0.0 + self.downRate = 0.0 + self.upTotal = 0L + self.downTotal = 0L + self.httpDownTotal = 0L + self.size = 0L + self.timeRemaining = 0.0 + self.errorMessage = "" class Statistics: """Generate statistics for the swarm. @@ -162,6 +228,7 @@ s = Statistics_Response() s.upTotal = self.upmeasure.get_total() s.downTotal = self.downmeasure.get_total() + s.httpDownTotal = self.downmeasure.get_http_subtotal() s.last_failed = self.rerequest_lastfailed() s.external_connection_made = self.connecter.external_connection_made if s.downTotal > 0: diff -rN -u old-debtorrent/DebTorrent/CurrentRateMeasure.py new-debtorrent/DebTorrent/CurrentRateMeasure.py --- old-debtorrent/DebTorrent/CurrentRateMeasure.py 2008-06-30 00:31:03.000000000 +0100 +++ new-debtorrent/DebTorrent/CurrentRateMeasure.py 2008-06-30 00:31:03.000000000 +0100 @@ -10,7 +10,14 @@ class Measure: """The measurement of one rate. - + + This keeps track of both the current rate and the total + amount of data sent or received. + + For DebTorrent, it can keep a subtotal of the amount of data + transferred via HTTP. Currently the HTTP rate is not + calculated, just the total. + @type max_rate_period: C{float} @ivar max_rate_period: maximum amount of time to guess the current rate estimate represents @@ -22,10 +29,12 @@ @ivar rate: the latest calculated rate @type total: C{long} @ivar total: the total amount that went in to calculating the rate + @type httptotal: C{long} + @ivar httptotal: the total amount of HTTP data (also included in the total) """ - def __init__(self, max_rate_period, fudge = 1, saved_total = 0L): + def __init__(self, max_rate_period, fudge = 1, saved_total = 0L, http_total = 0L): """Initialize the measurement. @type max_rate_period: C{float} @@ -37,6 +46,8 @@ @type saved_total: C{long} @param saved_total: the saved amount measured from a previous run (optional, defaults to 0) + @param http_total: the saved amount measured from a previous run + (optional, defaults to 0) """ @@ -45,6 +56,7 @@ self.last = self.ratesince self.rate = 0.0 self.total = long(saved_total) + self.httptotal = long(http_total) def update_rate(self, amount): """Update the rate with new data. @@ -62,6 +74,20 @@ if self.ratesince < t - self.max_rate_period: self.ratesince = t - self.max_rate_period + def update_http_rate(self, amount): + """Update the rate with new data. + + This new data is added to the figures returned by all of + C{get_rate}, C{get_total} and C{get_http_subtotal}. + + @type amount: C{long} + @param amount: the new data to add into the rate calculation + + """ + + self.httptotal += amount + self.update_rate(amount) + def get_rate(self): """Get the current rate measurement. @@ -107,4 +133,14 @@ """ - return self.total \ No newline at end of file + return self.total + + def get_http_subtotal(self): + """Get the amount transferred via HTTP only + + @rtype: C{float} + @return: the total amount + + """ + + return self.httptotal diff -rN -u old-debtorrent/DebTorrent/download_bt1.py new-debtorrent/DebTorrent/download_bt1.py --- old-debtorrent/DebTorrent/download_bt1.py 2008-06-30 00:31:03.000000000 +0100 +++ new-debtorrent/DebTorrent/download_bt1.py 2008-06-30 00:31:03.000000000 +0100 @@ -905,7 +905,7 @@ else: self.pickled_data['resume data'] = {'priority': {}, 'files': {}} must_find_files = True - self.pickled_data['stats'] = {'upload': 0L, 'download': 0L} + self.pickled_data['stats'] = {'upload': 0L, 'download': 0L, 'download_http': 0L} self.pickled_data['version'] = 1 # Initialize the saved state it if it wasn't found @@ -913,7 +913,7 @@ must_find_files = True self.pickled_data = {} self.pickled_data['resume data'] = {'priority': {}, 'files': {}} - self.pickled_data['stats'] = {'upload': 0L, 'download': 0L} + self.pickled_data['stats'] = {'upload': 0L, 'download': 0L, 'download_http': 0L} self.pickled_data['version'] = 1 enabled_files = [] @@ -1099,7 +1099,7 @@ """ - self.downmeasure.update_rate(x) + self.downmeasure.update_http_rate(x) self.ratemeasure.data_came_in(x) self.downloader.external_data_received(x) @@ -1139,7 +1139,7 @@ @return: whether the engines were started """ - + if self.doneflag.isSet(): return False @@ -1162,9 +1162,13 @@ total_up = long(self.pickled_data['stats']['upload']) total_down = long(self.pickled_data['stats']['download']) + # The total_http stat isn't in files created with debtorrent-0.1.8 + total_http = 0L; + if self.pickled_data['stats'].has_key('download_http'): + total_http = long(self.pickled_data['stats']['download_http']) self.upmeasure = Measure(self.config['max_rate_period'], self.config['upload_rate_fudge'], saved_total = total_up) - self.downmeasure = Measure(self.config['max_rate_period'], saved_total = total_down) + self.downmeasure = Measure(self.config['max_rate_period'], saved_total = total_down, http_total = total_http) if ratelimiter: self.ratelimiter = ratelimiter @@ -1325,7 +1329,8 @@ if self.fileselector and self.started: torrentdata['version'] = 1 torrentdata['stats'] = {'upload': self.upmeasure.get_total(), - 'download': self.downmeasure.get_total()} + 'download': self.downmeasure.get_total(), + 'download_http': self.downmeasure.get_http_subtotal()} if not self.failed: self.fileselector.finish() torrentdata['resume data'] = self.fileselector.pickle() diff -rN -u old-debtorrent/DebTorrent/launchmanycore.py new-debtorrent/DebTorrent/launchmanycore.py --- old-debtorrent/DebTorrent/launchmanycore.py 2008-06-30 00:31:03.000000000 +0100 +++ new-debtorrent/DebTorrent/launchmanycore.py 2008-06-30 00:31:03.000000000 +0100 @@ -1,5 +1,6 @@ # Written by John Hoffman # Modified by Cameron Dale +# Modified by Steve Cotton # see LICENSE.txt for license information # # $Id: launchmanycore.py 389 2008-06-22 19:23:06Z camrdale-guest $ @@ -35,6 +36,7 @@ import logging from DebTorrent.BT1.AptListener import AptListener from DebTorrent.HTTPHandler import HTTPHandler +from DebTorrent.BT1.Statistics import CookedStatistics logger = logging.getLogger('DebTorrent.launchmanycore') @@ -413,20 +415,8 @@ def gather_stats(self): """Gather the statistics for the currently running torrents. - Returns a list, one per running torrent, of tuples: - - (C{string}, C{string}, C{string}, C{string}, - C{int}, C{int}, C{string}, C{float}, - C{float}, C{float}, C{long}, C{long}, - C{long}, C{float}, C{string}) - - Which are the name, info hash, current status, progress report, - number of peers, number of seeds, seed message, number of distributed copies, - upload rate, download rate, amount uploaded, amount downloaded, - total length, time remaining, and latest error message. - - @rtype: C{list} - @return: various statistics for the running torrents + @rtype: C{list} of C{CookedStatistics} + @return: A CookedStatistics for each of the running torrents """ @@ -438,60 +428,50 @@ name = cache['path'] else: name = cache['name'] - size = 0 + + cooked = CookedStatistics(name, id) d = self.downloads[hash] - progress = '0.0%' - peers = 0 - seeds = 0 - seedsmsg = "S" - dist = 0.0 - uprate = 0.0 - dnrate = 0.0 - upamt = 0 - dnamt = 0 - t = 0 if d.is_dead(): - status = 'stopped' + cooked.status = 'stopped' elif d.waiting: - status = 'waiting for hash check' + cooked.status = 'waiting for hash check' elif d.checking: - status = d.status_msg - progress = '%.1f%%' % (d.status_done*100) + cooked.status = d.status_msg + cooked.progress = '%.1f%%' % (d.status_done*100) else: stats = d.statsfunc() s = stats['stats'] if d.seed: - status = 'seeding' - progress = '100.0%' - seeds = s.numOldSeeds - seedsmsg = "s" - dist = s.numCopies + cooked.status = 'seeding' + cooked.progress = '100.0%' + cooked.numSeeds = s.numOldSeeds + cooked.numCopies = s.numCopies else: if s.numSeeds + s.numPeers: - t = stats['time'] - if t == 0: # unlikely - t = 0.01 - status = fmttime(t) + cooked.timeRemaining = stats['time'] + if cooked.timeRemaining == 0: # unlikely + cooked.timeRemaining = 0.01 + cooked.status = fmttime(cooked.timeRemaining) else: - t = -1 - status = 'connecting to peers' - progress = '%.1f%%' % (int(stats['frac']*1000)/10.0) - seeds = s.numSeeds - dist = s.numCopies2 - dnrate = stats['down'] - peers = s.numPeers - uprate = stats['up'] - upamt = s.upTotal - dnamt = s.downTotal - size = stats['wanted'] + cooked.timeRemaining = -1 + cooked.status = 'connecting to peers' + cooked.progress = '%.1f%%' % (int(stats['frac']*1000)/10.0) + cooked.numSeeds = s.numSeeds + cooked.numCopies = s.numCopies2 + cooked.downRate = stats['down'] + cooked.numPeers = s.numPeers + cooked.upRate = stats['up'] + cooked.upTotal = s.upTotal + cooked.downTotal = s.downTotal + cooked.httpDownTotal = s.httpDownTotal + cooked.size = stats['wanted'] if d.is_dead() or d.status_errtime+300 > clock(): - msg = d.status_err[-1] + cooked.errorMessage = d.status_err[-1] else: - msg = '' + cooked.errorMessage = '' - data.append(( name, id, status, progress, peers, seeds, seedsmsg, - dist, uprate, dnrate, upamt, dnamt, size, t, msg )) + data.append(cooked) return data