misc mutable-type fixes:

* fix tahoe.cfg control of default mutable type
* tolerate arbitrary case in [client]mutable.format value
* small docs improvements
* use get_mutable_type() as a format-is-mutable predicate
* tighten up error message
This commit is contained in:
Brian Warner 2011-10-13 09:32:29 -07:00
parent 01b00dc7dc
commit 210761cd49
9 changed files with 44 additions and 33 deletions

View File

@ -379,15 +379,20 @@ Writing/Uploading A File
immutable file, the "offset" parameter is not valid. immutable file, the "offset" parameter is not valid.
When creating a new file, you can control the type of file created by When creating a new file, you can control the type of file created by
specifying a format= argument in the query string. format=MDMF creates an MDMF specifying a format= argument in the query string. format=MDMF creates an
mutable file. format=SDMF creates an SDMF mutable file. format=CHK creates an MDMF mutable file. format=SDMF creates an SDMF mutable file. format=CHK
immutable file. The value of the format argument is case-insensitive. For creates an immutable file. The value of the format argument is
compatibility with previous versions of Tahoe-LAFS, the webapi will also case-insensitive. If no format is specified, the newly-created file will be
accept a mutable=true argument in the query string. If mutable=true is given, immutable (but see below).
then the new file will be mutable, and its format will be the default mutable
file format, as configured on the Tahoe-LAFS node hosting the webapi server. For compatibility with previous versions of Tahoe-LAFS, the web-API will
Use of mutable=true is discouraged; new code should use format= instead of also accept a mutable=true argument in the query string. If mutable=true is
mutable=true. If neither format= nor mutable=true are given, the given, then the new file will be mutable, and its format will be the default
mutable file format, as configured by the [client]mutable.format option of
tahoe.cfg on the Tahoe-LAFS node hosting the webapi server. Use of
mutable=true is discouraged; new code should use format= instead of
mutable=true (unless it needs to be compatible with web-API servers older
than v1.9.0). If neither format= nor mutable=true are given, the
newly-created file will be immutable. newly-created file will be immutable.
This returns the file-cap of the resulting file. If a new file was created This returns the file-cap of the resulting file. If a new file was created

View File

@ -339,19 +339,20 @@ class Client(node.Node, pollmixin.PollMixin):
self.blacklist = Blacklist(fn) self.blacklist = Blacklist(fn)
def init_nodemaker(self): def init_nodemaker(self):
default = self.get_config("client", "mutable.format", default="SDMF")
if default.upper() == "MDMF":
self.mutable_file_default = MDMF_VERSION
else:
self.mutable_file_default = SDMF_VERSION
self.nodemaker = NodeMaker(self.storage_broker, self.nodemaker = NodeMaker(self.storage_broker,
self._secret_holder, self._secret_holder,
self.get_history(), self.get_history(),
self.getServiceNamed("uploader"), self.getServiceNamed("uploader"),
self.terminator, self.terminator,
self.get_encoding_parameters(), self.get_encoding_parameters(),
self.mutable_file_default,
self._key_generator, self._key_generator,
self.blacklist) self.blacklist)
default = self.get_config("client", "mutable.format", default="sdmf")
if default == "mdmf":
self.mutable_file_default = MDMF_VERSION
else:
self.mutable_file_default = SDMF_VERSION
def get_history(self): def get_history(self):
return self.history return self.history
@ -507,8 +508,6 @@ class Client(node.Node, pollmixin.PollMixin):
return self.nodemaker.create_immutable_directory(children, convergence) return self.nodemaker.create_immutable_directory(children, convergence)
def create_mutable_file(self, contents=None, keysize=None, version=None): def create_mutable_file(self, contents=None, keysize=None, version=None):
if not version:
version = self.mutable_file_default
return self.nodemaker.create_mutable_file(contents, keysize, return self.nodemaker.create_mutable_file(contents, keysize,
version=version) version=version)

View File

