more #514: pass a Monitor to all checker operations, make mutable-checker honor the cancel flag

This commit is contained in:
Brian Warner 2008-10-22 01:38:18 -07:00
parent 8178b10ef1
commit 977c6ac510
14 changed files with 106 additions and 107 deletions

View File

@ -224,11 +224,11 @@ class NewDirectoryNode:
def get_storage_index(self):
return self._uri._filenode_uri.storage_index
def check(self, verify=False):
def check(self, monitor, verify=False):
"""Perform a file check. See IChecker.check for details."""
return self._node.check(verify)
def check_and_repair(self, verify=False):
return self._node.check_and_repair(verify)
return self._node.check(monitor, verify)
def check_and_repair(self, monitor, verify=False):
return self._node.check_and_repair(monitor, verify)
def list(self):
"""I return a Deferred that fires with a dictionary mapping child
@ -669,10 +669,10 @@ class DeepChecker:
def add_node(self, node, childpath):
if self._repair:
d = node.check_and_repair(self._verify)
d = node.check_and_repair(self.monitor, self._verify)
d.addCallback(self._results.add_check_and_repair, childpath)
else:
d = node.check(self._verify)
d = node.check(self.monitor, self._verify)
d.addCallback(self._results.add_check, childpath)
d.addCallback(lambda ignored: self._stats.add_node(node, childpath))
return d

View File

@ -55,7 +55,7 @@ class FileNode(ImmutableFileNode):
def get_storage_index(self):
return self.u.storage_index
def check(self, verify=False):
def check(self, monitor, verify=False):
storage_index = self.u.storage_index
k = self.u.needed_shares
N = self.u.total_shares
@ -68,7 +68,7 @@ class FileNode(ImmutableFileNode):
v = self.checker_class(self._client, storage_index, k, N)
return v.start()
def check_and_repair(self, verify=False):
def check_and_repair(self, monitor, verify=False):
# this is a stub, to allow the deep-check tests to pass.
#raise NotImplementedError("not implemented yet")
from allmydata.checker_results import CheckAndRepairResults
@ -113,10 +113,10 @@ class LiteralFileNode(ImmutableFileNode):
def get_storage_index(self):
return None
def check(self, verify=False):
def check(self, monitor, verify=False):
return defer.succeed(None)
def check_and_repair(self, verify=False):
def check_and_repair(self, monitor, verify=False):
return defer.succeed(None)
def download(self, target):

View File

@ -422,23 +422,6 @@ class IFilesystemNode(Interface):
download. This may be None if there is no storage index (i.e. LIT
files)."""
def check(verify=False, repair=False):
"""Perform a file check. See IChecker.check for details.
The default mode is named 'check' and simply asks each server whether
or not it has a share, and believes the answers. If verify=True, this
switches into the 'verify' mode, in which every byte of every share
is retrieved, and all hashes are verified. This uses much more
network and disk bandwidth than simple checking, especially for large
files, but will catch disk errors.
The default repair=False argument means that files which are not
perfectly healthy will be reported, but not fixed. When repair=True,
the node will attempt to repair the file first. The results will
indicate the initial status of the file in either case. If repair was
attempted, the results will indicate that too.
"""
def is_readonly():
"""Return True if this reference provides mutable access to the given
file or directory (i.e. if you can modify it), or False if not. Note
@ -1450,13 +1433,17 @@ class IUploader(Interface):
"""TODO: how should this work?"""
class ICheckable(Interface):
def check(verify=False):
def check(monitor, verify=False):
"""Check upon my health, optionally repairing any problems.
This returns a Deferred that fires with an instance that provides
ICheckerResults, or None if the object is non-distributed (i.e. LIT
files).
The monitor will be checked periodically to see if the operation has
been cancelled. If so, no new queries will be sent, and the Deferred
will fire (with a OperationCancelledError) immediately.
Filenodes and dirnodes (which provide IFilesystemNode) are also
checkable. Instances that represent verifier-caps will be checkable
but not downloadable. Some objects (like LIT files) do not actually
@ -1480,22 +1467,22 @@ class ICheckable(Interface):
failures during retrieval, or is malicious or buggy, then
verification will detect the problem, but checking will not.
If repair=True, then a non-healthy result will cause an immediate
repair operation, to generate and upload new shares. After repair,
the file will be as healthy as we can make it. Details about what
sort of repair is done will be put in the checker results. My
Deferred will not fire until the repair is complete.
TODO: any problems seen during checking will be reported to the
health-manager.furl, a centralized object which is responsible for
figuring out why files are unhealthy so corrective action can be
taken.
"""
def check_and_repair(verify=False):
def check_and_repair(monitor, verify=False):
"""Like check(), but if the file/directory is not healthy, attempt to
repair the damage.
Any non-healthy result will cause an immediate repair operation, to
generate and upload new shares. After repair, the file will be as
healthy as we can make it. Details about what sort of repair is done
will be put in the check-and-repair results. The Deferred will not
fire until the repair is complete.
This returns a Deferred which fires with an instance of
ICheckAndRepairResults."""

View File

@ -11,8 +11,9 @@ from layout import unpack_share, SIGNED_PREFIX_LENGTH
class MutableChecker:
def __init__(self, node):
def __init__(self, node, monitor):
self._node = node
self._monitor = monitor
self.bad_shares = [] # list of (nodeid,shnum,failure)
self._storage_index = self._node.get_storage_index()
self.results = CheckerResults(self._storage_index)
@ -21,7 +22,7 @@ class MutableChecker:
def check(self, verify=False):
servermap = ServerMap()
u = ServermapUpdater(self._node, servermap, MODE_CHECK)
u = ServermapUpdater(self._node, self._monitor, servermap, MODE_CHECK)
d = u.update()
d.addCallback(self._got_mapupdate_results)
if verify:
@ -35,6 +36,7 @@ class MutableChecker:
# the file is healthy if there is exactly one recoverable version, it
# has at least N distinct shares, and there are no unrecoverable
# versions: all existing shares will be for the same version.
self._monitor.raise_if_cancelled()
self.best_version = None
num_recoverable = len(servermap.recoverable_versions())
if num_recoverable:
@ -68,7 +70,7 @@ class MutableChecker:
d = self._do_read(ss, peerid, self._storage_index, [shnum], readv)
d.addCallback(self._got_answer, peerid, servermap)
dl.append(d)
return defer.DeferredList(dl, fireOnOneErrback=True)
return defer.DeferredList(dl, fireOnOneErrback=True, consumeErrors=True)
def _do_read(self, ss, peerid, storage_index, shnums, readv):
# isolate the callRemote to a separate method, so tests can subclass
@ -149,6 +151,7 @@ class MutableChecker:
return counters
def _fill_checker_results(self, smap, r):
self._monitor.raise_if_cancelled()
r.set_servermap(smap.copy())
healthy = True
data = {}
@ -265,8 +268,8 @@ class MutableChecker:
class MutableCheckAndRepairer(MutableChecker):
def __init__(self, node):
MutableChecker.__init__(self, node)
def __init__(self, node, monitor):
MutableChecker.__init__(self, node, monitor)
self.cr_results = CheckAndRepairResults(self._storage_index)
self.cr_results.pre_repair_results = self.results
self.need_repair = False
@ -278,6 +281,7 @@ class MutableCheckAndRepairer(MutableChecker):
return d
def _maybe_repair(self, res):
self._monitor.raise_if_cancelled()
if not self.need_repair:
self.cr_results.post_repair_results = self.results
return

View File

@ -10,6 +10,7 @@ from allmydata.interfaces import IMutableFileNode, IMutableFileURI, \
from allmydata.util import hashutil, log
from allmydata.util.assertutil import precondition
from allmydata.uri import WriteableSSKFileURI
from allmydata.monitor import Monitor
from allmydata.immutable.encode import NotEnoughSharesError
from pycryptopp.publickey import rsa
from pycryptopp.cipher.aes import AES
@ -242,12 +243,12 @@ class MutableFileNode:
#################################
# ICheckable
def check(self, verify=False):
checker = self.checker_class(self)
def check(self, monitor, verify=False):
checker = self.checker_class(self, monitor)
return checker.check(verify)
def check_and_repair(self, verify=False):
checker = self.check_and_repairer_class(self)
def check_and_repair(self, monitor, verify=False):
checker = self.check_and_repairer_class(self, monitor)
return checker.check(verify)
#################################
@ -398,7 +399,7 @@ class MutableFileNode:
servermap = ServerMap()
return self._update_servermap(servermap, mode)
def _update_servermap(self, servermap, mode):
u = ServermapUpdater(self, servermap, mode)
u = ServermapUpdater(self, Monitor(), servermap, mode)
self._client.notify_mapupdate(u.get_status())
return u.update()

View File

@ -333,13 +333,14 @@ class ServerMap:
class ServermapUpdater:
def __init__(self, filenode, servermap, mode=MODE_READ):
def __init__(self, filenode, monitor, servermap, mode=MODE_READ):
"""I update a servermap, locating a sufficient number of useful
shares and remembering where they are located.
"""
self._node = filenode
self._monitor = monitor
self._servermap = servermap
self.mode = mode
self._running = True

View File

@ -46,7 +46,7 @@ class FakeCHKFileNode:
return self.my_uri
def get_verifier(self):
return IURI(self.my_uri).get_verifier()
def check(self, verify=False):
def check(self, monitor, verify=False):
r = CheckerResults(self.storage_index)
is_bad = self.bad_shares.get(self.storage_index, None)
data = {}
@ -58,7 +58,7 @@ class FakeCHKFileNode:
r.problems = []
r.set_data(data)
return defer.succeed(r)
def check_and_repair(self, verify=False):
def check_and_repair(self, monitor, verify=False):
d = self.check(verify)
def _got(cr):
r = CheckAndRepairResults(self.storage_index)
@ -149,7 +149,7 @@ class FakeMutableFileNode:
def get_storage_index(self):
return self.storage_index
def check(self, verify=False):
def check(self, monitor, verify=False):
r = CheckerResults(self.storage_index)
is_bad = self.bad_shares.get(self.storage_index, None)
data = {}
@ -165,7 +165,7 @@ class FakeMutableFileNode:
r.set_data(data)
return defer.succeed(r)
def check_and_repair(self, verify=False):
def check_and_repair(self, monitor, verify=False):
d = self.check(verify)
def _got(cr):
r = CheckAndRepairResults(self.storage_index)

View File

@ -9,6 +9,7 @@ from allmydata.interfaces import IURI, IClient, IMutableFileNode, \
INewDirectoryURI, IReadonlyNewDirectoryURI, IFileNode, \
ExistingChildError, IDeepCheckResults, IDeepCheckAndRepairResults
from allmydata.util import hashutil, testutil
from allmydata.monitor import Monitor
from allmydata.test.common import make_chk_file_uri, make_mutable_file_uri, \
FakeDirectoryNode, create_chk_filenode
from allmydata.checker_results import CheckerResults, CheckAndRepairResults
@ -127,7 +128,7 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin, testutil.StallMixin):
def test_check(self):
d = self.client.create_empty_dirnode()
d.addCallback(lambda dn: dn.check())
d.addCallback(lambda dn: dn.check(Monitor()))
def _done(res):
self.failUnless(res.is_healthy())
d.addCallback(_done)

View File

@ -1,6 +1,7 @@
from twisted.trial import unittest
from allmydata import uri
from allmydata.monitor import Monitor
from allmydata.immutable import filenode, download
from allmydata.mutable.node import MutableFileNode
from allmydata.util import hashutil
@ -115,12 +116,12 @@ class LiteralChecker(unittest.TestCase):
u = uri.LiteralFileURI(data=DATA)
fn1 = filenode.LiteralFileNode(u, None)
d = fn1.check()
d = fn1.check(Monitor())
def _check_checker_results(cr):
self.failUnlessEqual(cr, None)
d.addCallback(_check_checker_results)
d.addCallback(lambda res: fn1.check(verify=True))
d.addCallback(lambda res: fn1.check(Monitor(), verify=True))
d.addCallback(_check_checker_results)
return d

View File

@ -1,6 +1,7 @@
from allmydata.immutable import encode, upload
from allmydata.test.common import SystemTestMixin, ShareManglingMixin
from allmydata.util import testutil
from allmydata.monitor import Monitor
from allmydata.interfaces import IURI
from twisted.internet import defer
from twisted.trial import unittest
@ -280,7 +281,7 @@ class Test(ShareManglingMixin, unittest.TestCase):
# The following process of leaving 8 of the shares deleted and asserting that you can't
# repair it is more to test this test code than to test the Tahoe code...
def _then_repair(unused=None):
d2 = self.filenode.check_and_repair(verify=False)
d2 = self.filenode.check_and_repair(Monitor(), verify=False)
def _after_repair(checkandrepairresults):
prerepairres = checkandrepairresults.get_pre_repair_results()
postrepairres = checkandrepairresults.get_post_repair_results()
@ -323,7 +324,7 @@ class Test(ShareManglingMixin, unittest.TestCase):
def _check1(filenode):
before_check_reads = self._count_reads()
d2 = filenode.check(verify=False)
d2 = filenode.check(Monitor(), verify=False)
def _after_check(checkresults):
after_check_reads = self._count_reads()
self.failIf(after_check_reads - before_check_reads > 0, after_check_reads - before_check_reads)
@ -336,7 +337,7 @@ class Test(ShareManglingMixin, unittest.TestCase):
d.addCallback(lambda ignore: self.replace_shares({}, storage_index=self.uri.storage_index))
def _check2(ignored):
before_check_reads = self._count_reads()
d2 = self.filenode.check(verify=False)
d2 = self.filenode.check(Monitor(), verify=False)
def _after_check(checkresults):
after_check_reads = self._count_reads()
@ -360,7 +361,7 @@ class Test(ShareManglingMixin, unittest.TestCase):
def _check1(filenode):
before_check_reads = self._count_reads()
d2 = filenode.check(verify=True)
d2 = filenode.check(Monitor(), verify=True)
def _after_check(checkresults):
after_check_reads = self._count_reads()
# print "delta was ", after_check_reads - before_check_reads
@ -380,7 +381,7 @@ class Test(ShareManglingMixin, unittest.TestCase):
def _check2(ignored):
before_check_reads = self._count_reads()
d2 = self.filenode.check(verify=True)
d2 = self.filenode.check(Monitor(), verify=True)
def _after_check(checkresults):
after_check_reads = self._count_reads()
@ -435,7 +436,7 @@ class Test(ShareManglingMixin, unittest.TestCase):
before_repair_reads = self._count_reads()
before_repair_allocates = self._count_allocates()
d2 = filenode.check_and_repair(verify=False)
d2 = filenode.check_and_repair(Monitor(), verify=False)
def _after_repair(checkandrepairresults):
prerepairres = checkandrepairresults.get_pre_repair_results()
postrepairres = checkandrepairresults.get_post_repair_results()
@ -469,7 +470,7 @@ class Test(ShareManglingMixin, unittest.TestCase):
before_repair_reads = self._count_reads()
before_repair_allocates = self._count_allocates()
d2 = filenode.check_and_repair(verify=False)
d2 = filenode.check_and_repair(Monitor(), verify=False)
def _after_repair(checkandrepairresults):
prerepairres = checkandrepairresults.get_pre_repair_results()
postrepairres = checkandrepairresults.get_post_repair_results()
@ -496,7 +497,7 @@ class Test(ShareManglingMixin, unittest.TestCase):
before_repair_reads = self._count_reads()
before_repair_allocates = self._count_allocates()
d2 = filenode.check_and_repair(verify=False)
d2 = filenode.check_and_repair(Monitor(), verify=False)
def _after_repair(checkandrepairresults):
prerepairres = checkandrepairresults.get_pre_repair_results()
postrepairres = checkandrepairresults.get_post_repair_results()

View File

@ -13,6 +13,7 @@ from allmydata.util.hashutil import tagged_hash
from allmydata.util.fileutil import make_dirs
from allmydata.interfaces import IURI, IMutableFileURI, IUploadable, \
FileTooLargeError, IRepairResults
from allmydata.monitor import Monitor
from allmydata.test.common import ShouldFailMixin
from foolscap.eventual import eventually, fireEventually
from foolscap.logging import log
@ -698,12 +699,12 @@ class Servermap(unittest.TestCase, PublishMixin):
def make_servermap(self, mode=MODE_CHECK, fn=None):
if fn is None:
fn = self._fn
smu = ServermapUpdater(fn, ServerMap(), mode)
smu = ServermapUpdater(fn, Monitor(), ServerMap(), mode)
d = smu.update()
return d
def update_servermap(self, oldmap, mode=MODE_CHECK):
smu = ServermapUpdater(self._fn, oldmap, mode)
smu = ServermapUpdater(self._fn, Monitor(), oldmap, mode)
d = smu.update()
return d
@ -877,7 +878,7 @@ class Roundtrip(unittest.TestCase, testutil.ShouldFailMixin, PublishMixin):
def make_servermap(self, mode=MODE_READ, oldmap=None):
if oldmap is None:
oldmap = ServerMap()
smu = ServermapUpdater(self._fn, oldmap, mode)
smu = ServermapUpdater(self._fn, Monitor(), oldmap, mode)
d = smu.update()
return d
@ -1203,14 +1204,14 @@ class Checker(unittest.TestCase, CheckerMixin, PublishMixin):
def test_check_good(self):
d = self._fn.check()
d = self._fn.check(Monitor())
d.addCallback(self.check_good, "test_check_good")
return d
def test_check_no_shares(self):
for shares in self._storage._peers.values():
shares.clear()
d = self._fn.check()
d = self._fn.check(Monitor())
d.addCallback(self.check_bad, "test_check_no_shares")
return d
@ -1219,44 +1220,44 @@ class Checker(unittest.TestCase, CheckerMixin, PublishMixin):
for shnum in shares.keys():
if shnum > 0:
del shares[shnum]
d = self._fn.check()
d = self._fn.check(Monitor())
d.addCallback(self.check_bad, "test_check_not_enough_shares")
return d
def test_check_all_bad_sig(self):
corrupt(None, self._storage, 1) # bad sig
d = self._fn.check()
d = self._fn.check(Monitor())
d.addCallback(self.check_bad, "test_check_all_bad_sig")
return d
def test_check_all_bad_blocks(self):
corrupt(None, self._storage, "share_data", [9]) # bad blocks
# the Checker won't notice this.. it doesn't look at actual data
d = self._fn.check()
d = self._fn.check(Monitor())
d.addCallback(self.check_good, "test_check_all_bad_blocks")
return d
def test_verify_good(self):
d = self._fn.check(verify=True)
d = self._fn.check(Monitor(), verify=True)
d.addCallback(self.check_good, "test_verify_good")
return d
def test_verify_all_bad_sig(self):
corrupt(None, self._storage, 1) # bad sig
d = self._fn.check(verify=True)
d = self._fn.check(Monitor(), verify=True)
d.addCallback(self.check_bad, "test_verify_all_bad_sig")
return d
def test_verify_one_bad_sig(self):
corrupt(None, self._storage, 1, [9]) # bad sig
d = self._fn.check(verify=True)
d = self._fn.check(Monitor(), verify=True)
d.addCallback(self.check_bad, "test_verify_one_bad_sig")
return d
def test_verify_one_bad_block(self):
corrupt(None, self._storage, "share_data", [9]) # bad blocks
# the Verifier *will* notice this, since it examines every byte
d = self._fn.check(verify=True)
d = self._fn.check(Monitor(), verify=True)
d.addCallback(self.check_bad, "test_verify_one_bad_block")
d.addCallback(self.check_expected_failure,
CorruptShareError, "block hash tree failure",
@ -1265,7 +1266,7 @@ class Checker(unittest.TestCase, CheckerMixin, PublishMixin):
def test_verify_one_bad_sharehash(self):
corrupt(None, self._storage, "share_hash_chain", [9], 5)
d = self._fn.check(verify=True)
d = self._fn.check(Monitor(), verify=True)
d.addCallback(self.check_bad, "test_verify_one_bad_sharehash")
d.addCallback(self.check_expected_failure,
CorruptShareError, "corrupt hashes",
@ -1274,7 +1275,7 @@ class Checker(unittest.TestCase, CheckerMixin, PublishMixin):
def test_verify_one_bad_encprivkey(self):
corrupt(None, self._storage, "enc_privkey", [9]) # bad privkey
d = self._fn.check(verify=True)
d = self._fn.check(Monitor(), verify=True)
d.addCallback(self.check_bad, "test_verify_one_bad_encprivkey")
d.addCallback(self.check_expected_failure,
CorruptShareError, "invalid privkey",
@ -1285,7 +1286,7 @@ class Checker(unittest.TestCase, CheckerMixin, PublishMixin):
corrupt(None, self._storage, "enc_privkey", [9]) # bad privkey
readonly_fn = self._fn.get_readonly()
# a read-only node has no way to validate the privkey
d = readonly_fn.check(verify=True)
d = readonly_fn.check(Monitor(), verify=True)
d.addCallback(self.check_good,
"test_verify_one_bad_encprivkey_uncheckable")
return d
@ -1308,7 +1309,7 @@ class Repair(unittest.TestCase, PublishMixin, ShouldFailMixin):
self.old_shares = []
d = self.publish_one()
d.addCallback(self.copy_shares)
d.addCallback(lambda res: self._fn.check())
d.addCallback(lambda res: self._fn.check(Monitor()))
d.addCallback(lambda check_results: self._fn.repair(check_results))
def _check_results(rres):
self.failUnless(IRepairResults.providedBy(rres))
@ -1363,7 +1364,7 @@ class Repair(unittest.TestCase, PublishMixin, ShouldFailMixin):
self._set_versions({0:3,2:3,4:3,6:3,8:3,
1:4,3:4,5:4,7:4,9:4}))
d.addCallback(self.copy_shares)
d.addCallback(lambda res: self._fn.check())
d.addCallback(lambda res: self._fn.check(Monitor()))
def _try_repair(check_results):
ex = "There were multiple recoverable versions with identical seqnums, so force=True must be passed to the repair() operation"
d2 = self.shouldFail(MustForceRepairError, "test_merge", ex,
@ -1451,7 +1452,7 @@ class MultipleEncodings(unittest.TestCase):
def make_servermap(self, mode=MODE_READ, oldmap=None):
if oldmap is None:
oldmap = ServerMap()
smu = ServermapUpdater(self._fn, oldmap, mode)
smu = ServermapUpdater(self._fn, Monitor(), oldmap, mode)
d = smu.update()
return d
@ -1563,7 +1564,7 @@ class MultipleVersions(unittest.TestCase, PublishMixin, CheckerMixin):
d = self._fn.download_best_version()
d.addCallback(lambda res: self.failUnlessEqual(res, self.CONTENTS[4]))
# and the checker should report problems
d.addCallback(lambda res: self._fn.check())
d.addCallback(lambda res: self._fn.check(Monitor()))
d.addCallback(self.check_bad, "test_multiple_versions")
# but if everything is at version 2, that's what we should download

View File

@ -16,7 +16,7 @@ from allmydata.scripts import runner
from allmydata.interfaces import IDirectoryNode, IFileNode, IFileURI, \
ICheckerResults, ICheckAndRepairResults, IDeepCheckResults, \
IDeepCheckAndRepairResults
from allmydata.monitor import OperationCancelledError
from allmydata.monitor import Monitor, OperationCancelledError
from allmydata.mutable.common import NotMutableError
from allmydata.mutable import layout as mutable_layout
from foolscap import DeadReferenceError
@ -1689,21 +1689,21 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
ut = upload.Data("too big to be literal" * 200, convergence=None)
d = self._personal_node.add_file(u"big file", ut)
d.addCallback(lambda res: self._personal_node.check())
d.addCallback(lambda res: self._personal_node.check(Monitor()))
def _check_dirnode_results(r):
self.failUnless(r.is_healthy())
d.addCallback(_check_dirnode_results)
d.addCallback(lambda res: self._personal_node.check(verify=True))
d.addCallback(lambda res: self._personal_node.check(Monitor(), verify=True))
d.addCallback(_check_dirnode_results)
d.addCallback(lambda res: self._personal_node.get(u"big file"))
def _got_chk_filenode(n):
self.failUnless(isinstance(n, filenode.FileNode))
d = n.check()
d = n.check(Monitor())
def _check_filenode_results(r):
self.failUnless(r.is_healthy())
d.addCallback(_check_filenode_results)
d.addCallback(lambda res: n.check(verify=True))
d.addCallback(lambda res: n.check(Monitor(), verify=True))
d.addCallback(_check_filenode_results)
return d
d.addCallback(_got_chk_filenode)
@ -1711,11 +1711,11 @@ class SystemTest(SystemTestMixin, unittest.TestCase):
d.addCallback(lambda res: self._personal_node.get(u"sekrit data"))
def _got_lit_filenode(n):
self.failUnless(isinstance(n, filenode.LiteralFileNode))
d = n.check()
d = n.check(Monitor())
def _check_lit_filenode_results(r):
self.failUnlessEqual(r, None)
d.addCallback(_check_lit_filenode_results)
d.addCallback(lambda res: n.check(verify=True))
d.addCallback(lambda res: n.check(Monitor(), verify=True))
d.addCallback(_check_lit_filenode_results)
return d
d.addCallback(_got_lit_filenode)
@ -1993,45 +1993,45 @@ class DeepCheckWeb(SystemTestMixin, unittest.TestCase, WebErrorMixin):
def do_test_good(self, ignored):
d = defer.succeed(None)
# check the individual items
d.addCallback(lambda ign: self.root.check())
d.addCallback(lambda ign: self.root.check(Monitor()))
d.addCallback(self.check_is_healthy, self.root, "root")
d.addCallback(lambda ign: self.mutable.check())
d.addCallback(lambda ign: self.mutable.check(Monitor()))
d.addCallback(self.check_is_healthy, self.mutable, "mutable")
d.addCallback(lambda ign: self.large.check())
d.addCallback(lambda ign: self.large.check(Monitor()))
d.addCallback(self.check_is_healthy, self.large, "large")
d.addCallback(lambda ign: self.small.check())
d.addCallback(lambda ign: self.small.check(Monitor()))
d.addCallback(self.failUnlessEqual, None, "small")
# and again with verify=True
d.addCallback(lambda ign: self.root.check(verify=True))
d.addCallback(lambda ign: self.root.check(Monitor(), verify=True))
d.addCallback(self.check_is_healthy, self.root, "root")
d.addCallback(lambda ign: self.mutable.check(verify=True))
d.addCallback(lambda ign: self.mutable.check(Monitor(), verify=True))
d.addCallback(self.check_is_healthy, self.mutable, "mutable")
d.addCallback(lambda ign: self.large.check(verify=True))
d.addCallback(lambda ign: self.large.check(Monitor(), verify=True))
d.addCallback(self.check_is_healthy, self.large, "large",
incomplete=True)
d.addCallback(lambda ign: self.small.check(verify=True))
d.addCallback(lambda ign: self.small.check(Monitor(), verify=True))
d.addCallback(self.failUnlessEqual, None, "small")
# and check_and_repair(), which should be a nop
d.addCallback(lambda ign: self.root.check_and_repair())
d.addCallback(lambda ign: self.root.check_and_repair(Monitor()))
d.addCallback(self.check_and_repair_is_healthy, self.root, "root")
d.addCallback(lambda ign: self.mutable.check_and_repair())
d.addCallback(lambda ign: self.mutable.check_and_repair(Monitor()))
d.addCallback(self.check_and_repair_is_healthy, self.mutable, "mutable")
d.addCallback(lambda ign: self.large.check_and_repair())
d.addCallback(lambda ign: self.large.check_and_repair(Monitor()))
d.addCallback(self.check_and_repair_is_healthy, self.large, "large")
d.addCallback(lambda ign: self.small.check_and_repair())
d.addCallback(lambda ign: self.small.check_and_repair(Monitor()))
d.addCallback(self.failUnlessEqual, None, "small")
# check_and_repair(verify=True)
d.addCallback(lambda ign: self.root.check_and_repair(verify=True))
d.addCallback(lambda ign: self.root.check_and_repair(Monitor(), verify=True))
d.addCallback(self.check_and_repair_is_healthy, self.root, "root")
d.addCallback(lambda ign: self.mutable.check_and_repair(verify=True))
d.addCallback(lambda ign: self.mutable.check_and_repair(Monitor(), verify=True))
d.addCallback(self.check_and_repair_is_healthy, self.mutable, "mutable")
d.addCallback(lambda ign: self.large.check_and_repair(verify=True))
d.addCallback(lambda ign: self.large.check_and_repair(Monitor(), verify=True))
d.addCallback(self.check_and_repair_is_healthy, self.large, "large",
incomplete=True)
d.addCallback(lambda ign: self.small.check_and_repair(verify=True))
d.addCallback(lambda ign: self.small.check_and_repair(Monitor(), verify=True))
d.addCallback(self.failUnlessEqual, None, "small")

View File

@ -15,6 +15,7 @@ from allmydata.util import base32
from allmydata.uri import from_string_dirnode
from allmydata.interfaces import IDirectoryNode, IFileNode, IMutableFileNode, \
ExistingChildError
from allmydata.monitor import Monitor
from allmydata.web.common import text_plain, WebError, \
IClient, IOpHandleTable, NeedOperationHandleError, \
boolean_of_arg, get_arg, get_root, \
@ -344,10 +345,10 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
verify = boolean_of_arg(get_arg(req, "verify", "false"))
repair = boolean_of_arg(get_arg(req, "repair", "false"))
if repair:
d = self.node.check_and_repair(verify)
d = self.node.check_and_repair(Monitor(), verify)
d.addCallback(lambda res: CheckAndRepairResults(res))
else:
d = self.node.check(verify)
d = self.node.check(Monitor(), verify)
d.addCallback(lambda res: CheckerResults(res))
return d

View File

@ -9,6 +9,7 @@ from nevow import url, rend
from nevow.inevow import IRequest
from allmydata.interfaces import IDownloadTarget, ExistingChildError
from allmydata.monitor import Monitor
from allmydata.immutable.upload import FileHandle
from allmydata.immutable.filenode import LiteralFileNode
from allmydata.util import log
@ -264,10 +265,10 @@ class FileNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
if isinstance(self.node, LiteralFileNode):
return defer.succeed(LiteralCheckerResults())
if repair:
d = self.node.check_and_repair(verify)
d = self.node.check_and_repair(Monitor(), verify)
d.addCallback(lambda res: CheckAndRepairResults(res))
else:
d = self.node.check(verify)
d = self.node.check(Monitor(), verify)
d.addCallback(lambda res: CheckerResults(res))
return d