From d575ccba2864cbf701ff51ea76b7cf15b0f771ee Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Sun, 28 Aug 2011 01:09:31 -0700 Subject: [PATCH] Teach 'tahoe debug catalog-shares about MDMF. Closes #1507. --- src/allmydata/scripts/debug.py | 34 +++++++++++++++++++++++++++++- src/allmydata/test/test_mutable.py | 20 ++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/allmydata/scripts/debug.py b/src/allmydata/scripts/debug.py index a507b7cf..16e57b33 100644 --- a/src/allmydata/scripts/debug.py +++ b/src/allmydata/scripts/debug.py @@ -728,9 +728,12 @@ def describe_share(abs_sharefile, si_s, shnum_s, now, out): share_type = "unknown" f.seek(m.DATA_OFFSET) - if f.read(1) == "\x00": + version = f.read(1) + if version == "\x00": # this slot contains an SMDF share share_type = "SDMF" + elif version == "\x01": + share_type = "MDMF" if share_type == "SDMF": f.seek(m.DATA_OFFSET) @@ -752,6 +755,35 @@ def describe_share(abs_sharefile, si_s, shnum_s, now, out): (si_s, k, N, datalen, seqnum, base32.b2a(root_hash), expiration, quote_output(abs_sharefile)) + elif share_type == "MDMF": + from allmydata.mutable.layout import MDMFSlotReadProxy + fake_shnum = 0 + # TODO: factor this out with dump_MDMF_share() + class ShareDumper(MDMFSlotReadProxy): + def _read(self, readvs, force_remote=False, queue=False): + data = [] + for (where,length) in readvs: + f.seek(m.DATA_OFFSET+where) + data.append(f.read(length)) + return defer.succeed({fake_shnum: data}) + + p = ShareDumper(None, "fake-si", fake_shnum) + def extract(func): + stash = [] + # these methods return Deferreds, but we happen to know that + # they run synchronously when not actually talking to a + # remote server + d = func() + d.addCallback(stash.append) + return stash[0] + + verinfo = extract(p.get_verinfo) + (seqnum, root_hash, salt_to_use, segsize, datalen, k, N, prefix, + offsets) = verinfo + print >>out, "MDMF %s %d/%d %d #%d:%s %d %s" % \ + (si_s, k, N, datalen, + seqnum, base32.b2a(root_hash), + expiration, quote_output(abs_sharefile)) else: print >>out, "UNKNOWN mutable %s" % quote_output(abs_sharefile) diff --git a/src/allmydata/test/test_mutable.py b/src/allmydata/test/test_mutable.py index 45622220..6a4af6c0 100644 --- a/src/allmydata/test/test_mutable.py +++ b/src/allmydata/test/test_mutable.py @@ -2990,6 +2990,26 @@ class Version(GridTestMixin, unittest.TestCase, testutil.ShouldFailMixin, \ self.failUnless(" datalen: %d" % len(self.data) in lines, output) vcap = n.get_verify_cap().to_string() self.failUnless(" verify-cap: %s" % vcap in lines, output) + + cso = debug.CatalogSharesOptions() + cso.nodedirs = fso.nodedirs + cso.stdout = StringIO() + cso.stderr = StringIO() + debug.catalog_shares(cso) + shares = cso.stdout.getvalue().splitlines() + oneshare = shares[0] # all shares should be MDMF + self.failIf(oneshare.startswith("UNKNOWN"), oneshare) + self.failUnless(oneshare.startswith("MDMF"), oneshare) + fields = oneshare.split() + self.failUnlessEqual(fields[0], "MDMF") + self.failUnlessEqual(fields[1], storage_index) + self.failUnlessEqual(fields[2], "3/10") + self.failUnlessEqual(fields[3], "%d" % len(self.data)) + self.failUnless(fields[4].startswith("#1:"), fields[3]) + # the rest of fields[4] is the roothash, which depends upon + # encryption salts and is not constant. fields[5] is the + # remaining time on the longest lease, which is timing dependent. + # The rest of the line is the quoted pathname to the share. d.addCallback(_debug) return d -- 2.37.2