@ -1,7 +1,7 @@
import weakref import weakref
from zope.interface import implements from zope.interface import implements
from allmydata.util.assertutil import precondition from allmydata.util.assertutil import precondition
from allmydata.interfaces import INodeMaker, SDMF_VERSION from allmydata.interfaces import INodeMaker
from allmydata.immutable.literal import LiteralFileNode from allmydata.immutable.literal import LiteralFileNode
from allmydata.immutable.filenode import ImmutableFileNode, CiphertextFileNode from allmydata.immutable.filenode import ImmutableFileNode, CiphertextFileNode
from allmydata.immutable.upload import Data from allmydata.immutable.upload import Data
@ -18,14 +18,15 @@ class NodeMaker:
def __init__(self, storage_broker, secret_holder, history, def __init__(self, storage_broker, secret_holder, history,
uploader, terminator, uploader, terminator,
default_encoding_parameters, key_generator, default_encoding_parameters, mutable_file_default,
blacklist=None): key_generator, blacklist=None):
self.storage_broker = storage_broker self.storage_broker = storage_broker
self.secret_holder = secret_holder self.secret_holder = secret_holder
self.history = history self.history = history
self.uploader = uploader self.uploader = uploader
self.terminator = terminator self.terminator = terminator
self.default_encoding_parameters = default_encoding_parameters self.default_encoding_parameters = default_encoding_parameters
self.mutable_file_default = mutable_file_default
self.key_generator = key_generator self.key_generator = key_generator
self.blacklist = blacklist self.blacklist = blacklist
@ -111,7 +112,7 @@ class NodeMaker:
def create_mutable_file(self, contents=None, keysize=None, version=None): def create_mutable_file(self, contents=None, keysize=None, version=None):
if version is None: if version is None:
version = SDMF_VERSION version = self.mutable_file_default
n = MutableFileNode(self.storage_broker, self.secret_holder, n = MutableFileNode(self.storage_broker, self.secret_holder,
self.default_encoding_parameters, self.history) self.default_encoding_parameters, self.history)
d = self.key_generator.generate(keysize) d = self.key_generator.generate(keysize)

View File

