From d6e732b65f62b1a7421ec7906f1440718fabd6d8 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Thu, 28 Jun 2007 11:00:03 -0700 Subject: [PATCH] vdrive: add get_node_at_path(pathlist) --- src/allmydata/interfaces.py | 13 +++ src/allmydata/test/test_system.py | 152 ++++++++++++++++++++++++------ src/allmydata/vdrive.py | 33 +++++-- 3 files changed, 161 insertions(+), 37 deletions(-) diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py index 20d3ca93..af99b727 100644 --- a/src/allmydata/interfaces.py +++ b/src/allmydata/interfaces.py @@ -679,6 +679,19 @@ class IVirtualDrive(Interface): This returns a Deferred that fires with an IDirectoryNode instance corresponding to this client's private root directory.""" + def get_node_at_path(self, path): + """Transform a path into an IDirectoryNode or IFileNode. + + The path is a list of path-name elements, typically constructed by + doing userpath.split('/') . If the first element of this list is '~', + the rest will be interpreted relative to the local user's private + root directory. Otherwse it will be interpreted relative to the + global public root directory. + + This method returns a Deferred that fires with the node in question, + or errbacks with an IndexError if the target node could not be found. + """ + def get_node(self, uri): """Transform a URI into an IDirectoryNode or IFileNode. diff --git a/src/allmydata/test/test_system.py b/src/allmydata/test/test_system.py index 651dfc1f..5e6a248c 100644 --- a/src/allmydata/test/test_system.py +++ b/src/allmydata/test/test_system.py @@ -8,6 +8,7 @@ from allmydata import client, uri, download, upload from allmydata.introducer_and_vdrive import IntroducerAndVdrive from allmydata.util import idlib, fileutil, testutil from allmydata.scripts import runner +from allmydata.interfaces import IDirectoryNode from foolscap.eventual import flushEventualQueue from twisted.python import log from twisted.python.failure import Failure @@ -104,7 +105,7 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase): return defer.succeed(None) def test_connections(self): - self.basedir = "test_system/SystemTest/test_connections" + self.basedir = "system/SystemTest/test_connections" d = self.set_up_nodes() self.extra_node = None d.addCallback(lambda res: self.add_extra_node(5)) @@ -128,7 +129,7 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase): del test_connections def test_upload_and_download(self): - self.basedir = "test_system/SystemTest/test_upload_and_download" + self.basedir = "system/SystemTest/test_upload_and_download" # we use 4000 bytes of data, which will result in about 400k written # to disk among all our simulated nodes DATA = "Some data to upload\n" * 200 @@ -231,42 +232,131 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase): # plaintext_hash check. def test_vdrive(self): - self.basedir = "test_system/SystemTest/test_vdrive" + self.basedir = "system/SystemTest/test_vdrive" self.data = DATA = "Some data to publish to the virtual drive\n" d = self.set_up_nodes() - def _do_publish(res): - log.msg("PUBLISHING") - ut = upload.Data(DATA) - c0 = self.clients[0] - d1 = c0.getServiceNamed("vdrive").get_public_root() - d1.addCallback(lambda root: root.create_empty_directory("subdir1")) - d1.addCallback(lambda subdir1_node: - subdir1_node.add_file("mydata567", ut)) - def _stash_uri(filenode): - self.uri = filenode.get_uri() - return filenode - d1.addCallback(_stash_uri) - return d1 - d.addCallback(_do_publish) - def _publish_done(filenode): - log.msg("publish finished") - - c1 = self.clients[1] - d1 = c1.getServiceNamed("vdrive").get_public_root() - d1.addCallback(lambda root: root.get("subdir1")) - d1.addCallback(lambda subdir1: subdir1.get("mydata567")) - d1.addCallback(lambda filenode: filenode.download_to_data()) - return d1 - d.addCallback(_publish_done) - def _get_done(data): - log.msg("get finished") - self.failUnlessEqual(data, DATA) - d.addCallback(_get_done) + d.addCallback(self.log, "starting publish") + d.addCallback(self._do_publish) + # at this point, we have the following global filesystem: + # / + # /subdir1 + # /subdir1/mydata567 + + d.addCallback(self._bounce_client0) + d.addCallback(self.log, "bounced client0") + + d.addCallback(self._check_publish1) + d.addCallback(self.log, "did _check_publish1") + d.addCallback(self._check_publish2) + d.addCallback(self.log, "did _check_publish2") + d.addCallback(self._do_publish_private) + d.addCallback(self.log, "did _do_publish_private") + # now we also have: + # ~client0/personal/sekrit data + d.addCallback(self._check_publish_private) + d.addCallback(self.log, "did _check_publish_private") d.addCallback(self._test_web) d.addCallback(self._test_runner) return d test_vdrive.timeout = 1100 + def _do_publish(self, res): + ut = upload.Data(self.data) + c0 = self.clients[0] + d = c0.getServiceNamed("vdrive").get_public_root() + d.addCallback(lambda root: root.create_empty_directory("subdir1")) + d.addCallback(lambda subdir1_node: + subdir1_node.add_file("mydata567", ut)) + d.addCallback(self.log, "publish finished") + def _stash_uri(filenode): + self.uri = filenode.get_uri() + return filenode + d.addCallback(_stash_uri) + return d + + def _bounce_client0(self, res): + old_client0 = self.clients[0] + d = old_client0.disownServiceParent() + assert isinstance(d, defer.Deferred) + d.addCallback(self.log, "STOPPED") + def _stopped(res): + new_client0 = client.Client(basedir=self.getdir("client0")) + self.add_service(new_client0) + self.clients[0] = new_client0 + return self.wait_for_connections() + d.addCallback(_stopped) + d.addCallback(self.log, "CONNECTED") + def _connected(res): + # now find out where the web port was + l = self.clients[0].getServiceNamed("webish").listener + port = l._port.getHost().port + self.webish_url = "http://localhost:%d/" % port + d.addCallback(_connected) + d.addCallback(self.log, "GOT WEB LISTENER") + return d + + def log(self, res, msg): + #print msg + log.msg(msg) + return res + + def _do_publish_private(self, res): + ut = upload.Data(self.data) + vdrive0 = self.clients[0].getServiceNamed("vdrive") + d = vdrive0.get_node_at_path(["~"]) + d.addCallback(self.log, "GOT ~") + d.addCallback(lambda node: node.create_empty_directory("personal")) + d.addCallback(self.log, "made ~/personal") + d.addCallback(lambda node: node.add_file("sekrit data", ut)) + return d + + def _check_publish1(self, res): + # this one uses the iterative API + c1 = self.clients[1] + d = c1.getServiceNamed("vdrive").get_public_root() + d.addCallback(self.log, "check_publish1 got /") + d.addCallback(lambda root: root.get("subdir1")) + d.addCallback(lambda subdir1: subdir1.get("mydata567")) + d.addCallback(lambda filenode: filenode.download_to_data()) + d.addCallback(self.log, "get finished") + def _get_done(data): + self.failUnlessEqual(data, self.data) + d.addCallback(_get_done) + return d + + def _check_publish2(self, res): + # this one uses the path-based API + vdrive1 = self.clients[1].getServiceNamed("vdrive") + def get_path(path): + return vdrive1.get_node_at_path(path.split("/")) + d = get_path("subdir1") + d.addCallback(lambda dirnode: + self.failUnless(IDirectoryNode.providedBy(dirnode))) + d.addCallback(lambda res: get_path("subdir1/mydata567")) + d.addCallback(lambda filenode: filenode.download_to_data()) + d.addCallback(lambda data: self.failUnlessEqual(data, self.data)) + + d.addCallback(lambda res: get_path("subdir1/mydata567")) + def _got_filenode(filenode): + d1 = vdrive1.get_node(filenode.get_uri()) + d1.addCallback(self.failUnlessEqual, filenode) + return d1 + d.addCallback(_got_filenode) + return d + + def _check_publish_private(self, res): + # this one uses the path-based API + def get_path(path): + vdrive0 = self.clients[0].getServiceNamed("vdrive") + return vdrive0.get_node_at_path(path.split("/")) + d = get_path("~/personal") + d.addCallback(lambda dirnode: + self.failUnless(IDirectoryNode.providedBy(dirnode))) + d.addCallback(lambda res: get_path("~/personal/sekrit data")) + d.addCallback(lambda filenode: filenode.download_to_data()) + d.addCallback(lambda data: self.failUnlessEqual(data, self.data)) + return d + def _test_web(self, res): base = self.webish_url d = getPage(base) diff --git a/src/allmydata/vdrive.py b/src/allmydata/vdrive.py index aa22aaad..cb44d36f 100644 --- a/src/allmydata/vdrive.py +++ b/src/allmydata/vdrive.py @@ -71,12 +71,6 @@ class VirtualDrive(service.MultiService): d.addCallback(_got_directory) - def get_node(self, node_uri): - if uri.is_dirnode_uri(node_uri): - return dirnode.create_directory_node(self.parent, node_uri) - else: - return defer.succeed(dirnode.FileNode(node_uri, self.parent)) - def have_public_root(self): return bool(self._global_uri) def get_public_root(self): @@ -91,3 +85,30 @@ class VirtualDrive(service.MultiService): return defer.fail(NoPrivateVirtualDriveError()) return self.get_node(self._private_uri) + def get_node(self, node_uri): + if uri.is_dirnode_uri(node_uri): + return dirnode.create_directory_node(self.parent, node_uri) + else: + return defer.succeed(dirnode.FileNode(node_uri, self.parent)) + + + def get_node_at_path(self, path, root=None): + assert isinstance(path, (list, tuple)) + + if root is None: + if path and path[0] == "~": + d = self.get_private_root() + d.addCallback(lambda node: + self.get_node_at_path(path[1:], node)) + return d + d = self.get_public_root() + d.addCallback(lambda node: self.get_node_at_path(path, node)) + return d + + if path: + assert path[0] != "" + d = root.get(path[0]) + d.addCallback(lambda node: self.get_node_at_path(path[1:], node)) + return d + + return root -- 2.45.2