manifest: include stats in results. webapi is unchanged.
authorBrian Warner <warner@allmydata.com>
Wed, 19 Nov 2008 22:03:47 +0000 (15:03 -0700)
committerBrian Warner <warner@allmydata.com>
Wed, 19 Nov 2008 22:03:47 +0000 (15:03 -0700)
docs/frontends/webapi.txt
src/allmydata/dirnode.py
src/allmydata/interfaces.py
src/allmydata/test/test_dirnode.py
src/allmydata/test/test_system.py
src/allmydata/web/directory.py

index 2ecba41015b09a86a0b56bbbec8b4b3670bcae15..cfa96ea75a529bcc6a163e4be4818e42cbb7bffe 100644 (file)
@@ -964,11 +964,13 @@ POST $DIRURL?t=start-manifest    (must add &ophandle=XYZ)
   by a space.
 
   If output=JSON is added to the queryargs, then the results will be a
-  JSON-formatted dictionary with three keys:
+  JSON-formatted dictionary with four keys:
 
    finished (bool): if False then you must reload the page until True
    origin_si (str): the storage index of the starting point
    manifest: list of (path, cap) tuples, where path is a list of strings.
+   stats: a dictionary with the same keys as the t=deep-stats command
+          (described below)
 
 POST $DIRURL?t=start-deep-size    (must add &ophandle=XYZ)
 
index 86d23d08181a9727b4c4ba95e261ff9a67b9e10e..42db6ab23ddbf0567ee132c964ed16169684afbe 100644 (file)
@@ -536,21 +536,6 @@ class NewDirectoryNode:
         return self.deep_traverse(DeepChecker(self, verify, repair=True))
 
 
-class ManifestWalker:
-    def __init__(self, origin):
-        self.manifest = []
-        self.origin = origin
-    def set_monitor(self, monitor):
-        self.monitor = monitor
-        monitor.origin_si = self.origin.get_storage_index()
-        monitor.set_status(self.manifest)
-    def add_node(self, node, path):
-        self.manifest.append( (tuple(path), node.get_uri()) )
-    def enter_directory(self, parent, children):
-        pass
-    def finish(self):
-        return self.manifest
-
 
 class DeepStats:
     def __init__(self, origin):
@@ -651,6 +636,20 @@ class DeepStats:
     def finish(self):
         return self.get_results()
 
+class ManifestWalker(DeepStats):
+    def __init__(self, origin):
+        DeepStats.__init__(self, origin)
+        self.manifest = []
+
+    def add_node(self, node, path):
+        self.manifest.append( (tuple(path), node.get_uri()) )
+        return DeepStats.add_node(self, node, path)
+
+    def finish(self):
+        return {"manifest": self.manifest,
+                "stats": self.get_results(),
+                }
+
 
 class DeepChecker:
     def __init__(self, root, verify, repair):
index c678b07f76c9a9f1446fb1eb0b5e01d4bb437eee..885b29cbc3d8c050ee32250c179b147c2df7098f 100644 (file)
@@ -871,12 +871,18 @@ class IDirectoryNode(IMutableFilesystemNode):
         NoSuchChildError if I do not have a child by that name."""
 
     def build_manifest():
-        """Return a Monitor. The Monitor's results will be a list of (path,
-        cap) tuples for nodes (directories and files) reachable from this
-        one. 'path' will be a tuple of unicode strings. The origin dirnode
-        will be represented by an empty path tuple. The Monitor will also
-        have an .origin_si attribute with the (binary) storage index of the
-        starting point.
+        """I generate a table of everything reachable from this directory.
+        I also compute deep-stats as described below.
+
+        I return a Monitor. The Monitor's results will be a dictionary with
+        two elements. The 'manifest' element is a list of (path, cap) tuples
+        for nodes (directories and files) reachable from this one. 'path'
+        will be a tuple of unicode strings. The origin dirnode will be
+        represented by an empty path tuple. The 'stats' element is a
+        dictionary, the same that is generated by start_deep_stats() below.
+
+        The Monitor will also have an .origin_si attribute with the (binary)
+        storage index of the starting point.
         """
 
     def start_deep_stats():
