deep-check-and-repair: improve results and their HTML representation

This commit is contained in:
Brian Warner 2009-01-12 18:56:19 -07:00
parent 8f2ec16b2c
commit bf56e2bb51
4 changed files with 55 additions and 14 deletions

View 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)

View 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):

View 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

View File

@ -70,17 +70,21 @@
<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>