Ticket #1162: download-progress.diff

File download-progress.diff, 5.1 KB (added by warner, at 2010-08-10T06:24:45Z)

v3 patch, more tests

  • src/allmydata/immutable/downloader/status.py

    diff --git a/src/allmydata/immutable/downloader/status.py b/src/allmydata/immutable/downloader/status.py
    index 5d60db0..3970ca1 100644
    a b class DownloadStatus: 
    157157    def get_size(self):
    158158        return self.size
    159159    def get_status(self):
    160         return "not impl yet" # TODO
     160        # mention all outstanding segment requests
     161        outstanding = set()
     162        errorful = set()
     163        for s_ev in self.segment_events:
     164            (etype, segnum, when, segstart, seglen, decodetime) = s_ev
     165            if etype == "request":
     166                outstanding.add(segnum)
     167            elif etype == "delivery":
     168                outstanding.remove(segnum)
     169            else: # "error"
     170                outstanding.remove(segnum)
     171                errorful.add(segnum)
     172        def join(segnums):
     173            if len(segnums) == 1:
     174                return "segment %s" % list(segnums)[0]
     175            else:
     176                return "segments %s" % (",".join([str(i)
     177                                                  for i in sorted(segnums)]))
     178        error_s = ""
     179        if errorful:
     180            error_s = "; errors on %s" % join(errorful)
     181        if outstanding:
     182            s = "fetching %s" % join(outstanding)
     183        else:
     184            s = "idle"
     185        return s + error_s
     186
    161187    def get_progress(self):
    162         return 0.1 # TODO
     188        # measure all read events that aren't completely done, return the
     189        # total percentage complete for them
     190        if not self.read_events:
     191            return 0.0
     192        total_outstanding, total_received = 0, 0
     193        for r_ev in self.read_events:
     194            (start, length, ign1, finishtime, bytes, ign2, ign3) = r_ev
     195            if finishtime is None:
     196                total_outstanding += length
     197                total_received += bytes
     198            # else ignore completed requests
     199        if not total_outstanding:
     200            return 1.0
     201        return 1.0 * total_received / total_outstanding
     202
    163203    def using_helper(self):
    164204        return False
    165205    def get_active(self):
  • src/allmydata/test/test_download.py

    diff --git a/src/allmydata/test/test_download.py b/src/allmydata/test/test_download.py
    index add4d24..71a556b 100644
    a b from allmydata.test.common import ShouldFailMixin 
    1616from allmydata.interfaces import NotEnoughSharesError, NoSharesError
    1717from allmydata.immutable.downloader.common import BadSegmentNumberError, \
    1818     BadCiphertextHashError, DownloadStopped
     19from allmydata.immutable.downloader.status import DownloadStatus
    1920from allmydata.codec import CRSDecoder
    2021from foolscap.eventual import fireEventually, flushEventualQueue
    2122
    class DownloadV2(_Base, unittest.TestCase): 
    12141215            return d
    12151216        d.addCallback(_uploaded)
    12161217        return d
     1218
     1219class Status(unittest.TestCase):
     1220    def test_status(self):
     1221        now = 12345.1
     1222        ds = DownloadStatus("si-1", 123)
     1223        self.failUnlessEqual(ds.get_status(), "idle")
     1224        ds.add_segment_request(0, now)
     1225        self.failUnlessEqual(ds.get_status(), "fetching segment 0")
     1226        ds.add_segment_delivery(0, now+1, 0, 1000, 2.0)
     1227        self.failUnlessEqual(ds.get_status(), "idle")
     1228        ds.add_segment_request(2, now+2)
     1229        ds.add_segment_request(1, now+2)
     1230        self.failUnlessEqual(ds.get_status(), "fetching segments 1,2")
     1231        ds.add_segment_error(1, now+3)
     1232        self.failUnlessEqual(ds.get_status(),
     1233                             "fetching segment 2; errors on segment 1")
     1234
     1235    def test_progress(self):
     1236        now = 12345.1
     1237        ds = DownloadStatus("si-1", 123)
     1238        self.failUnlessEqual(ds.get_progress(), 0.0)
     1239        e = ds.add_read_event(0, 1000, now)
     1240        self.failUnlessEqual(ds.get_progress(), 0.0)
     1241        e.update(500, 2.0, 2.0)
     1242        self.failUnlessEqual(ds.get_progress(), 0.5)
     1243        e.finished(now+2)
     1244        self.failUnlessEqual(ds.get_progress(), 1.0)
     1245
     1246        e1 = ds.add_read_event(1000, 2000, now+3)
     1247        e2 = ds.add_read_event(4000, 2000, now+3)
     1248        self.failUnlessEqual(ds.get_progress(), 0.0)
     1249        e1.update(1000, 2.0, 2.0)
     1250        self.failUnlessEqual(ds.get_progress(), 0.25)
     1251        e2.update(1000, 2.0, 2.0)
     1252        self.failUnlessEqual(ds.get_progress(), 0.5)
     1253        e1.update(1000, 2.0, 2.0)
     1254        e1.finished(now+4)
     1255        # now there is only one outstanding read, and it is 50% done
     1256        self.failUnlessEqual(ds.get_progress(), 0.5)
     1257        e2.update(1000, 2.0, 2.0)
     1258        e2.finished(now+5)
     1259        self.failUnlessEqual(ds.get_progress(), 1.0)
  • src/allmydata/test/test_web.py

    diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
    index dfaaabd..78b9902 100644
    a b def build_one_ds(): 
    8383    ds.add_segment_delivery(0, now+1, 0, 100, 0.5)
    8484    ds.add_segment_request(1, now+2)
    8585    ds.add_segment_error(1, now+3)
     86    # two outstanding requests
     87    ds.add_segment_request(2, now+4)
     88    ds.add_segment_request(3, now+5)
    8689
    8790    e = ds.add_dyhb_sent("serverid_a", now)
    8891    e.finished([1,2], now+1)