]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
web: add /status/?t=json, with active upload/download ops. Addresses #493.
authorBrian Warner <warner@allmydata.com>
Sat, 26 Jul 2008 00:41:10 +0000 (17:41 -0700)
committerBrian Warner <warner@allmydata.com>
Sat, 26 Jul 2008 00:41:10 +0000 (17:41 -0700)
docs/webapi.txt
src/allmydata/test/test_web.py
src/allmydata/web/status.py

index ea5a4ecaf30126ce86e7de723745bf0d4949c47c..44d16087bf0c29f557cb39fd29b9c0163b867f8a 100644 (file)
@@ -754,6 +754,45 @@ GET /status/
  that describes file sizes, servers that were involved, and the time consumed
  in each phase of the operation.
 
  that describes file sizes, servers that were involved, and the time consumed
  in each phase of the operation.
 
+ A GET of /status/?t=json will contain a machine-readable subset of the same
+ data. It returns a JSON-encoded dictionary. The only key defined at this
+ time is "active", with a value that is a list of operation dictionaries, one
+ for each active operation. Once an operation is completed, it will no longer
+ appear in data["active"] .
+
+ Each op-dict contains a "type" key, one of "upload", "download",
+ "mapupdate", "publish", or "retrieve" (the first two are for immutable
+ files, while the latter three are for mutable files and directories).
+
+ The "upload" op-dict will contain the following keys:
+
+   type (string): "upload"
+   storage-index-string (string): a base32-encoded storage index
+   total-size (int): total size of the file
+   status (string): current status of the operation
+   progress-hash (float): 1.0 when the file has been hashed
+   progress-ciphertext (float): 1.0 when the file has been encrypted.
+   progress-encode-push (float): 1.0 when the file has been encoded and
+                                 pushed to the storage servers. For helper
+                                 uploads, the ciphertext value climbs to 1.0
+                                 first, then encoding starts. For unassisted
+                                 uploads, ciphertext and encode-push progress
+                                 will climb at the same pace.
+
+ The "download" op-dict will contain the following keys:
+
+   type (string): "download"
+   storage-index-string (string): a base32-encoded storage index
+   total-size (int): total size of the file
+   status (string): current status of the operation
+   progress (float): 1.0 when the file has been fully downloaded
+
+ Front-ends which want to report progress information are advised to simply
+ average together all the progress-* indicators. A slightly more accurate
+ value can be found by ignoring the progress-hash value (since the current
+ implementation hashes synchronously, so clients will probably never see
+ progress-hash!=1.0).
+
 GET /provisioning/
 
  This page provides a basic tool to predict the likely storage and bandwidth
 GET /provisioning/
 
  This page provides a basic tool to predict the likely storage and bandwidth
index da1b5ec85d79b1fe5ee57f794eed57d4e7950321..b794f8d4dbc9dbb0b84d3a9a6bddae4f6f2da997 100644 (file)
@@ -438,6 +438,15 @@ class Web(WebMixin, unittest.TestCase):
             self.failUnless('"publish-%d"' % pub_num in res, res)
             self.failUnless('"retrieve-%d"' % ret_num in res, res)
         d.addCallback(_check)
             self.failUnless('"publish-%d"' % pub_num in res, res)
             self.failUnless('"retrieve-%d"' % ret_num in res, res)
         d.addCallback(_check)
+        d.addCallback(lambda res: self.GET("/status/?t=json"))
+        def _check_json(res):
+            data = simplejson.loads(res)
+            self.failUnless(isinstance(data, dict))
+            active = data["active"]
+            # TODO: test more. We need a way to fake an active operation
+            # here.
+        d.addCallback(_check_json)
+
         d.addCallback(lambda res: self.GET("/status/down-%d" % dl_num))
         def _check_dl(res):
             self.failUnless("File Download Status" in res, res)
         d.addCallback(lambda res: self.GET("/status/down-%d" % dl_num))
         def _check_dl(res):
             self.failUnless("File Download Status" in res, res)
index c2d429efc9cce652a400d3e0c65970c05abc353d..2c9bafaac91d6541b05bea1180739ab8fbeb5a8a 100644 (file)
@@ -772,6 +772,41 @@ class Status(rend.Page):
     docFactory = getxmlfile("status.xhtml")
     addSlash = True
 
     docFactory = getxmlfile("status.xhtml")
     addSlash = True
 
+    def renderHTTP(self, ctx):
+        t = get_arg(inevow.IRequest(ctx), "t")
+        if t == "json":
+            return self.json(ctx)
+        return rend.Page.renderHTTP(self, ctx)
+
+    def json(self, ctx):
+        inevow.IRequest(ctx).setHeader("content-type", "text/plain")
+        client = IClient(ctx)
+        data = {}
+        data["active"] = active = []
+        for s in self.data_active_operations(ctx, None):
+            si_s = base32.b2a_or_none(s.get_storage_index())
+            size = s.get_size()
+            status = s.get_status()
+            if IUploadStatus.providedBy(s):
+                h,c,e = s.get_progress()
+                active.append({"type": "upload",
+                               "storage-index-string": si_s,
+                               "total-size": size,
+                               "status": status,
+                               "progress-hash": h,
+                               "progress-ciphertext": c,
+                               "progress-encode-push": e,
+                               })
+            elif IDownloadStatus.providedBy(s):
+                active.append({"type": "download",
+                               "storage-index-string": si_s,
+                               "total-size": size,
+                               "status": status,
+                               "progress": s.get_progress(),
+                               })
+
+        return simplejson.dumps(data, indent=1)
+
     def _get_all_statuses(self, client):
         return itertools.chain(client.list_all_upload_statuses(),
                                client.list_all_download_statuses(),
     def _get_all_statuses(self, client):
         return itertools.chain(client.list_all_upload_statuses(),
                                client.list_all_download_statuses(),