]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
deep-check-and-repair: improve results and their HTML representation
authorBrian Warner <warner@allmydata.com>
Tue, 13 Jan 2009 01:56:19 +0000 (18:56 -0700)
committerBrian Warner <warner@allmydata.com>
Tue, 13 Jan 2009 01:56:19 +0000 (18:56 -0700)
src/allmydata/immutable/filenode.py
src/allmydata/interfaces.py
src/allmydata/web/check_results.py
src/allmydata/web/deep-check-and-repair-results.xhtml

index 50fc996c1c2e05d5bcb0201aca0feacb9d144522..b2b63c5b3921d719c2c8aae36d020c043b54df98 100644 (file)
@@ -208,6 +208,8 @@ class FileNode(_ImmutableFileNodeBase, log.PrefixingLogMixin):
                 crr.post_repair_results = cr
                 return defer.succeed(crr)
             else:
+                crr.repair_attempted = True
+                crr.repair_successful = False # until proven successful
                 def _gather_repair_results(ur):
                     assert IUploadResults.providedBy(ur), ur
                     # clone the cr -- check results to form the basic of the prr -- post-repair results
@@ -222,14 +224,22 @@ class FileNode(_ImmutableFileNodeBase, log.PrefixingLogMixin):
                     prr.data['servers-responding'] = list(servers_responding)
                     prr.data['count-shares-good'] = len(sm)
                     prr.data['count-good-share-hosts'] = len(sm)
-                    prr.set_healthy(len(sm) >= self.u.total_shares)
+                    is_healthy = len(sm) >= self.u.total_shares
+                    prr.set_healthy(is_healthy)
+                    crr.repair_successful = is_healthy
                     prr.set_needs_rebalancing(len(sm) >= self.u.total_shares)
 
                     crr.post_repair_results = prr
                     return crr
+                def _repair_error(f):
+                    # as with mutable repair, I'm not sure if I want to pass
+                    # through a failure or not. TODO
+                    crr.repair_successful = False
+                    crr.repair_failure = f
+                    return f
                 r = Repairer(client=self._client, verifycap=verifycap, monitor=monitor)
                 d = r.start()
-                d.addCallback(_gather_repair_results)
+                d.addCallbacks(_gather_repair_results, _repair_error)
                 return d
 
         d.addCallback(_maybe_repair)
