From: Brian Warner <warner@lothar.com>
Date: Thu, 13 Oct 2011 16:32:29 +0000 (-0700)
Subject: misc mutable-type fixes:
X-Git-Url: https://git.rkrishnan.org/%5B/frontends/index.php?a=commitdiff_plain;h=210761cd49f9ba68522991c6c5f8addd05b3fd2c;p=tahoe-lafs%2Ftahoe-lafs.git

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
---

diff --git a/docs/frontends/webapi.rst b/docs/frontends/webapi.rst
index 6365f441..49e8b1f1 100644
--- a/docs/frontends/webapi.rst
+++ b/docs/frontends/webapi.rst
@@ -379,15 +379,20 @@ Writing/Uploading A File
  immutable file, the "offset" parameter is not valid.
 
  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
- mutable file. format=SDMF creates an SDMF mutable file. format=CHK creates an
- immutable file. The value of the format argument is case-insensitive. For
- compatibility with previous versions of Tahoe-LAFS, the webapi will also
- accept a mutable=true argument in the query string. If mutable=true is given,
- 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.
- Use of mutable=true is discouraged; new code should use format= instead of
- mutable=true.  If neither format= nor mutable=true are given, the
+ specifying a format= argument in the query string. format=MDMF creates an
+ MDMF mutable file. format=SDMF creates an SDMF mutable file. format=CHK
+ creates an immutable file. The value of the format argument is
+ case-insensitive. If no format is specified, the newly-created file will be
+ immutable (but see below).
+
+ For compatibility with previous versions of Tahoe-LAFS, the web-API will
+ also accept a mutable=true argument in the query string. If mutable=true is
+ 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.
 
  This returns the file-cap of the resulting file. If a new file was created
diff --git a/src/allmydata/client.py b/src/allmydata/client.py
index aa55da7a..813ee395 100644
--- a/src/allmydata/client.py
+++ b/src/allmydata/client.py
@@ -339,19 +339,20 @@ class Client(node.Node, pollmixin.PollMixin):
         self.blacklist = Blacklist(fn)
 
     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._secret_holder,
                                    self.get_history(),
                                    self.getServiceNamed("uploader"),
                                    self.terminator,
                                    self.get_encoding_parameters(),
+                                   self.mutable_file_default,
                                    self._key_generator,
                                    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):
         return self.history
@@ -507,8 +508,6 @@ class Client(node.Node, pollmixin.PollMixin):
         return self.nodemaker.create_immutable_directory(children, convergence)
 
     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,
                                                   version=version)
 
diff --git a/src/allmydata/nodemaker.py b/src/allmydata/nodemaker.py
index 6fdaf479..d0c9b4b6 100644
--- a/src/allmydata/nodemaker.py
+++ b/src/allmydata/nodemaker.py
@@ -1,7 +1,7 @@
 import weakref
 from zope.interface import implements
 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.filenode import ImmutableFileNode, CiphertextFileNode
 from allmydata.immutable.upload import Data
@@ -18,14 +18,15 @@ class NodeMaker:
 
     def __init__(self, storage_broker, secret_holder, history,
                  uploader, terminator,
-                 default_encoding_parameters, key_generator,
-                 blacklist=None):
+                 default_encoding_parameters, mutable_file_default,
+                 key_generator, blacklist=None):
         self.storage_broker = storage_broker
         self.secret_holder = secret_holder
         self.history = history
         self.uploader = uploader
         self.terminator = terminator
         self.default_encoding_parameters = default_encoding_parameters
+        self.mutable_file_default = mutable_file_default
         self.key_generator = key_generator
         self.blacklist = blacklist
 
@@ -111,7 +112,7 @@ class NodeMaker:
 
     def create_mutable_file(self, contents=None, keysize=None, version=None):
         if version is None:
-            version = SDMF_VERSION
+            version = self.mutable_file_default
         n = MutableFileNode(self.storage_broker, self.secret_holder,
                             self.default_encoding_parameters, self.history)
         d = self.key_generator.generate(keysize)
diff --git a/src/allmydata/test/test_dirnode.py b/src/allmydata/test/test_dirnode.py
index 145419be..8bea7d05 100644
--- a/src/allmydata/test/test_dirnode.py
+++ b/src/allmydata/test/test_dirnode.py
@@ -1376,7 +1376,7 @@ class Packing(testutil.ReallyEqualMixin, unittest.TestCase):
         known_tree = b32decode(self.known_tree)
         nodemaker = NodeMaker(None, None, None,
                               None, None,
-                              {"k": 3, "n": 10}, None)
+                              {"k": 3, "n": 10}, None, None)
         write_uri = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q"
         filenode = nodemaker.create_from_cap(write_uri)
         node = dirnode.DirectoryNode(filenode, nodemaker, None)