index 3cf9408700a59bd29a72547cea42a7e07fcc4928..c838d6dde2c6e15c1b6dcce17990f7897a84626e 100644 (file)
@@ -335,12 +335,6 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin, testutil.StallMixin):
                           self.failUnlessEqual(sorted(children.keys()),
                                                sorted([u"child", u"subdir"])))
 
-            d.addCallback(lambda res: n.build_manifest().when_done())
-            def _check_manifest(manifest):
-                self.failUnlessEqual(sorted(manifest),
-                                     sorted(self.expected_manifest))
-            d.addCallback(_check_manifest)
-
             d.addCallback(lambda res: n.start_deep_stats().when_done())
             def _check_deepstats(stats):
                 self.failUnless(isinstance(stats, dict))
@@ -367,6 +361,15 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin, testutil.StallMixin):
                 self.failUnlessEqual(stats["size-files-histogram"], [])
             d.addCallback(_check_deepstats)
 
+            d.addCallback(lambda res: n.build_manifest().when_done())
+            def _check_manifest(res):
+                manifest = res["manifest"]
+                self.failUnlessEqual(sorted(manifest),
+                                     sorted(self.expected_manifest))
+                stats = res["stats"]
+                _check_deepstats(stats)
+            d.addCallback(_check_manifest)
+
             def _add_subsubdir(res):
                 return self.subdir.create_empty_directory(u"subsubdir")
             d.addCallback(_add_subsubdir)
index e3047f1f156e07b606420fd19f340ba73e9f8f8f..5cbf36c3189b3e28313d598460f5d22861c9f9d5 100644 (file)
@@ -684,8 +684,8 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
             d1.addCallback(lambda res: dnode.has_child(u"see recursive"))
             d1.addCallback(lambda answer: self.failUnlessEqual(answer, True))
             d1.addCallback(lambda res: dnode.build_manifest().when_done())
-            d1.addCallback(lambda manifest:
-                           self.failUnlessEqual(len(manifest), 1))
+            d1.addCallback(lambda res:
+                           self.failUnlessEqual(len(res["manifest"]), 1))
             return d1
         d.addCallback(_created_dirnode)
 
@@ -975,8 +975,8 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
             # P/personal/sekrit data
             # P/s2-rw  (same as P/s2-ro)
             # P/s2-rw/mydata992 (same as P/s2-rw/mydata992)
-            d1.addCallback(lambda manifest:
-                           self.failUnlessEqual(len(manifest), 5))
+            d1.addCallback(lambda res:
+                           self.failUnlessEqual(len(res["manifest"]), 5))
             d1.addCallback(lambda res: home.start_deep_stats().when_done())
             def _check_stats(stats):
                 expected = {"count-immutable-files": 1,
index 04f3ae747d5594860f8fc9b9d30cab0d873b3079..968356305e62b0d76a5cd268ba6024e67fa40784 100644 (file)
@@ -724,14 +724,15 @@ class ManifestResults(rend.Page, ReloadMixin):
         lines = []
         is_finished = self.monitor.is_finished()
         lines.append("finished: " + {True: "yes", False: "no"}[is_finished])
-        for (path, cap) in self.monitor.get_status():
+        for (path, cap) in self.monitor.get_status()["manifest"]:
             lines.append(self.slashify_path(path) + " " + cap)
         return "\n".join(lines) + "\n"
 
     def json(self, ctx):
         inevow.IRequest(ctx).setHeader("content-type", "text/plain")
         m = self.monitor
-        status = {"manifest": m.get_status(),
+        status = {"manifest": m.get_status()["manifest"],
+                  "stats": m.get_status()["stats"],
                   "finished": m.is_finished(),
                   "origin": base32.b2a(m.origin_si),
                   }
@@ -747,7 +748,7 @@ class ManifestResults(rend.Page, ReloadMixin):
         return T.p["Manifest of SI=%s" % self._si_abbrev()]
 
     def data_items(self, ctx, data):
-        return self.monitor.get_status()
+        return self.monitor.get_status()["manifest"]
 
     def render_row(self, ctx, (path, cap)):
         ctx.fillSlots("path", self.slashify_path(path))