webish status: distinguish active uploads/downloads from recent ones

This commit is contained in:
Brian Warner 2008-02-26 15:35:28 -07:00
parent d4bf623b87
commit 301dd3d489
6 changed files with 89 additions and 14 deletions

View File

@ -336,6 +336,7 @@ class DownloadStatus:
self.progress = 0.0 self.progress = 0.0
self.paused = False self.paused = False
self.stopped = False self.stopped = False
self.active = True
def get_storage_index(self): def get_storage_index(self):
return self.storage_index return self.storage_index
@ -352,6 +353,8 @@ class DownloadStatus:
return status return status
def get_progress(self): def get_progress(self):
return self.progress return self.progress
def get_active(self):
return self.active
def set_storage_index(self, si): def set_storage_index(self, si):
self.storage_index = si self.storage_index = si
@ -367,7 +370,8 @@ class DownloadStatus:
self.stopped = stopped self.stopped = stopped
def set_progress(self, value): def set_progress(self, value):
self.progress = value self.progress = value
def set_active(self, value):
self.active = value
class FileDownloader: class FileDownloader:
implements(IPushProducer) implements(IPushProducer)
@ -392,6 +396,7 @@ class FileDownloader:
s.set_storage_index(self._storage_index) s.set_storage_index(self._storage_index)
s.set_size(self._size) s.set_size(self._size)
s.set_helper(False) s.set_helper(False)
s.set_active(True)
if IConsumer.providedBy(downloadable): if IConsumer.providedBy(downloadable):
downloadable.registerProducer(self, True) downloadable.registerProducer(self, True)
@ -448,6 +453,7 @@ class FileDownloader:
self._stopped = True self._stopped = True
if self._status: if self._status:
self._status.set_stopped(True) self._status.set_stopped(True)
self._status.set_active(False)
def start(self): def start(self):
self.log("starting download") self.log("starting download")
@ -465,6 +471,7 @@ class FileDownloader:
def _finished(res): def _finished(res):
if self._status: if self._status:
self._status.set_status("Finished") self._status.set_status("Finished")
self._status.set_active(False)
if IConsumer.providedBy(self._downloadable): if IConsumer.providedBy(self._downloadable):
self._downloadable.unregisterProducer() self._downloadable.unregisterProducer()
return res return res
@ -472,6 +479,7 @@ class FileDownloader:
def _failed(why): def _failed(why):
if self._status: if self._status:
self._status.set_status("Failed") self._status.set_status("Failed")
self._status.set_active(False)
self._output.fail(why) self._output.fail(why)
return why return why
d.addErrback(_failed) d.addErrback(_failed)
@ -809,6 +817,7 @@ class LiteralDownloader:
s.set_storage_index(None) s.set_storage_index(None)
s.set_helper(False) s.set_helper(False)
s.set_status("Done") s.set_status("Done")
s.set_active(False)
s.set_progress(1.0) s.set_progress(1.0)
def start(self): def start(self):

View File

