From 124d531b41c0c4c08f71a1d8e5f2a18460707873 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Sun, 21 Jan 2007 13:31:16 -0700 Subject: [PATCH] filetree: mark leaf nodes by adding is_leaf_subtree(), stop traversing when we hit them, to make vdrive._get_file_uri() work --- src/allmydata/filetree/directory.py | 11 +++++++++++ src/allmydata/filetree/file.py | 6 ++++++ src/allmydata/filetree/interfaces.py | 21 +++++++++++++++++++++ src/allmydata/filetree/redirect.py | 6 ++++++ src/allmydata/filetree/vdrive.py | 2 +- src/allmydata/test/test_filetree_new.py | 4 ++-- 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/allmydata/filetree/directory.py b/src/allmydata/filetree/directory.py index 91613e6e..93a3f291 100644 --- a/src/allmydata/filetree/directory.py +++ b/src/allmydata/filetree/directory.py @@ -104,6 +104,8 @@ class SubTreeNode: child = node_maker.make_node_from_serialized(child_data) self.children[name] = child + def is_leaf_subtree(self): + return False class _DirectorySubTree(object): @@ -190,6 +192,9 @@ class LocalFileSubTreeNode(BaseDataNode): def set_base_data(self, data): self.filename = data + def is_leaf_subtree(self): + return False + class LocalFileSubTree(_DirectorySubTree): node_class = LocalFileSubTreeNode @@ -238,6 +243,9 @@ class CHKDirectorySubTreeNode(BaseDataNode): def get_uri(self): return self.uri + def is_leaf_subtree(self): + return False + class CHKDirectorySubTree(_DirectorySubTree): # maybe mutable, maybe not @@ -306,6 +314,9 @@ class SSKDirectorySubTreeNode(object): def set_write_capability(self, write_cap): self.write_cap = write_cap + def is_leaf_subtree(self): + return False + class SSKDirectorySubTree(_DirectorySubTree): node_class = SSKDirectorySubTreeNode diff --git a/src/allmydata/filetree/file.py b/src/allmydata/filetree/file.py index e08f2f9a..8dced32b 100644 --- a/src/allmydata/filetree/file.py +++ b/src/allmydata/filetree/file.py @@ -20,6 +20,9 @@ class CHKFileNode(BaseDataNode): def get_uri(self): return self.uri + def is_leaf_subtree(self): + return True + class SSKFileNode(object): implements(INode, IFileNode) prefix = "SSKFile" @@ -37,3 +40,6 @@ class SSKFileNode(object): def get_write_capability(self): return self.write_cap + def is_leaf_subtree(self): + return True + diff --git a/src/allmydata/filetree/interfaces.py b/src/allmydata/filetree/interfaces.py index 665d1b63..e39cd5c8 100644 --- a/src/allmydata/filetree/interfaces.py +++ b/src/allmydata/filetree/interfaces.py @@ -23,6 +23,27 @@ class INode(Interface): provides that same make_node_from_serialized function to create any internal child nodes that might be necessary.""" + def is_leaf_subtree(): + """Return True if this node does not refer to a traversable + subtree. When searching for the node that describes a path, the + search will stop at the first leaf node found. IFileNodes should + return True here. + """ +# TODO: there is a slightly confusing mixture of IDirectoryNodes and all +# other kinds of nodes. It is convenient to mix them because that way list() +# can point at nodes of all sorts, but IDirectoryNodes are very different +# than the rest (because they to not represent distinct subtrees). There +# might be a better way to factor this. + +# TODO: 'node' is a problematic term here. It refers to nodes in the graph of +# connected subtrees. It also refers to nodes in the graph of directories and +# links within a single subtree. And the interface named INode is +# unfortunately a homonym with "inode", the data structure we previously used +# to represent information about an uploaded file which was too large to keep +# locally (the list of blockids), which meant the inode itself was uploaded. +# We no longer use inodes, but using a word that sounds just like it may +# cause confusion. + class IFileNode(Interface): """This is a file which can be retrieved.""" # TODO: not sure which of these to provide.. should URIs contain "CHK" or diff --git a/src/allmydata/filetree/redirect.py b/src/allmydata/filetree/redirect.py index bfd54016..3e2f1086 100644 --- a/src/allmydata/filetree/redirect.py +++ b/src/allmydata/filetree/redirect.py @@ -19,6 +19,9 @@ class LocalFileRedirectionNode(BaseDataNode): def set_base_data(self, data): self.handle = data + def is_leaf_subtree(self): + return False + class _BaseRedirection(object): implements(ISubTree) @@ -231,6 +234,9 @@ class HTTPRedirectionNode(BaseDataNode): def set_base_data(self, data): self.url = data + def is_leaf_subtree(self): + return False + class HTTPRedirection(_BaseRedirection): node_class = HTTPRedirectionNode diff --git a/src/allmydata/filetree/vdrive.py b/src/allmydata/filetree/vdrive.py index 8a44f343..473257ca 100644 --- a/src/allmydata/filetree/vdrive.py +++ b/src/allmydata/filetree/vdrive.py @@ -106,7 +106,7 @@ class VirtualDrive(object): def _get_closest_node_1(self, subtree, path): (found_path, node, remaining_path) = subtree.get_node_for_path(path) parent_is_mutable = subtree.is_mutable() - if IDirectoryNode.providedBy(node): + if IDirectoryNode.providedBy(node) or node.is_leaf_subtree(): # traversal done return (node, remaining_path) # otherwise, we must open and recurse into a new subtree diff --git a/src/allmydata/test/test_filetree_new.py b/src/allmydata/test/test_filetree_new.py index 2f1eccb3..3d23f843 100644 --- a/src/allmydata/test/test_filetree_new.py +++ b/src/allmydata/test/test_filetree_new.py @@ -469,8 +469,8 @@ class Stuff(unittest.TestCase): {"c": child2, "d": child3}) d.addCallback(_listed4) - #d.addCallback(lambda res: v._get_file_uri(["b","c"])) - #d.addCallback(self.failUnlessEqual, "uri2") + d.addCallback(lambda res: v._get_file_uri(["b","c"])) + d.addCallback(self.failUnlessEqual, "uri2") d.addCallback(lambda res: v.list(["bogus"])) def _listed_bogus(res): -- 2.45.2