From: Brian Warner <warner@lothar.com>
Date: Fri, 9 Nov 2007 09:54:51 +0000 (-0700)
Subject: consolidate dirnode/filenode-creation code into Client
X-Git-Tag: allmydata-tahoe-0.7.0~236
X-Git-Url: https://git.rkrishnan.org/%5B/%5D%20//%22?a=commitdiff_plain;h=63233ecf37a1ba683d04846ab2b835992017174a;p=tahoe-lafs%2Ftahoe-lafs.git

consolidate dirnode/filenode-creation code into Client
---

diff --git a/src/allmydata/client.py b/src/allmydata/client.py
index 5fde8980..17d411de 100644
--- a/src/allmydata/client.py
+++ b/src/allmydata/client.py
@@ -20,6 +20,12 @@ from allmydata.introducer import IntroducerClient
 from allmydata.vdrive import VirtualDrive
 from allmydata.util import hashutil, idlib, testutil
 
+from allmydata.dirnode import FileNode
+from allmydata.dirnode2 import NewDirectoryNode
+from allmydata.mutable import MutableFileNode
+from allmydata.interfaces import IURI, INewDirectoryURI, IDirnodeURI, \
+     IFileURI, IMutableFileURI
+
 class Client(node.Node, Referenceable, testutil.PollMixin):
     implements(RIClient)
     PORTNUMFILE = "client.port"
@@ -209,28 +215,42 @@ class Client(node.Node, Referenceable, testutil.PollMixin):
         return d
 
 
+    # these four methods are the primitives for creating filenodes and
+    # dirnodes. The first takes a URI and produces a filenode or (new-style)
+    # dirnode. The other three create brand-new filenodes/dirnodes.
+
+    def create_node_from_uri(self, u):
+        # this returns synchronously. As a result, it cannot be used to
+        # create old-style dirnodes, since those contain a RemoteReference.
+        # This means that new-style dirnodes cannot contain old-style
+        # dirnodes as children.
+        u = IURI(u)
+        if INewDirectoryURI.providedBy(u):
+            # new-style dirnodes
+            return NewDirectoryNode(self).init_from_uri(u)
+        if IDirnodeURI.providedBy(u):
+            ## handles old-style dirnodes, both mutable and immutable
+            #return dirnode.create_directory_node(self, u)
+            raise RuntimeError("not possible, sorry")
+        if IFileURI.providedBy(u):
+            # CHK
+            return FileNode(u, self)
+        assert IMutableFileURI.providedBy(u)
+        return MutableFileNode(self).init_from_uri(u)
+
     def create_empty_dirnode(self):
-        from allmydata.dirnode2 import NewDirectoryNode
         n = NewDirectoryNode(self)
         d = n.create()
         d.addCallback(lambda res: n)
         return d
 
-    def create_dirnode_from_uri(self, u):
-        from allmydata.dirnode2 import NewDirectoryNode
-        return NewDirectoryNode(self).init_from_uri(u)
-
     def create_mutable_file(self, contents=""):
-        from allmydata.mutable import MutableFileNode
         n = MutableFileNode(self)
         d = n.create(contents)
         d.addCallback(lambda res: n)
         return d
 
-    def create_mutable_file_from_uri(self, u):
-        from allmydata.mutable import MutableFileNode
-        return MutableFileNode(self).init_from_uri(u)
+    def upload(self, uploadable):
+        uploader = self.getServiceNamed("uploader")
+        return uploader.upload(uploadable)
 
-    def create_file_from_uri(self, u):
-        from allmydata.mutable import FileNode
-        return FileNode(u, self)
diff --git a/src/allmydata/dirnode.py b/src/allmydata/dirnode.py
index dbbe18a3..5b199b04 100644
--- a/src/allmydata/dirnode.py
+++ b/src/allmydata/dirnode.py
@@ -290,7 +290,7 @@ class ImmutableDirectoryNode:
         if IDirnodeURI.providedBy(u):
             return create_directory_node(self._client, u)
         else:
-            return defer.succeed(FileNode(u, self._client))
+            return defer.succeed(self._client.create_node_from_uri(child_uri))
 
     def _split_uri(self, child_uri):
         u = IURI(child_uri)
diff --git a/src/allmydata/dirnode2.py b/src/allmydata/dirnode2.py
index 5cdec394..ec141437 100644
--- a/src/allmydata/dirnode2.py
+++ b/src/allmydata/dirnode2.py
@@ -5,11 +5,11 @@ from zope.interface import implements
 from twisted.internet import defer
 import simplejson
 from allmydata.interfaces import IMutableFileNode, IDirectoryNode,\
-     IMutableFileURI, INewDirectoryURI, IURI, IFileNode, NotMutableError, \
+     INewDirectoryURI, IFileNode, NotMutableError, \
      IVerifierURI
 from allmydata.util import hashutil
 from allmydata.util.hashutil import netstring
-from allmydata.dirnode import IntegrityCheckError, FileNode
+from allmydata.dirnode import IntegrityCheckError
 from allmydata.uri import NewDirectoryURI
 from allmydata.Crypto.Cipher import AES
 
@@ -94,14 +94,7 @@ class NewDirectoryNode:
         return plaintext
 
     def _create_node(self, child_uri):