@ -1420,6 +1420,8 @@ class IUploadStatus(Interface):
process has finished: for helper uploads this is dependent upon the process has finished: for helper uploads this is dependent upon the
helper providing progress reports. It might be reasonable to add all helper providing progress reports. It might be reasonable to add all
three numbers and report the sum to the user.""" 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): class IDownloadStatus(Interface):
def get_storage_index(): 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 """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 download that has completed. This value will remain at 0.0 until the
first byte of plaintext is pushed to the download target.""" 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): class NotCapableError(Exception):

View File

@ -377,7 +377,7 @@ class Web(WebMixin, unittest.TestCase):
def test_status(self): def test_status(self):
d = self.GET("/status") d = self.GET("/status")
def _check(res): def _check(res):
self.failUnless('Current Uploads and Downloads' in res) self.failUnless('Upload and Download Status' in res)
d.addCallback(_check) d.addCallback(_check)
return d return d

View File

@ -568,6 +568,7 @@ class UploadStatus:
self.helper = False self.helper = False
self.status = "Not started" self.status = "Not started"
self.progress = [0.0, 0.0, 0.0] self.progress = [0.0, 0.0, 0.0]
self.active = True
def get_storage_index(self): def get_storage_index(self):
return self.storage_index return self.storage_index
@ -579,6 +580,8 @@ class UploadStatus:
return self.status return self.status
def get_progress(self): def get_progress(self):
return tuple(self.progress) return tuple(self.progress)
def get_active(self):
return self.active
def set_storage_index(self, si): def set_storage_index(self, si):
self.storage_index = si self.storage_index = si
@ -591,6 +594,8 @@ class UploadStatus:
def set_progress(self, which, value): def set_progress(self, which, value):
# [0]: chk, [1]: ciphertext, [2]: encode+push # [0]: chk, [1]: ciphertext, [2]: encode+push
self.progress[which] = value self.progress[which] = value
def set_active(self, value):
self.active = value
class CHKUploader: class CHKUploader:
peer_selector_class = Tahoe2PeerSelector peer_selector_class = Tahoe2PeerSelector
@ -603,6 +608,7 @@ class CHKUploader:
self._storage_index = None self._storage_index = None
self._upload_status = UploadStatus() self._upload_status = UploadStatus()
self._upload_status.set_helper(False) self._upload_status.set_helper(False)
self._upload_status.set_active(True)
def log(self, *args, **kwargs): def log(self, *args, **kwargs):
if "parent" not in kwargs: if "parent" not in kwargs:
@ -629,6 +635,10 @@ class CHKUploader:
d1.addCallback(lambda key: self._compute_uri(res, key)) d1.addCallback(lambda key: self._compute_uri(res, key))
return d1 return d1
d.addCallback(_uploaded) d.addCallback(_uploaded)
def _done(res):
self._upload_status.set_active(False)
return res
d.addBoth(_done)
return d return d
def abort(self): def abort(self):
@ -758,6 +768,7 @@ class LiteralUploader:
s.set_storage_index(None) s.set_storage_index(None)
s.set_helper(False) s.set_helper(False)
s.set_progress(0, 1.0) s.set_progress(0, 1.0)
s.set_active(False)
def start(self, uploadable): def start(self, uploadable):
uploadable = IUploadable(uploadable) uploadable = IUploadable(uploadable)
@ -874,6 +885,7 @@ class AssistedUploader:
self._storage_index = None self._storage_index = None
self._upload_status = s = UploadStatus() self._upload_status = s = UploadStatus()
s.set_helper(True) s.set_helper(True)
s.set_active(True)
def log(self, msg, parent=None, **kwargs): def log(self, msg, parent=None, **kwargs):
if parent is None: if parent is None:
@ -900,6 +912,10 @@ class AssistedUploader:
d.addCallback(self._got_storage_index) d.addCallback(self._got_storage_index)
d.addCallback(self._contact_helper) d.addCallback(self._contact_helper)
d.addCallback(self._build_readcap) d.addCallback(self._build_readcap)
def _done(res):
self._upload_status.set_active(False)
return res
d.addBoth(_done)
return d return d
def _got_size(self, size): def _got_size(self, size):

View File

@ -8,11 +8,11 @@
</head> </head>
<body> <body>
<h1>Current Uploads and Downloads</h1> <h1>Upload and Download Status</h1>
<h2>Current Uploads:</h2> <h2>Active Uploads:</h2>
<table n:render="sequence" n:data="uploads" border="1"> <table n:render="sequence" n:data="active_uploads" border="1">
<tr n:pattern="header"> <tr n:pattern="header">
<td>Storage Index</td> <td>Storage Index</td>
<td>Helper?</td> <td>Helper?</td>
@ -31,11 +31,11 @@
<td><n:slot name="progress_encode"/></td> <td><n:slot name="progress_encode"/></td>
<td><n:slot name="status"/></td> <td><n:slot name="status"/></td>
</tr> </tr>
<tr n:pattern="empty"><td>No current uploads!</td></tr> <tr n:pattern="empty"><td>No active uploads!</td></tr>
</table> </table>
<h2>Current Downloads:</h2> <h2>Active Downloads:</h2>
<table n:render="sequence" n:data="downloads" border="1"> <table n:render="sequence" n:data="active_downloads" border="1">
<tr n:pattern="header"> <tr n:pattern="header">
<td>Storage Index</td> <td>Storage Index</td>
<td>Helper?</td> <td>Helper?</td>
@ -50,7 +50,50 @@
<td><n:slot name="progress"/></td> <td><n:slot name="progress"/></td>
<td><n:slot name="status"/></td> <td><n:slot name="status"/></td>
</tr> </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> </table>
<div>Return to the <a href="/">Welcome Page</a></div> <div>Return to the <a href="/">Welcome Page</a></div>

View File

@ -1567,11 +1567,14 @@ class UnlinkedPOSTCreateDirectory(rend.Page):
class Status(rend.Page): class Status(rend.Page):
docFactory = getxmlfile("status.xhtml") docFactory = getxmlfile("status.xhtml")
def data_uploads(self, ctx, data): def data_active_uploads(self, ctx, data):
return IClient(ctx).list_uploads() return [u for u in IClient(ctx).list_uploads() if u.get_active()]
def data_active_downloads(self, ctx, data):
def data_downloads(self, ctx, data): return [d for d in IClient(ctx).list_downloads() if d.get_active()]
return IClient(ctx).list_downloads() 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): def _render_common(self, ctx, data):
s = data s = data