index f2be3e0c0bfe5b8b96d6acd726a5d941f9400ff9..563ba72c37a5ac627bce7869f52844e6193bf83b 100644 (file)
@@ -1833,6 +1833,11 @@ class IDeepCheckAndRepairResults(Interface):
         be slash-joined) to an ICheckAndRepairResults instance, one for each
         object that was checked."""
 
+    def get_results_for_storage_index(storage_index):
+        """Retrive the ICheckAndRepairResults instance for the given (binary)
+        storage index. Raises KeyError if there are no results for that
+        storage index."""
+
 
 class IRepairable(Interface):
     def repair(check_results):
index 7aea7d3bae5c6255b3209cbf69dfaaa68861951f..399db8896a2ad7f562871c88ceba49622e9cfa57 100644 (file)
@@ -10,6 +10,13 @@ from allmydata.interfaces import ICheckAndRepairResults, ICheckResults
 from allmydata.util import base32, idlib
 
 class ResultsBase:
+    def _join_pathstring(self, path):
+        if path:
+            pathstring = "/".join(self._html(path))
+        else:
+            pathstring = "<root>"
+        return pathstring
+
     def _render_results(self, ctx, cr):
         assert ICheckResults(cr)
         c = IClient(ctx)
@@ -266,7 +273,7 @@ class CheckAndRepairResults(CheckerBase, rend.Page, ResultsBase):
 
     def render_post_repair_results(self, ctx, data):
         cr = self._render_results(ctx, self.r.get_post_repair_results())
-        return ctx.tag[cr]
+        return ctx.tag[T.div["Post-Repair Checker Results:"], cr]
 
     def render_maybe_pre_repair_results(self, ctx, data):
         if self.r.get_repair_attempted():
@@ -358,7 +365,7 @@ class DeepCheckResults(rend.Page, ResultsBase, ReloadMixin):
         if summary:
             summary_text = ": " + summary
         summary_text += " [SI: %s]" % cr.get_storage_index_string()
-        return ctx.tag["/".join(self._html(path)), self._html(summary_text)]
+        return ctx.tag[self._join_pathstring(path), self._html(summary_text)]
 
 
     def render_servers_with_corrupt_shares_p(self, ctx, data):
@@ -413,11 +420,7 @@ class DeepCheckResults(rend.Page, ResultsBase, ReloadMixin):
 
     def render_object(self, ctx, data):
         path, r = data
-        if path:
-            pathstring = "/".join(self._html(path))
-        else:
-            pathstring = "<root>"
-        ctx.fillSlots("path", pathstring)
+        ctx.fillSlots("path", self._join_pathstring(path))
         ctx.fillSlots("healthy", str(r.is_healthy()))
         ctx.fillSlots("recoverable", str(r.is_recoverable()))
         storage_index = r.get_storage_index()
@@ -438,6 +441,19 @@ class DeepCheckAndRepairResults(rend.Page, ResultsBase, ReloadMixin):
         #self.r = results
         self.monitor = monitor
 
+    def childFactory(self, ctx, name):
+        if not name:
+            return self
+        # /operation/$OPHANDLE/$STORAGEINDEX provides detailed information
+        # about a specific file or directory that was checked
+        si = base32.a2b(name)
+        r = self.monitor.get_status()
+        try:
+            return CheckAndRepairResults(r.get_results_for_storage_index(si))
+        except KeyError:
+            raise WebError("No detailed results for SI %s" % html.escape(name),
+                           http.NOT_FOUND)
+
     def renderHTTP(self, ctx):
         if self.want_json(ctx):
             return self.json(ctx)
@@ -530,7 +546,8 @@ class DeepCheckAndRepairResults(rend.Page, ResultsBase, ReloadMixin):
 
     def render_problem(self, ctx, data):
         path, cr = data
-        return ["/".join(self._html(path)), ": ", self._html(cr.get_summary())]
+        return ctx.tag[self._join_pathstring(path), ": ",
+                       self._html(cr.get_summary())]
 
     def render_post_repair_problems_p(self, ctx, data):
         c = self.monitor.get_status().get_counters()
@@ -583,11 +600,16 @@ class DeepCheckAndRepairResults(rend.Page, ResultsBase, ReloadMixin):
 
     def render_object(self, ctx, data):
         path, r = data
-        ctx.fillSlots("path", "/".join(self._html(path)))
+        ctx.fillSlots("path", self._join_pathstring(path))
         ctx.fillSlots("healthy_pre_repair",
                       str(r.get_pre_repair_results().is_healthy()))
+        ctx.fillSlots("recoverable_pre_repair",
+                      str(r.get_pre_repair_results().is_recoverable()))
         ctx.fillSlots("healthy_post_repair",
                       str(r.get_post_repair_results().is_healthy()))
+        storage_index = r.get_storage_index()
+        ctx.fillSlots("storage_index",
+                      self._render_si_link(ctx, storage_index))
         ctx.fillSlots("summary",
                       self._html(r.get_pre_repair_results().get_summary()))
         return ctx.tag
index b171d7bf470f2f5aa5b73167d85ae475c64f3ddb..fac98855a90f7067f44e726c6b768a80343e878f 100644 (file)
 <div n:render="return" />
 
 <div>
-<table n:render="sequence" n:data="all_objects">
+<table n:render="sequence" n:data="all_objects" border="1">
   <tr n:pattern="header">
     <td>Relative Path</td>
-    <td>Healthy</td>
-    <td>Post-Repair</td>
+    <td>Healthy Pre-Repair</td>
+    <td>Recoverable Pre-Repair</td>
+    <td>Healthy Post-Repair</td>
+    <td>Storage Index</td>
     <td>Summary</td>
   </tr>
   <tr n:pattern="item" n:render="object">
     <td><n:slot name="path"/></td>
     <td><n:slot name="healthy_pre_repair"/></td>
+    <td><n:slot name="recoverable_pre_repair"/></td>
     <td><n:slot name="healthy_post_repair"/></td>
+    <td><n:slot name="storage_index"/></td>
     <td><n:slot name="summary"/></td>
   </tr>
 </table>