mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-26 08:01:06 +00:00
131e05b155
* "cap" means a python instance which encapsulates a filecap/dircap (uri.py) * "uri" means a string with a "URI:" prefix * FileNode instances are created with (and retain) a cap instance, and generate uri strings on demand * .get_cap/get_readcap/get_verifycap/get_repaircap return cap instances * .get_uri/get_readonly_uri return uri strings * add filenode.download_to_filename() for control.py, should find a better way * use MutableFileNode.init_from_cap, not .init_from_uri * directory URI instances: use get_filenode_cap, not get_filenode_uri * update/cleanup bench_dirnode.py to match, add Makefile target to run it
95 lines
4.2 KiB
Python
95 lines
4.2 KiB
Python
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
|