@ -1376,7 +1376,7 @@ class Packing(testutil.ReallyEqualMixin, unittest.TestCase):
known_tree = b32decode(self.known_tree) known_tree = b32decode(self.known_tree)
nodemaker = NodeMaker(None, None, None, nodemaker = NodeMaker(None, None, None,
None, None, None, None,
{"k": 3, "n": 10}, None) {"k": 3, "n": 10}, None, None)
write_uri = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q" write_uri = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q"
filenode = nodemaker.create_from_cap(write_uri) filenode = nodemaker.create_from_cap(write_uri)
node = dirnode.DirectoryNode(filenode, nodemaker, None) node = dirnode.DirectoryNode(filenode, nodemaker, None)
@ -1437,7 +1437,7 @@ class Packing(testutil.ReallyEqualMixin, unittest.TestCase):
return kids return kids
def test_deep_immutable(self): def test_deep_immutable(self):
nm = NodeMaker(None, None, None, None, None, {"k": 3, "n": 10}, None) nm = NodeMaker(None, None, None, None, None, {"k": 3, "n": 10}, None, None)
fn = MinimalFakeMutableFile() fn = MinimalFakeMutableFile()
kids = self._make_kids(nm, ["imm", "lit", "write", "read", kids = self._make_kids(nm, ["imm", "lit", "write", "read",
@ -1536,7 +1536,7 @@ class FakeClient2(Client):
def __init__(self): def __init__(self):
self.nodemaker = FakeNodeMaker(None, None, None, self.nodemaker = FakeNodeMaker(None, None, None,
None, None, None, None,
{"k":3,"n":10}, None) {"k":3,"n":10}, None, None)
def create_node_from_uri(self, rwcap, rocap): def create_node_from_uri(self, rwcap, rocap):
return self.nodemaker.create_from_cap(rwcap, rocap) return self.nodemaker.create_from_cap(rwcap, rocap)
@ -1825,6 +1825,7 @@ class Deleter(GridTestMixin, testutil.ReallyEqualMixin, unittest.TestCase):
c0.get_history(), c0.getServiceNamed("uploader"), c0.get_history(), c0.getServiceNamed("uploader"),
c0.terminator, c0.terminator,
c0.get_encoding_parameters(), c0.get_encoding_parameters(),
c0.mutable_file_default,
c0._key_generator) c0._key_generator)
n = nm.create_from_cap(self.root_uri) n = nm.create_from_cap(self.root_uri)
assert n._node.please_ucwe_after_next_upload == False assert n._node.please_ucwe_after_next_upload == False

View File

@ -239,7 +239,7 @@ def make_nodemaker(s=None, num_peers=10):
keygen.set_default_keysize(TEST_RSA_KEY_SIZE) keygen.set_default_keysize(TEST_RSA_KEY_SIZE)
nodemaker = NodeMaker(storage_broker, sh, None, nodemaker = NodeMaker(storage_broker, sh, None,
None, None, None, None,
{"k": 3, "n": 10}, keygen) {"k": 3, "n": 10}, SDMF_VERSION, keygen)
return nodemaker return nodemaker
class Filenode(unittest.TestCase, testutil.ShouldFailMixin): class Filenode(unittest.TestCase, testutil.ShouldFailMixin):

View File

@ -56,6 +56,11 @@ def get_mutable_type(file_format): # accepts result of get_format()
elif file_format == "MDMF": elif file_format == "MDMF":
return MDMF_VERSION return MDMF_VERSION
else: else:
# this is also used to identify which formats are mutable. Use
# if get_mutable_type(file_format) is not None:
# do_mutable()
# else:
# do_immutable()
return None return None

View File

@ -27,8 +27,8 @@ class ReplaceMeMixin:
def replace_me_with_a_child(self, req, client, replace): def replace_me_with_a_child(self, req, client, replace):
# a new file is being uploaded in our place. # a new file is being uploaded in our place.
file_format = get_format(req, "CHK") file_format = get_format(req, "CHK")
if file_format in ("SDMF", "MDMF"): mutable_type = get_mutable_type(file_format)
mutable_type = get_mutable_type(file_format) if mutable_type is not None:
data = MutableFileHandle(req.content) data = MutableFileHandle(req.content)
d = client.create_mutable_file(data, version=mutable_type) d = client.create_mutable_file(data, version=mutable_type)
def _uploaded(newnode): def _uploaded(newnode):

View File

@ -46,9 +46,9 @@ class URIHandler(RenderMixin, rend.Page):
t = get_arg(req, "t", "").strip() t = get_arg(req, "t", "").strip()
if t == "": if t == "":
file_format = get_format(req, "CHK") file_format = get_format(req, "CHK")
if file_format in ("SDMF", "MDMF"): mutable_type = get_mutable_type(file_format)
version = get_mutable_type(file_format) if mutable_type is not None:
return unlinked.PUTUnlinkedSSK(req, self.client, version) return unlinked.PUTUnlinkedSSK(req, self.client, mutable_type)
else: else:
return unlinked.PUTUnlinkedCHK(req, self.client) return unlinked.PUTUnlinkedCHK(req, self.client)
if t == "mkdir": if t == "mkdir":
@ -65,9 +65,9 @@ class URIHandler(RenderMixin, rend.Page):
t = get_arg(req, "t", "").strip() t = get_arg(req, "t", "").strip()
if t in ("", "upload"): if t in ("", "upload"):
file_format = get_format(req) file_format = get_format(req)
if file_format in ("SDMF", "MDMF"): mutable_type = get_mutable_type(file_format)
version = get_mutable_type(file_format) if mutable_type is not None:
return unlinked.POSTUnlinkedSSK(req, self.client, version) return unlinked.POSTUnlinkedSSK(req, self.client, mutable_type)
else: else:
return unlinked.POSTUnlinkedCHK(req, self.client) return unlinked.POSTUnlinkedCHK(req, self.client)
if t == "mkdir": if t == "mkdir":

View File

@ -29,7 +29,7 @@ def PUTUnlinkedCreateDirectory(req, client):
# "PUT /uri?t=mkdir", to create an unlinked directory. # "PUT /uri?t=mkdir", to create an unlinked directory.
file_format = get_format(req, None) file_format = get_format(req, None)
if file_format == "CHK": if file_format == "CHK":
raise WebError("format=CHK not currently accepted for PUT /uri?t=mkdir", raise WebError("format=CHK not accepted for PUT /uri?t=mkdir",
http.BAD_REQUEST) http.BAD_REQUEST)
mt = None mt = None
if file_format: if file_format: