vdrive: add get_node_at_path(pathlist)

This commit is contained in:
Brian Warner 2007-06-28 11:00:03 -07:00
parent 13400e24ac
commit d6e732b65f
3 changed files with 160 additions and 36 deletions

View File

@ -679,6 +679,19 @@ class IVirtualDrive(Interface):
This returns a Deferred that fires with an IDirectoryNode instance This returns a Deferred that fires with an IDirectoryNode instance
corresponding to this client's private root directory.""" 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): def get_node(self, uri):
"""Transform a URI into an IDirectoryNode or IFileNode. """Transform a URI into an IDirectoryNode or IFileNode.

View File

@ -8,6 +8,7 @@ from allmydata import client, uri, download, upload
from allmydata.introducer_and_vdrive import IntroducerAndVdrive from allmydata.introducer_and_vdrive import IntroducerAndVdrive
from allmydata.util import idlib, fileutil, testutil from allmydata.util import idlib, fileutil, testutil
from allmydata.scripts import runner from allmydata.scripts import runner
from allmydata.interfaces import IDirectoryNode
from foolscap.eventual import flushEventualQueue from foolscap.eventual import flushEventualQueue
from twisted.python import log from twisted.python import log
from twisted.python.failure import Failure from twisted.python.failure import Failure
@ -104,7 +105,7 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase):
return defer.succeed(None) return defer.succeed(None)
def test_connections(self): def test_connections(self):
self.basedir = "test_system/SystemTest/test_connections" self.basedir = "system/SystemTest/test_connections"
d = self.set_up_nodes() d = self.set_up_nodes()
self.extra_node = None self.extra_node = None
d.addCallback(lambda res: self.add_extra_node(5)) d.addCallback(lambda res: self.add_extra_node(5))
@ -128,7 +129,7 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase):
del test_connections del test_connections
def test_upload_and_download(self): 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 # we use 4000 bytes of data, which will result in about 400k written
# to disk among all our simulated nodes # to disk among all our simulated nodes
DATA = "Some data to upload\n" * 200 DATA = "Some data to upload\n" * 200
@ -231,42 +232,131 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase):
# plaintext_hash check. # plaintext_hash check.
def test_vdrive(self): 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" self.data = DATA = "Some data to publish to the virtual drive\n"
d = self.set_up_nodes() d = self.set_up_nodes()
def _do_publish(res): d.addCallback(self.log, "starting publish")
log.msg("PUBLISHING") d.addCallback(self._do_publish)
ut = upload.Data(DATA) # at this point, we have the following global filesystem:
c0 = self.clients[0] # /
d1 = c0.getServiceNamed("vdrive").get_public_root() # /subdir1
d1.addCallback(lambda root: root.create_empty_directory("subdir1")) # /subdir1/mydata567
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] d.addCallback(self._bounce_client0)
d1 = c1.getServiceNamed("vdrive").get_public_root() d.addCallback(self.log, "bounced client0")
d1.addCallback(lambda root: root.get("subdir1"))
d1.addCallback(lambda subdir1: subdir1.get("mydata567")) d.addCallback(self._check_publish1)
d1.addCallback(lambda filenode: filenode.download_to_data()) d.addCallback(self.log, "did _check_publish1")
return d1 d.addCallback(self._check_publish2)
d.addCallback(_publish_done) d.addCallback(self.log, "did _check_publish2")
def _get_done(data): d.addCallback(self._do_publish_private)
log.msg("get finished") d.addCallback(self.log, "did _do_publish_private")
self.failUnlessEqual(data, DATA) # now we also have:
d.addCallback(_get_done) # ~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_web)
d.addCallback(self._test_runner) d.addCallback(self._test_runner)
return d return d
test_vdrive.timeout = 1100 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): def _test_web(self, res):
base = self.webish_url base = self.webish_url
d = getPage(base) d = getPage(base)

View File

@ -71,12 +71,6 @@ class VirtualDrive(service.MultiService):
d.addCallback(_got_directory) 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): def have_public_root(self):
return bool(self._global_uri) return bool(self._global_uri)
def get_public_root(self): def get_public_root(self):
@ -91,3 +85,30 @@ class VirtualDrive(service.MultiService):
return defer.fail(NoPrivateVirtualDriveError()) return defer.fail(NoPrivateVirtualDriveError())
return self.get_node(self._private_uri) 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