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
12 class DummyImmutableFileNode:
13 def get_writekey(self):
17 implements(INodeMaker)
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
31 self._node_cache = weakref.WeakValueDictionary() # uri -> node
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,
43 return n.init_from_cap(cap)
44 def _create_dirnode(self, filenode):
45 return DirectoryNode(filenode, self, self.uploader)
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
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
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)
62 self._node_cache[bigcap] = node # note: WeakValueDictionary
64 node = UnknownNode(writecap, readcap) # don't cache UnknownNode
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)
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)
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)
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)
121 d.addCallback(_uploaded)
122 d.addCallback(self._create_dirnode)