]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/nodemaker.py
class name cleanups: s/FileNode/ImmutableFileNode/
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / nodemaker.py
1 import weakref
2 from zope.interface import implements
3 from allmydata.util.assertutil import precondition
4 from allmydata.interfaces import INodeMaker, NotDeepImmutableError
5 from allmydata.immutable.filenode import ImmutableFileNode, LiteralFileNode
6 from allmydata.immutable.upload import Data
7 from allmydata.mutable.filenode import MutableFileNode
8 from allmydata.dirnode import DirectoryNode, pack_children
9 from allmydata.unknown import UnknownNode
10 from allmydata import uri
11
12 class DummyImmutableFileNode:
13     def get_writekey(self):
14         return None
15
16 class NodeMaker:
17     implements(INodeMaker)
18
19     def __init__(self, storage_broker, secret_holder, history,
20                  uploader, downloader, download_cache_dirman,
21                  default_encoding_parameters, key_generator):
22         self.storage_broker = storage_broker
23         self.secret_holder = secret_holder
24         self.history = history
25         self.uploader = uploader
26         self.downloader = downloader
27         self.download_cache_dirman = download_cache_dirman
28         self.default_encoding_parameters = default_encoding_parameters
29         self.key_generator = key_generator
30
31         self._node_cache = weakref.WeakValueDictionary() # uri -> node
32
33     def _create_lit(self, cap):
34         return LiteralFileNode(cap)
35     def _create_immutable(self, cap):
36         return ImmutableFileNode(cap, self.storage_broker, self.secret_holder,
37                                  self.downloader, self.history,
38                                  self.download_cache_dirman)
39     def _create_mutable(self, cap):
40         n = MutableFileNode(self.storage_broker, self.secret_holder,
41                             self.default_encoding_parameters,
42                             self.history)
43         return n.init_from_cap(cap)
44     def _create_dirnode(self, filenode):
45         return DirectoryNode(filenode, self, self.uploader)
46
47     def create_from_cap(self, writecap, readcap=None):
48         # this returns synchronously. It starts with a "cap string".
49         assert isinstance(writecap, (str, type(None))), type(writecap)
50         assert isinstance(readcap,  (str, type(None))), type(readcap)
51         bigcap = writecap or readcap
52         if not bigcap:
53             # maybe the writecap was hidden because we're in a readonly
54             # directory, and the future cap format doesn't have a readcap, or
55             # something.
56             return UnknownNode(writecap, readcap)
57         if bigcap in self._node_cache:
58             return self._node_cache[bigcap]
59         cap = uri.from_string(bigcap)
60         node = self._create_from_cap(cap)
61         if node:
62             self._node_cache[bigcap] = node  # note: WeakValueDictionary
63         else:
64             node = UnknownNode(writecap, readcap) # don't cache UnknownNode
65         return node
66
67     def _create_from_cap(self, cap):
68         # This starts with a "cap instance"
69         if isinstance(cap, uri.LiteralFileURI):
70             return self._create_lit(cap)
71         if isinstance(cap, uri.CHKFileURI):
72             return self._create_immutable(cap)
73         if isinstance(cap, (uri.ReadonlySSKFileURI, uri.WriteableSSKFileURI)):
74             return self._create_mutable(cap)
75         if isinstance(cap, (uri.DirectoryURI,
76                             uri.ReadonlyDirectoryURI,
77                             uri.ImmutableDirectoryURI,
78                             uri.LiteralDirectoryURI)):
79             filenode = self._create_from_cap(cap.get_filenode_cap())
80             return self._create_dirnode(filenode)
81         return None
82
83     def create_mutable_file(self, contents=None, keysize=None):
84         n = MutableFileNode(self.storage_broker, self.secret_holder,
85                             self.default_encoding_parameters, self.history)
86         d = self.key_generator.generate(keysize)
87         d.addCallback(n.create_with_keys, contents)
88         d.addCallback(lambda res: n)
89         return d
90
91     def create_new_mutable_directory(self, initial_children={}):
92         # initial_children must have metadata (i.e. {} instead of None), and
93         # should not contain UnknownNodes
94         for (name, (node, metadata)) in initial_children.iteritems():
95             precondition(not isinstance(node, UnknownNode),
96                          "create_new_mutable_directory does not accept UnknownNode", node)
97             precondition(isinstance(metadata, dict),
98                          "create_new_mutable_directory requires metadata to be a dict, not None", metadata)
99         d = self.create_mutable_file(lambda n:
100                                      pack_children(n, initial_children))
101         d.addCallback(self._create_dirnode)
102         return d
103
104     def create_immutable_directory(self, children, convergence=None):
105         if convergence is None:
106             convergence = self.secret_holder.get_convergence_secret()
107         for (name, (node, metadata)) in children.iteritems():
108             precondition(not isinstance(node, UnknownNode),
109                          "create_immutable_directory does not accept UnknownNode", node)
110             precondition(isinstance(metadata, dict),
111                          "create_immutable_directory requires metadata to be a dict, not None", metadata)
112             if node.is_mutable():
113                 raise NotDeepImmutableError("%s is not immutable" % (node,))
114         n = DummyImmutableFileNode() # writekey=None
115         packed = pack_children(n, children)
116         uploadable = Data(packed, convergence)
117         d = self.uploader.upload(uploadable, history=self.history)
118         def _uploaded(results):
119             filecap = self.create_from_cap(results.uri)
120             return filecap
121         d.addCallback(_uploaded)
122         d.addCallback(self._create_dirnode)
123         return d