]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/nodemaker.py
Rewrite immutable downloader (#798). This patch includes higher-level
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / nodemaker.py
1 import weakref
2 from zope.interface import implements
3 from allmydata.interfaces import INodeMaker
4 from allmydata.immutable.literal import LiteralFileNode
5 from allmydata.immutable.filenode import ImmutableFileNode, CiphertextFileNode
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 NodeMaker:
13     implements(INodeMaker)
14
15     def __init__(self, storage_broker, secret_holder, history,
16                  uploader, terminator,
17                  default_encoding_parameters, key_generator):
18         self.storage_broker = storage_broker
19         self.secret_holder = secret_holder
20         self.history = history
21         self.uploader = uploader
22         self.terminator = terminator
23         self.default_encoding_parameters = default_encoding_parameters
24         self.key_generator = key_generator
25
26         self._node_cache = weakref.WeakValueDictionary() # uri -> node
27
28     def _create_lit(self, cap):
29         return LiteralFileNode(cap)
30     def _create_immutable(self, cap):
31         return ImmutableFileNode(cap, self.storage_broker, self.secret_holder,
32                                  self.terminator, self.history)
33     def _create_immutable_verifier(self, cap):
34         return CiphertextFileNode(cap, self.storage_broker, self.secret_holder,
35                                   self.terminator, self.history)
36     def _create_mutable(self, cap):
37         n = MutableFileNode(self.storage_broker, self.secret_holder,
38                             self.default_encoding_parameters,
39                             self.history)
40         return n.init_from_cap(cap)
41     def _create_dirnode(self, filenode):
42         return DirectoryNode(filenode, self, self.uploader)
43
44     def create_from_cap(self, writecap, readcap=None, deep_immutable=False, name=u"<unknown name>"):
45         # this returns synchronously. It starts with a "cap string".
46         assert isinstance(writecap, (str, type(None))), type(writecap)
47         assert isinstance(readcap,  (str, type(None))), type(readcap)
48
49         bigcap = writecap or readcap
50         if not bigcap:
51             # maybe the writecap was hidden because we're in a readonly
52             # directory, and the future cap format doesn't have a readcap, or
53             # something.
54             return UnknownNode(None, None)  # deep_immutable and name not needed
55
56         # The name doesn't matter for caching since it's only used in the error
57         # attribute of an UnknownNode, and we don't cache those.
58         if deep_immutable:
59             memokey = "I" + bigcap
60         else:
61             memokey = "M" + bigcap
62         if memokey in self._node_cache:
63             return self._node_cache[memokey]
64         cap = uri.from_string(bigcap, deep_immutable=deep_immutable, name=name)
65         node = self._create_from_single_cap(cap)
66         if node:
67             self._node_cache[memokey] = node  # note: WeakValueDictionary
68         else:
69             # don't cache UnknownNode
70             node = UnknownNode(writecap, readcap, deep_immutable=deep_immutable, name=name)
71         return node
72
73     def _create_from_single_cap(self, cap):
74         if isinstance(cap, uri.LiteralFileURI):
75             return self._create_lit(cap)
76         if isinstance(cap, uri.CHKFileURI):
77             return self._create_immutable(cap)
78         if isinstance(cap, uri.CHKFileVerifierURI):
79             return self._create_immutable_verifier(cap)
80         if isinstance(cap, (uri.ReadonlySSKFileURI, uri.WriteableSSKFileURI)):
81             return self._create_mutable(cap)
82         if isinstance(cap, (uri.DirectoryURI,
83                             uri.ReadonlyDirectoryURI,
84                             uri.ImmutableDirectoryURI,
85                             uri.LiteralDirectoryURI)):
86             filenode = self._create_from_single_cap(cap.get_filenode_cap())
87             return self._create_dirnode(filenode)
88         return None
89
90     def create_mutable_file(self, contents=None, keysize=None):
91         n = MutableFileNode(self.storage_broker, self.secret_holder,
92                             self.default_encoding_parameters, self.history)
93         d = self.key_generator.generate(keysize)
94         d.addCallback(n.create_with_keys, contents)
95         d.addCallback(lambda res: n)
96         return d
97
98     def create_new_mutable_directory(self, initial_children={}):
99         d = self.create_mutable_file(lambda n:
100                                      pack_children(initial_children, n.get_writekey()))
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         packed = pack_children(children, None, deep_immutable=True)
108         uploadable = Data(packed, convergence)
109         d = self.uploader.upload(uploadable, history=self.history)
110         d.addCallback(lambda results: self.create_from_cap(None, results.uri))
111         d.addCallback(self._create_dirnode)
112         return d