@@ -1437,7 +1437,7 @@ class Packing(testutil.ReallyEqualMixin, unittest.TestCase):
         return kids
 
     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()
 
         kids = self._make_kids(nm, ["imm", "lit", "write", "read",
@@ -1536,7 +1536,7 @@ class FakeClient2(Client):
     def __init__(self):
         self.nodemaker = FakeNodeMaker(None, None, None,
                                        None, None,
-                                       {"k":3,"n":10}, None)
+                                       {"k":3,"n":10}, None, None)
     def create_node_from_uri(self, 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.terminator,
                                   c0.get_encoding_parameters(),
+                                  c0.mutable_file_default,
                                   c0._key_generator)
             n = nm.create_from_cap(self.root_uri)
             assert n._node.please_ucwe_after_next_upload == False
diff --git a/src/allmydata/test/test_mutable.py b/src/allmydata/test/test_mutable.py
index 3c39ae51..e273448a 100644
--- a/src/allmydata/test/test_mutable.py
+++ b/src/allmydata/test/test_mutable.py
@@ -239,7 +239,7 @@ def make_nodemaker(s=None, num_peers=10):
     keygen.set_default_keysize(TEST_RSA_KEY_SIZE)
     nodemaker = NodeMaker(storage_broker, sh, None,
                           None, None,
-                          {"k": 3, "n": 10}, keygen)
+                          {"k": 3, "n": 10}, SDMF_VERSION, keygen)
     return nodemaker
 
 class Filenode(unittest.TestCase, testutil.ShouldFailMixin):
diff --git a/src/allmydata/web/common.py b/src/allmydata/web/common.py
index 9bfed072..13385c5f 100644
--- a/src/allmydata/web/common.py
+++ b/src/allmydata/web/common.py
@@ -56,6 +56,11 @@ def get_mutable_type(file_format): # accepts result of get_format()
     elif file_format == "MDMF":
         return MDMF_VERSION
     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
 
 
diff --git a/src/allmydata/web/filenode.py b/src/allmydata/web/filenode.py
index 28913170..3e4abf13 100644
--- a/src/allmydata/web/filenode.py
+++ b/src/allmydata/web/filenode.py
@@ -27,8 +27,8 @@ class ReplaceMeMixin:
     def replace_me_with_a_child(self, req, client, replace):
         # a new file is being uploaded in our place.
         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)
             d = client.create_mutable_file(data, version=mutable_type)
             def _uploaded(newnode):
diff --git a/src/allmydata/web/root.py b/src/allmydata/web/root.py
index 47a6e9bf..2b9ea204 100644
--- a/src/allmydata/web/root.py
+++ b/src/allmydata/web/root.py
@@ -46,9 +46,9 @@ class URIHandler(RenderMixin, rend.Page):
         t = get_arg(req, "t", "").strip()
         if t == "":
             file_format = get_format(req, "CHK")
-            if file_format in ("SDMF", "MDMF"):
-                version = get_mutable_type(file_format)
-                return unlinked.PUTUnlinkedSSK(req, self.client, version)
+            mutable_type = get_mutable_type(file_format)
+            if mutable_type is not None:
+                return unlinked.PUTUnlinkedSSK(req, self.client, mutable_type)
             else:
                 return unlinked.PUTUnlinkedCHK(req, self.client)
         if t == "mkdir":
@@ -65,9 +65,9 @@ class URIHandler(RenderMixin, rend.Page):
         t = get_arg(req, "t", "").strip()
         if t in ("", "upload"):
             file_format = get_format(req)
-            if file_format in ("SDMF", "MDMF"):
-                version = get_mutable_type(file_format)
-                return unlinked.POSTUnlinkedSSK(req, self.client, version)
+            mutable_type = get_mutable_type(file_format)
+            if mutable_type is not None:
+                return unlinked.POSTUnlinkedSSK(req, self.client, mutable_type)
             else:
                 return unlinked.POSTUnlinkedCHK(req, self.client)
         if t == "mkdir":
diff --git a/src/allmydata/web/unlinked.py b/src/allmydata/web/unlinked.py
index 94dd0621..8fa88479 100644
--- a/src/allmydata/web/unlinked.py
+++ b/src/allmydata/web/unlinked.py
@@ -29,7 +29,7 @@ def PUTUnlinkedCreateDirectory(req, client):
     # "PUT /uri?t=mkdir", to create an unlinked directory.
     file_format = get_format(req, None)
     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)
     mt = None
     if file_format: