From: Brian Warner Date: Sat, 6 Dec 2008 05:08:37 +0000 (-0700) Subject: dirnode.py: dirnode.delete which hits UCWE should not fail with NoSuchChildError... X-Git-Url: https://git.rkrishnan.org/%5B/%5D%20/file/URI:LIT:krugkidfnzsc4/index.php?a=commitdiff_plain;h=7a0afb59a4aff9a23e5cd6837110fbcd8294bc79;p=tahoe-lafs%2Ftahoe-lafs.git dirnode.py: dirnode.delete which hits UCWE should not fail with NoSuchChildError. Fixes #550. --- diff --git a/src/allmydata/dirnode.py b/src/allmydata/dirnode.py index 39c377eb..3caec6b4 100644 --- a/src/allmydata/dirnode.py +++ b/src/allmydata/dirnode.py @@ -27,7 +27,7 @@ class Deleter: def modify(self, old_contents, servermap, first_time): children = self.node._unpack_contents(old_contents) if self.name not in children: - if self.must_exist: + if first_time and self.must_exist: raise NoSuchChildError(self.name) self.old_child = None return None diff --git a/src/allmydata/test/test_dirnode.py b/src/allmydata/test/test_dirnode.py index b1dd67f0..0447e9c1 100644 --- a/src/allmydata/test/test_dirnode.py +++ b/src/allmydata/test/test_dirnode.py @@ -9,10 +9,12 @@ from allmydata.interfaces import IURI, IClient, IMutableFileNode, \ INewDirectoryURI, IReadonlyNewDirectoryURI, IFileNode, \ ExistingChildError, NoSuchChildError, \ IDeepCheckResults, IDeepCheckAndRepairResults +from allmydata.mutable.node import MutableFileNode +from allmydata.mutable.common import UncoordinatedWriteError from allmydata.util import hashutil, base32 from allmydata.monitor import Monitor from allmydata.test.common import make_chk_file_uri, make_mutable_file_uri, \ - FakeDirectoryNode, create_chk_filenode, ErrorMixin + FakeDirectoryNode, create_chk_filenode, ErrorMixin, SystemTestMixin from allmydata.checker_results import CheckerResults, CheckAndRepairResults import common_util as testutil @@ -761,3 +763,45 @@ class DeepStats(unittest.TestCase): (3162277660169L, 10000000000000L, 1), ]) +class UCWEingMutableFileNode(MutableFileNode): + please_ucwe_after_next_upload = False + + def _upload(self, new_contents, servermap): + d = MutableFileNode._upload(self, new_contents, servermap) + def _ucwe(res): + raise UncoordinatedWriteError() + d.addCallback(_ucwe) + return d +class UCWEingNewDirectoryNode(dirnode.NewDirectoryNode): + filenode_class = UCWEingMutableFileNode + + +class Deleter(SystemTestMixin, unittest.TestCase): + def test_retry(self): + # ticket #550, a dirnode.delete which experiences an + # UncoordinatedWriteError will fail with an incorrect "you're + # deleting something which isn't there" NoSuchChildError exception. + + # to trigger this, we start by creating a directory with a single + # file in it. Then we create a special dirnode that uses a modified + # MutableFileNode which will raise UncoordinatedWriteError once on + # demand. We then call dirnode.delete, which ought to retry and + # succeed. + + self.basedir = self.mktemp() + d = self.set_up_nodes() + d.addCallback(lambda ignored: self.clients[0].create_empty_dirnode()) + small = upload.Data("Small enough for a LIT", None) + def _created_dir(dn): + self.root = dn + self.root_uri = dn.get_uri() + return dn.add_file(u"file", small) + d.addCallback(_created_dir) + def _do_delete(ignored): + n = UCWEingNewDirectoryNode(self.clients[0]).init_from_uri(self.root_uri) + # This should succeed, not raise an exception + return n.delete(u"file") + d.addCallback(_do_delete) + + return d +