From 2dcac796e93bf054dadfd1d8cf21005acd8b29e6 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Wed, 6 Feb 2008 13:19:51 -0700 Subject: [PATCH] add 'tahoe find-shares' command, to locate share files on a local node's disk --- src/allmydata/scripts/debug.py | 34 ++++++++++++++++++++++++++++++- src/allmydata/test/test_system.py | 14 +++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/allmydata/scripts/debug.py b/src/allmydata/scripts/debug.py index ea2fefbe..7e113a9d 100644 --- a/src/allmydata/scripts/debug.py +++ b/src/allmydata/scripts/debug.py @@ -21,6 +21,8 @@ def dump_share(config, out=sys.stdout, err=sys.stderr): from allmydata import uri, storage # check the version, to see if we have a mutable or immutable share + print >>out, "%19s: %s" % ("share filename", config['filename']) + f = open(config['filename'], "rb") prefix = f.read(32) f.close() @@ -315,14 +317,44 @@ def dump_uri_instance(u, nodeid, secret, out, err, show_header=True): else: print >>out, "unknown cap type" +class FindSharesOptions(usage.Options): + def parseArgs(self, storage_index_s, *nodedirs): + self.si_s = storage_index_s + self.nodedirs = nodedirs + +def find_shares(config, out=sys.stdout, err=sys.stderr): + """Given a storage index and a list of node directories, emit a list of + all matching shares to stdout, one per line. For example: + + find-shares.py 44kai1tui348689nrw8fjegc8c ~/testnet/node-* + + gives: + + /home/warner/testnet/node-1/storage/shares/44k/44kai1tui348689nrw8fjegc8c/5 + /home/warner/testnet/node-1/storage/shares/44k/44kai1tui348689nrw8fjegc8c/9 + /home/warner/testnet/node-2/storage/shares/44k/44kai1tui348689nrw8fjegc8c/2 + """ + from allmydata import storage + from allmydata.util import idlib + + sharedir = storage.storage_index_to_dir(idlib.a2b(config.si_s)) + for d in config.nodedirs: + d = os.path.join(os.path.expanduser(d), "storage/shares", sharedir) + if os.path.exists(d): + for shnum in os.listdir(d): + print >>out, os.path.join(d, shnum) + + return 0 subCommands = [ ["dump-share", None, DumpOptions, "Unpack and display the contents of a share (uri_extension and leases)."], - ["dump-cap", None, DumpCapOptions, "Unpack a read-cap or write-cap"] + ["dump-cap", None, DumpCapOptions, "Unpack a read-cap or write-cap"], + ["find-shares", None, FindSharesOptions, "Locate sharefiles in node dirs"], ] dispatch = { "dump-share": dump_share, "dump-cap": dump_cap, + "find-shares": find_shares, } diff --git a/src/allmydata/test/test_system.py b/src/allmydata/test/test_system.py index 8f669f6c..c307ef9d 100644 --- a/src/allmydata/test/test_system.py +++ b/src/allmydata/test/test_system.py @@ -1144,6 +1144,7 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase): # we only upload a single file, so we can assert some things about # its size and shares. + self.failUnless(("share filename: %s" % filename) in output) self.failUnless("size: %d\n" % len(self.data) in output) self.failUnless("num_segments: 1\n" in output) # segment_size is always a multiple of needed_shares @@ -1158,6 +1159,19 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase): "share_root_hash", "UEB_hash"): self.failUnless("%s: " % key in output, key) + # now use its storage index to find the other shares using the + # 'find-shares' tool + sharedir, shnum = os.path.split(filename) + storagedir, storage_index_s = os.path.split(sharedir) + out,err = StringIO(), StringIO() + nodedirs = [self.getdir("client%d" % i) for i in range(self.numclients)] + cmd = ["find-shares", storage_index_s] + nodedirs + rc = runner.runner(cmd, stdout=out, stderr=err) + self.failUnlessEqual(rc, 0) + out.seek(0) + sharefiles = [sfn.strip() for sfn in out.readlines()] + self.failUnlessEqual(len(sharefiles), 10) + def _test_control(self, res): # exercise the remote-control-the-client foolscap interfaces in # allmydata.control (mostly used for performance tests) -- 2.45.2