Ticket #1160: patch-2-fewer-downloadstatus.diff

File patch-2-fewer-downloadstatus.diff, 6.3 KB (added by warner, at 2010-08-09T23:10:10Z)

stop creating download-status objects for non-downloaded filenodes (v2)

  • src/allmydata/immutable/filenode.py

    diff --git a/src/allmydata/immutable/filenode.py b/src/allmydata/immutable/filenode.py
    index 44c8e95..ed3785b 100644
    a b import binascii 
    33import copy
    44import time
    55now = time.time
    6 from zope.interface import implements
     6from zope.interface import implements, Interface
    77from twisted.internet import defer
    88from twisted.internet.interfaces import IConsumer
    99
    from allmydata.immutable.repairer import Repairer 
    1919from allmydata.immutable.downloader.node import DownloadNode
    2020from allmydata.immutable.downloader.status import DownloadStatus
    2121
     22class IDownloadStatusHandlingConsumer(Interface):
     23    def set_download_status_read_event(read_ev):
     24        """Record the DownloadStatus 'read event', to be updated with the
     25        time it takes to decrypt each chunk of data."""
     26
    2227class CiphertextFileNode:
    2328    def __init__(self, verifycap, storage_broker, secret_holder,
    24                  terminator, history, download_status=None):
     29                 terminator, history):
    2530        assert isinstance(verifycap, uri.CHKFileVerifierURI)
    2631        self._verifycap = verifycap
    2732        self._storage_broker = storage_broker
    2833        self._secret_holder = secret_holder
    29         if download_status is None:
    30             ds = DownloadStatus(verifycap.storage_index, verifycap.size)
    31             if history:
    32                 history.add_download(ds)
    33             download_status = ds
    3434        self._terminator = terminator
    3535        self._history = history
    36         self._download_status = download_status
     36        self._download_status = None
    3737        self._node = None # created lazily, on read()
    3838
    3939    def _maybe_create_download_node(self):
     40        if not self._download_status:
     41            ds = DownloadStatus(self._verifycap.storage_index,
     42                                self._verifycap.size)
     43            if self._history:
     44                self._history.add_download(ds)
     45            self._download_status = ds
    4046        if self._node is None:
    4147            self._node = DownloadNode(self._verifycap, self._storage_broker,
    4248                                      self._secret_holder,
    4349                                      self._terminator,
    4450                                      self._history, self._download_status)
    4551
    46     def read(self, consumer, offset=0, size=None, read_ev=None):
     52    def read(self, consumer, offset=0, size=None):
    4753        """I am the main entry point, from which FileNode.read() can get
    4854        data. I feed the consumer with the desired range of ciphertext. I
    4955        return a Deferred that fires (with the consumer) when the read is
    5056        finished."""
    5157        self._maybe_create_download_node()
     58        actual_size = size
     59        if actual_size is None:
     60            actual_size = self._verifycap.size - offset
     61        read_ev = self._download_status.add_read_event(offset, actual_size,
     62                                                       now())
     63        if IDownloadStatusHandlingConsumer.providedBy(consumer):
     64            consumer.set_download_status_read_event(read_ev)
    5265        return self._node.read(consumer, offset, size, read_ev)
    5366
    5467    def get_segment(self, segnum):
    class CiphertextFileNode: 
    155168                    monitor=monitor)
    156169        return v.start()
    157170
    158 
    159171class DecryptingConsumer:
    160172    """I sit between a CiphertextDownloader (which acts as a Producer) and
    161173    the real Consumer, decrypting everything that passes by. The real
    162174    Consumer sees the real Producer, but the Producer sees us instead of the
    163175    real consumer."""
    164     implements(IConsumer)
     176    implements(IConsumer, IDownloadStatusHandlingConsumer)
    165177
    166     def __init__(self, consumer, readkey, offset, read_event):
     178    def __init__(self, consumer, readkey, offset):
    167179        self._consumer = consumer
    168         self._read_event = read_event
     180        self._read_event = None
    169181        # TODO: pycryptopp CTR-mode needs random-access operations: I want
    170182        # either a=AES(readkey, offset) or better yet both of:
    171183        #  a=AES(readkey, offset=0)
    class DecryptingConsumer: 
    177189        self._decryptor = AES(readkey, iv=iv)
    178190        self._decryptor.process("\x00"*offset_small)
    179191
     192    def set_download_status_read_event(self, read_ev):
     193        self._read_event = read_ev
     194
    180195    def registerProducer(self, producer, streaming):
    181196        # this passes through, so the real consumer can flow-control the real
    182197        # producer. Therefore we don't need to provide any IPushProducer
    class DecryptingConsumer: 
    188203    def write(self, ciphertext):
    189204        started = now()
    190205        plaintext = self._decryptor.process(ciphertext)
    191         elapsed = now() - started
    192         self._read_event.update(0, elapsed, 0)
     206        if self._read_event:
     207            elapsed = now() - started
     208            self._read_event.update(0, elapsed, 0)
    193209        self._consumer.write(plaintext)
    194210
    195211class ImmutableFileNode:
    class ImmutableFileNode: 
    200216                 history):
    201217        assert isinstance(filecap, uri.CHKFileURI)
    202218        verifycap = filecap.get_verify_cap()
    203         ds = DownloadStatus(verifycap.storage_index, verifycap.size)
    204         if history:
    205             history.add_download(ds)
    206         self._download_status = ds
    207219        self._cnode = CiphertextFileNode(verifycap, storage_broker,
    208                                          secret_holder, terminator, history, ds)
     220                                         secret_holder, terminator, history)
    209221        assert isinstance(filecap, uri.CHKFileURI)
    210222        self.u = filecap
    211223        self._readkey = filecap.key
    class ImmutableFileNode: 
    226238            return True
    227239
    228240    def read(self, consumer, offset=0, size=None):
    229         actual_size = size
    230         if actual_size == None:
    231             actual_size = self.u.size
    232         actual_size = actual_size - offset
    233         read_ev = self._download_status.add_read_event(offset,actual_size,
    234                                                        now())
    235         decryptor = DecryptingConsumer(consumer, self._readkey, offset, read_ev)
    236         d = self._cnode.read(decryptor, offset, size, read_ev)
     241        decryptor = DecryptingConsumer(consumer, self._readkey, offset)
     242        d = self._cnode.read(decryptor, offset, size)
    237243        d.addCallback(lambda dc: consumer)
    238244        return d
    239245