import weakref from zope.interface import implements from allmydata.util.assertutil import precondition from allmydata.interfaces import INodeMaker from allmydata.immutable.filenode import FileNode, LiteralFileNode from allmydata.mutable.filenode import MutableFileNode from allmydata.dirnode import DirectoryNode, pack_children from allmydata.unknown import UnknownNode from allmydata import uri class NodeMaker: implements(INodeMaker) def __init__(self, storage_broker, secret_holder, history, uploader, downloader, download_cache_dirman, default_encoding_parameters, key_generator): self.storage_broker = storage_broker self.secret_holder = secret_holder self.history = history self.uploader = uploader self.downloader = downloader self.download_cache_dirman = download_cache_dirman self.default_encoding_parameters = default_encoding_parameters self.key_generator = key_generator self._node_cache = weakref.WeakValueDictionary() # uri -> node def _create_lit(self, cap): return LiteralFileNode(cap) def _create_immutable(self, cap): return FileNode(cap, self.storage_broker, self.secret_holder, self.downloader, self.history, self.download_cache_dirman) def _create_mutable(self, cap): n = MutableFileNode(self.storage_broker, self.secret_holder, self.default_encoding_parameters, self.history) return n.init_from_cap(cap) def _create_dirnode(self, filenode): return DirectoryNode(filenode, self, self.uploader) def create_from_cap(self, writecap, readcap=None): # this returns synchronously. It starts with a "cap string". assert isinstance(writecap, (str, type(None))), type(writecap) assert isinstance(readcap, (str, type(None))), type(readcap) bigcap = writecap or readcap if not bigcap: # maybe the writecap was hidden because we're in a readonly # directory, and the future cap format doesn't have a readcap, or # something. return UnknownNode(writecap, readcap) if bigcap in self._node_cache: return self._node_cache[bigcap] cap = uri.from_string(bigcap) node = self._create_from_cap(cap) if node: self._node_cache[bigcap] = node # note: WeakValueDictionary else: node = UnknownNode(writecap, readcap) # don't cache UnknownNode return node def _create_from_cap(self, cap): # This starts with a "cap instance" if isinstance(cap, uri.LiteralFileURI): return self._create_lit(cap) if isinstance(cap, uri.CHKFileURI): return self._create_immutable(cap) if isinstance(cap, (uri.ReadonlySSKFileURI, uri.WriteableSSKFileURI)): return self._create_mutable(cap) if isinstance(cap, (uri.ReadonlyDirectoryURI, uri.DirectoryURI)): filenode = self._create_from_cap(cap.get_filenode_cap()) return self._create_dirnode(filenode) return None def create_mutable_file(self, contents=None, keysize=None): n = MutableFileNode(self.storage_broker, self.secret_holder, self.default_encoding_parameters, self.history) d = self.key_generator.generate(keysize) d.addCallback(n.create_with_keys, contents) d.addCallback(lambda res: n) return d def create_new_mutable_directory(self, initial_children={}): # initial_children must have metadata (i.e. {} instead of None), and # should not contain UnknownNodes for (name, (node, metadata)) in initial_children.iteritems(): precondition(not isinstance(node, UnknownNode), "create_new_mutable_directory does not accept UnknownNode", node) precondition(isinstance(metadata, dict), "create_new_mutable_directory requires metadata to be a dict, not None", metadata) d = self.create_mutable_file(lambda n: pack_children(n, initial_children)) d.addCallback(self._create_dirnode) return d