immutable repairer: fix DownUpConnector so that it satisfies short reads the were...
authorZooko O'Whielacronx <zooko@zooko.com>
Fri, 13 Feb 2009 00:04:47 +0000 (17:04 -0700)
committerZooko O'Whielacronx <zooko@zooko.com>
Fri, 13 Feb 2009 00:04:47 +0000 (17:04 -0700)
This is probably the cause of the very rare "loss of progress" bug.  This is tested by unit tests.  A recent patch changed this to errback instead of losing progress, and now this patch is changing it again to return a short read instead of errbacking.  Returning a short read is what the uploader (in encode.py) is expecting, when it is reading the last block of the ciphertext, which might be shorter than the other blocks.

src/allmydata/immutable/repairer.py

index 6f21da2e189d6aecdc44bc894fc0065763e4c922..d799c7ddce22738dbb0b47d4e50fb971f83156cc 100644 (file)
@@ -73,16 +73,6 @@ class Repairer(log.PrefixingLogMixin):
 
         return d
 
-class PrematureClose(Exception):
-    # Uploader asked DUC to read a certain number of bytes, and
-    # Downloader closed DUC before writing enough bytes to satisfy the
-    # read.
-    def __init__(self, requested, avail):
-        self.requested = requested
-        self.avail = avail
-    def __repr__(self):
-        return "<%s requested: %d, avail: %d>" % (self.__class__.__name__, self.requested, self.avail)
-
 class DownUpConnector(log.PrefixingLogMixin):
     implements(IEncryptedUploadable, IDownloadTarget, IConsumer)
     """ I act like an "encrypted uploadable" -- something that a local uploader can read
@@ -186,10 +176,9 @@ class DownUpConnector(log.PrefixingLogMixin):
         pass
     def close(self):
         self._closed_to_pusher = True
-        # Any reads which haven't been satisfied by now are not going to be satisfied.
-        while self.next_read_ds:
-            self.next_read_ds.popleft().errback(
-                PrematureClose(self.next_read_lens.popleft(), self.bufsiz))
+        # Any reads which haven't been satisfied by now are going to
+        # have to be satisfied with short reads.
+        self._satisfy_reads_if_possible()
 
     # methods to satisfy the IEncryptedUploader interface
     # (From the perspective of an uploader I am an IEncryptedUploadable.)