-        u = IURI(child_uri)
-        if INewDirectoryURI.providedBy(u):
-            return self._client.create_dirnode_from_uri(u)
-        if IFileNode.providedBy(u):
-            return self._client.create_file_from_uri(u)
-        if IMutableFileURI.providedBy(u):
-            return self._client.create_mutable_file_from_uri(u)
-        raise TypeError("cannot handle '%s' URI" % (u.__class__,))
+        return self._client.create_node_from_uri(child_uri)
 
     def _unpack_contents(self, data):
         # the directory is serialized as a list of netstrings, one per child.
@@ -254,10 +247,9 @@ class NewDirectoryNode:
         the operation completes."""
         if self.is_readonly():
             return defer.fail(NotMutableError())
-        uploader = self._client.getServiceNamed("uploader")
-        d = uploader.upload(uploadable)
-        d.addCallback(lambda uri: self.set_node(name,
-                                                FileNode(uri, self._client)))
+        d = self._client.upload(uploadable)
+        d.addCallback(self._client.create_node_from_uri)
+        d.addCallback(lambda node: self.set_node(name, node))
         return d
 
     def delete(self, name):
diff --git a/src/allmydata/test/test_dirnode.py b/src/allmydata/test/test_dirnode.py
index 3ec6f342..18de497e 100644
--- a/src/allmydata/test/test_dirnode.py
+++ b/src/allmydata/test/test_dirnode.py
@@ -6,7 +6,7 @@ from twisted.internet import defer
 from twisted.python import failure
 from allmydata import uri, dirnode
 from allmydata.util import hashutil
-from allmydata.interfaces import IDirectoryNode, IDirnodeURI
+from allmydata.interfaces import IDirectoryNode, IDirnodeURI, IURI, IFileURI
 from allmydata.scripts import runner
 from allmydata.dirnode import VirtualDriveServer, \
      BadWriteEnablerError, NoPublicRootError
@@ -118,6 +118,11 @@ class MyClient:
     def __init__(self, vds, myfurl):
         self.tub = MyTub(vds, myfurl)
 
+    def create_node_from_uri(self, u):
+        u = IURI(u)
+        assert IFileURI.providedBy(u)
+        return dirnode.FileNode(u, self)
+
 class Test(unittest.TestCase):
     def test_create_directory(self):
         basedir = "vdrive/test_create_directory/vdrive"
diff --git a/src/allmydata/test/test_mutable.py b/src/allmydata/test/test_mutable.py
index f3a7abfc..1499a0d4 100644
--- a/src/allmydata/test/test_mutable.py
+++ b/src/allmydata/test/test_mutable.py
@@ -7,6 +7,8 @@ from allmydata import mutable, uri, dirnode2
 from allmydata.dirnode2 import split_netstring
 from allmydata.util.hashutil import netstring, tagged_hash
 from allmydata.encode import NotEnoughPeersError
+from allmydata.interfaces import IURI, INewDirectoryURI, IDirnodeURI, \
+     IMutableFileURI
 
 import sha
 from allmydata.Crypto.Util.number import bytes_to_long
@@ -113,7 +115,21 @@ class MyClient:
         d = n.create(contents)
         d.addCallback(lambda res: n)
         return d
-    def create_mutable_file_from_uri(self, u):
+
+    def create_node_from_uri(self, u):
+        # this returns synchronously. As a result, it cannot be used to
+        # create old-style dirnodes, since those contain a RemoteReference.
+        # This means that new-style dirnodes cannot contain old-style
+        # dirnodes as children.
+        u = IURI(u)
+        if INewDirectoryURI.providedBy(u):
+            return self.create_dirnode_from_uri(u)
+        if IDirnodeURI.providedBy(u):
+            raise RuntimeError("not possible, sorry")
+        #if IFileURI.providedBy(u):
+        #    # CHK
+        #    return FileNode(u, self)
+        assert IMutableFileURI.providedBy(u)
         return FakeFilenode(self).init_from_uri(u)
 
     def get_permuted_peers(self, key, include_myself=True):
diff --git a/src/allmydata/test/test_system.py b/src/allmydata/test/test_system.py
index 8514aca4..20515bcf 100644
--- a/src/allmydata/test/test_system.py
+++ b/src/allmydata/test/test_system.py
@@ -338,7 +338,7 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase):
             # on the same client that uploaded the data.
             uri = self._mutable_node_1.get_uri()
             log.msg("starting retrieve1")
-            newnode = self.clients[0].create_mutable_file_from_uri(uri)
+            newnode = self.clients[0].create_node_from_uri(uri)
             return newnode.download_to_data()
         d.addCallback(_check_download_1)
 
@@ -346,7 +346,7 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase):
             self.failUnlessEqual(res, DATA)
             # same thing, but with a different client
             uri = self._mutable_node_1.get_uri()
-            newnode = self.clients[1].create_mutable_file_from_uri(uri)
+            newnode = self.clients[1].create_node_from_uri(uri)
             log.msg("starting retrieve2")
             d1 = newnode.download_to_data()
             d1.addCallback(lambda res: (res, newnode))
@@ -367,8 +367,8 @@ class SystemTest(testutil.SignalMixin, unittest.TestCase):
             # now create an even newer node and replace the data on it. This
             # new node has never been used for download before.
             uri = self._mutable_node_1.get_uri()
-            newnode1 = self.clients[2].create_mutable_file_from_uri(uri)
-            newnode2 = self.clients[3].create_mutable_file_from_uri(uri)
+            newnode1 = self.clients[2].create_node_from_uri(uri)
+            newnode2 = self.clients[3].create_node_from_uri(uri)
             log.msg("starting replace2")
             d1 = newnode1.replace(NEWERDATA)
             d1.addCallback(lambda res: newnode2.download_to_data())