webish status: distinguish active uploads/downloads from recent ones
authorBrian Warner <warner@allmydata.com>
Tue, 26 Feb 2008 22:35:28 +0000 (15:35 -0700)
committerBrian Warner <warner@allmydata.com>
Tue, 26 Feb 2008 22:35:28 +0000 (15:35 -0700)
src/allmydata/download.py
src/allmydata/interfaces.py
src/allmydata/test/test_web.py
src/allmydata/upload.py
src/allmydata/web/status.xhtml
src/allmydata/webish.py

index 7632f1e0d00a56c3fa6106e7dd20c889cb46a970..60a3e4f14897ded2b7c659445aee570bb888427c 100644 (file)
@@ -336,6 +336,7 @@ class DownloadStatus:
         self.progress = 0.0
         self.paused = False
         self.stopped = False
+        self.active = True
 
     def get_storage_index(self):
         return self.storage_index
@@ -352,6 +353,8 @@ class DownloadStatus:
         return status
     def get_progress(self):
         return self.progress
+    def get_active(self):
+        return self.active
 
     def set_storage_index(self, si):
         self.storage_index = si
@@ -367,7 +370,8 @@ class DownloadStatus:
         self.stopped = stopped
     def set_progress(self, value):
         self.progress = value
-
+    def set_active(self, value):
+        self.active = value
 
 class FileDownloader:
     implements(IPushProducer)
@@ -392,6 +396,7 @@ class FileDownloader:
         s.set_storage_index(self._storage_index)
         s.set_size(self._size)
         s.set_helper(False)
+        s.set_active(True)
 
         if IConsumer.providedBy(downloadable):
             downloadable.registerProducer(self, True)
@@ -448,6 +453,7 @@ class FileDownloader:
         self._stopped = True
         if self._status:
             self._status.set_stopped(True)
+            self._status.set_active(False)
 
     def start(self):
         self.log("starting download")
@@ -465,6 +471,7 @@ class FileDownloader:
         def _finished(res):
             if self._status:
                 self._status.set_status("Finished")
+                self._status.set_active(False)
             if IConsumer.providedBy(self._downloadable):
                 self._downloadable.unregisterProducer()
             return res
@@ -472,6 +479,7 @@ class FileDownloader:
         def _failed(why):
             if self._status:
                 self._status.set_status("Failed")
+                self._status.set_active(False)
             self._output.fail(why)
             return why
         d.addErrback(_failed)
@@ -809,6 +817,7 @@ class LiteralDownloader:
         s.set_storage_index(None)
         s.set_helper(False)
         s.set_status("Done")
+        s.set_active(False)
         s.set_progress(1.0)
 
     def start(self):
index fe030101cefed2c362df5a658dde7f1f748abf6b..07d1cc7903445f83aa299d56f60ad11519447b7a 100644 (file)
@@ -1420,6 +1420,8 @@ class IUploadStatus(Interface):
         process has finished: for helper uploads this is dependent upon the
         helper providing progress reports. It might be reasonable to add all
         three numbers and report the sum to the user."""
+    def get_active():
+        """Return True if the upload is currently active, False if not."""
 
 class IDownloadStatus(Interface):
     def get_storage_index():
@@ -1439,6 +1441,8 @@ class IDownloadStatus(Interface):
         """Returns a float (from 0.0 to 1.0) describing the amount of the
         download that has completed. This value will remain at 0.0 until the
         first byte of plaintext is pushed to the download target."""
+    def get_active():
+        """Return True if the download is currently active, False if not."""
 
 
 class NotCapableError(Exception):
index 487b1bd3425f8a19a1528dc287225ffed3cc35e8..c78b0401de4bc1cf5cd3f14559f3ea9cc1019420 100644 (file)
@@ -377,7 +377,7 @@ class Web(WebMixin, unittest.TestCase):
     def test_status(self):
         d = self.GET("/status")
         def _check(res):
-            self.failUnless('Current Uploads and Downloads' in res)
+            self.failUnless('Upload and Download Status' in res)
         d.addCallback(_check)
         return d
 
index 8d7a633923387a859832273ff9521ae3f12a3150..bef05b92413760de52bee74e3c20f106a942f4e1 100644 (file)
@@ -568,6 +568,7 @@ class UploadStatus:
         self.helper = False
         self.status = "Not started"
         self.progress = [0.0, 0.0, 0.0]
+        self.active = True
 
     def get_storage_index(self):
         return self.storage_index
@@ -579,6 +580,8 @@ class UploadStatus:
         return self.status
     def get_progress(self):
         return tuple(self.progress)
+    def get_active(self):
+        return self.active
 
     def set_storage_index(self, si):
         self.storage_index = si
@@ -591,6 +594,8 @@ class UploadStatus:
     def set_progress(self, which, value):
         # [0]: chk, [1]: ciphertext, [2]: encode+push
         self.progress[which] = value
+    def set_active(self, value):
+        self.active = value
 
 class CHKUploader:
     peer_selector_class = Tahoe2PeerSelector
@@ -603,6 +608,7 @@ class CHKUploader:
         self._storage_index = None
         self._upload_status = UploadStatus()
         self._upload_status.set_helper(False)
+        self._upload_status.set_active(True)
 
     def log(self, *args, **kwargs):
         if "parent" not in kwargs:
@@ -629,6 +635,10 @@ class CHKUploader:
             d1.addCallback(lambda key: self._compute_uri(res, key))
             return d1
         d.addCallback(_uploaded)
+        def _done(res):
+            self._upload_status.set_active(False)
+            return res
+        d.addBoth(_done)
         return d
 
     def abort(self):
@@ -758,6 +768,7 @@ class LiteralUploader:
         s.set_storage_index(None)
         s.set_helper(False)
         s.set_progress(0, 1.0)
+        s.set_active(False)
 
     def start(self, uploadable):
         uploadable = IUploadable(uploadable)
@@ -874,6 +885,7 @@ class AssistedUploader:
         self._storage_index = None
         self._upload_status = s = UploadStatus()
         s.set_helper(True)
+        s.set_active(True)
 
     def log(self, msg, parent=None, **kwargs):
         if parent is None:
@@ -900,6 +912,10 @@ class AssistedUploader:
         d.addCallback(self._got_storage_index)
         d.addCallback(self._contact_helper)
         d.addCallback(self._build_readcap)
+        def _done(res):
+            self._upload_status.set_active(False)
+            return res
+        d.addBoth(_done)
         return d
 
     def _got_size(self, size):
index 5e4218773bbbe185f6bf596e06bc551408593f7f..62edf5f56dee75a7a82362deadcbcd88dfd71591 100644 (file)
@@ -8,11 +8,11 @@
   </head>
   <body>
 
-<h1>Current Uploads and Downloads</h1>
+<h1>Upload and Download Status</h1>
 
 
-<h2>Current Uploads:</h2>
-<table n:render="sequence" n:data="uploads" border="1">
+<h2>Active Uploads:</h2>
+<table n:render="sequence" n:data="active_uploads" border="1">
   <tr n:pattern="header">
     <td>Storage Index</td>
     <td>Helper?</td>
     <td><n:slot name="progress_encode"/></td>
     <td><n:slot name="status"/></td>
   </tr>
-  <tr n:pattern="empty"><td>No current uploads!</td></tr>
+  <tr n:pattern="empty"><td>No active uploads!</td></tr>
 </table>
 
-<h2>Current Downloads:</h2>
-<table n:render="sequence" n:data="downloads" border="1">
+<h2>Active Downloads:</h2>
+<table n:render="sequence" n:data="active_downloads" border="1">
   <tr n:pattern="header">
     <td>Storage Index</td>
     <td>Helper?</td>
     <td><n:slot name="progress"/></td>
     <td><n:slot name="status"/></td>
   </tr>
-  <tr n:pattern="empty"><td>No current downloads!</td></tr>
+  <tr n:pattern="empty"><td>No active downloads!</td></tr>
+</table>
+
+
+<h2>Recent Uploads:</h2>
+<table n:render="sequence" n:data="recent_uploads" border="1">
+  <tr n:pattern="header">
+    <td>Storage Index</td>
+    <td>Helper?</td>
+    <td>Total Size</td>
+    <td>Progress (Hash)</td>
+    <td>Progress (Ciphertext)</td>
+    <td>Progress (Encode+Push)</td>
+    <td>Status</td>
+  </tr>
+  <tr n:pattern="item" n:render="row_upload">
+    <td><n:slot name="si"/></td>
+    <td><n:slot name="helper"/></td>
+    <td><n:slot name="total_size"/></td>
+    <td><n:slot name="progress_hash"/></td>
+    <td><n:slot name="progress_ciphertext"/></td>
+    <td><n:slot name="progress_encode"/></td>
+    <td><n:slot name="status"/></td>
+  </tr>
+  <tr n:pattern="empty"><td>No recent uploads!</td></tr>
+</table>
+
+<h2>Recent Downloads:</h2>
+<table n:render="sequence" n:data="recent_downloads" border="1">
+  <tr n:pattern="header">
+    <td>Storage Index</td>
+    <td>Helper?</td>
+    <td>Total Size</td>
+    <td>Progress</td>
+    <td>Status</td>
+  </tr>
+  <tr n:pattern="item" n:render="row_download">
+    <td><n:slot name="si"/></td>
+    <td><n:slot name="helper"/></td>
+    <td><n:slot name="total_size"/></td>
+    <td><n:slot name="progress"/></td>
+    <td><n:slot name="status"/></td>
+  </tr>
+  <tr n:pattern="empty"><td>No recent downloads!</td></tr>
 </table>
 
 <div>Return to the <a href="/">Welcome Page</a></div>
index 06ec61c95dfd994eb7c76797221f2ba9c60af2d8..9ef58059eb134f3485342b8ec9fcbb9d615b1ba1 100644 (file)
@@ -1567,11 +1567,14 @@ class UnlinkedPOSTCreateDirectory(rend.Page):
 class Status(rend.Page):
     docFactory = getxmlfile("status.xhtml")
 
-    def data_uploads(self, ctx, data):
-        return IClient(ctx).list_uploads()
-
-    def data_downloads(self, ctx, data):
-        return IClient(ctx).list_downloads()
+    def data_active_uploads(self, ctx, data):
+        return [u for u in IClient(ctx).list_uploads() if u.get_active()]
+    def data_active_downloads(self, ctx, data):
+        return [d for d in IClient(ctx).list_downloads() if d.get_active()]
+    def data_recent_uploads(self, ctx, data):
+        return [u for u in IClient(ctx).list_uploads() if not u.get_active()]
+    def data_recent_downloads(self, ctx, data):
+        return [d for d in IClient(ctx).list_downloads() if not d.get_active()]
 
     def _render_common(self, ctx, data):
         s = data