From 4f58355a0eebd79e3bebe75c73e1c36d5cb0d45e Mon Sep 17 00:00:00 2001 From: david-sarah Date: Tue, 1 Jun 2010 18:46:44 -0700 Subject: [PATCH] dirnode.py: Fix bug that caused 'tahoe' fields, 'ctime' and 'mtime' not to be updated when new metadata is present. --- src/allmydata/dirnode.py | 44 +++++++++++--------- src/allmydata/test/test_dirnode.py | 65 +++++++++++++++++------------- 2 files changed, 64 insertions(+), 45 deletions(-) diff --git a/src/allmydata/dirnode.py b/src/allmydata/dirnode.py index 51f40c25..8a485f41 100644 --- a/src/allmydata/dirnode.py +++ b/src/allmydata/dirnode.py @@ -29,11 +29,11 @@ def update_metadata(metadata, new_metadata, now): Timestamps are set according to the time 'now'.""" if metadata is None: - metadata = {"ctime": now, - "mtime": now, - "tahoe": { - "linkcrtime": now, - "linkmotime": now, + metadata = {'ctime': now, + 'mtime': now, + 'tahoe': { + 'linkcrtime': now, + 'linkmotime': now, } } @@ -42,28 +42,36 @@ def update_metadata(metadata, new_metadata, now): newmd = new_metadata.copy() # Except 'tahoe'. - if newmd.has_key('tahoe'): + if 'tahoe' in newmd: del newmd['tahoe'] - if metadata.has_key('tahoe'): + if 'tahoe' in metadata: newmd['tahoe'] = metadata['tahoe'] + # For backwards compatibility with Tahoe < 1.4.0: + if 'ctime' not in newmd: + if 'ctime' in metadata: + newmd['ctime'] = metadata['ctime'] + else: + newmd['ctime'] = now + if 'mtime' not in newmd: + newmd['mtime'] = now + metadata = newmd else: # For backwards compatibility with Tahoe < 1.4.0: - if "ctime" not in metadata: - metadata["ctime"] = now - metadata["mtime"] = now + if 'ctime' not in metadata: + metadata['ctime'] = now + metadata['mtime'] = now # update timestamps sysmd = metadata.get('tahoe', {}) - if not 'linkcrtime' in sysmd: - if "ctime" in metadata: - # In Tahoe < 1.4.0 we used the word "ctime" to mean what Tahoe >= 1.4.0 - # calls "linkcrtime". - sysmd["linkcrtime"] = metadata["ctime"] - else: - sysmd["linkcrtime"] = now - sysmd["linkmotime"] = now + if 'linkcrtime' not in sysmd: + # In Tahoe < 1.4.0 we used the word 'ctime' to mean what Tahoe >= 1.4.0 + # calls 'linkcrtime'. + assert 'ctime' in metadata + sysmd['linkcrtime'] = metadata['ctime'] + sysmd['linkmotime'] = now + metadata['tahoe'] = sysmd return metadata diff --git a/src/allmydata/test/test_dirnode.py b/src/allmydata/test/test_dirnode.py index 5a326ee4..46497ae6 100644 --- a/src/allmydata/test/test_dirnode.py +++ b/src/allmydata/test/test_dirnode.py @@ -754,7 +754,8 @@ class Dirnode(GridTestMixin, unittest.TestCase, fake_file_uri, fake_file_uri, {})) d.addCallback(lambda res: n.get_metadata_for(u"c2")) - d.addCallback(lambda metadata: self.failUnlessEqual(metadata.keys(), ['tahoe'])) + d.addCallback(lambda metadata: + self.failUnlessEqual(set(metadata.keys()), set(["tahoe", "ctime", "mtime"]))) # You can't override the link timestamps. d.addCallback(lambda res: n.set_uri(u"c2", @@ -772,8 +773,7 @@ class Dirnode(GridTestMixin, unittest.TestCase, fake_file_uri, fake_file_uri)) d.addCallback(lambda res: n.get_metadata_for(u"c3")) d.addCallback(lambda metadata: - self.failUnlessEqual(set(metadata.keys()), - set(["tahoe", "ctime", "mtime"]))) + self.failUnlessEqual(set(metadata.keys()), set(["tahoe", "ctime", "mtime"]))) # or we can add specific metadata at set_uri() time, which # overrides the timestamps @@ -782,7 +782,7 @@ class Dirnode(GridTestMixin, unittest.TestCase, {"key": "value"})) d.addCallback(lambda res: n.get_metadata_for(u"c4")) d.addCallback(lambda metadata: - self.failUnless((set(metadata.keys()) == set(["key", "tahoe"])) and + self.failUnless((set(metadata.keys()) == set(["key", "tahoe", "ctime", "mtime"])) and (metadata['key'] == "value"), metadata)) d.addCallback(lambda res: n.delete(u"c2")) @@ -799,14 +799,14 @@ class Dirnode(GridTestMixin, unittest.TestCase, n.set_node, u"d2", n2, overwrite=False)) d.addCallback(lambda res: n.get_metadata_for(u"d2")) - d.addCallback(lambda metadata: self.failUnlessEqual(metadata.keys(), ['tahoe'])) + d.addCallback(lambda metadata: + self.failUnlessEqual(set(metadata.keys()), set(["tahoe", "ctime", "mtime"]))) # if we don't set any defaults, the child should get timestamps d.addCallback(lambda res: n.set_node(u"d3", n)) d.addCallback(lambda res: n.get_metadata_for(u"d3")) d.addCallback(lambda metadata: - self.failUnlessEqual(set(metadata.keys()), - set(["tahoe", "ctime", "mtime"]))) + self.failUnlessEqual(set(metadata.keys()), set(["tahoe", "ctime", "mtime"]))) # or we can add specific metadata at set_node() time, which # overrides the timestamps @@ -814,8 +814,8 @@ class Dirnode(GridTestMixin, unittest.TestCase, {"key": "value"})) d.addCallback(lambda res: n.get_metadata_for(u"d4")) d.addCallback(lambda metadata: - self.failUnless((set(metadata.keys()) == set(["key", "tahoe"])) and - (metadata['key'] == "value"), metadata)) + self.failUnless((set(metadata.keys()) == set(["key", "tahoe", "ctime", "mtime"])) and + (metadata["key"] == "value"), metadata)) d.addCallback(lambda res: n.delete(u"d2")) d.addCallback(lambda res: n.delete(u"d3")) @@ -845,15 +845,14 @@ class Dirnode(GridTestMixin, unittest.TestCase, d.addCallback(lambda children: self.failIf(u"new" in children)) d.addCallback(lambda res: n.get_metadata_for(u"e1")) d.addCallback(lambda metadata: - self.failUnlessEqual(set(metadata.keys()), - set(["tahoe", "ctime", "mtime"]))) + self.failUnlessEqual(set(metadata.keys()), set(["tahoe", "ctime", "mtime"]))) d.addCallback(lambda res: n.get_metadata_for(u"e2")) d.addCallback(lambda metadata: - self.failUnlessEqual(set(metadata.keys()), set(['tahoe']))) + self.failUnlessEqual(set(metadata.keys()), set(["tahoe", "ctime", "mtime"]))) d.addCallback(lambda res: n.get_metadata_for(u"e3")) d.addCallback(lambda metadata: - self.failUnless((set(metadata.keys()) == set(["key", "tahoe"])) - and (metadata['key'] == "value"), metadata)) + self.failUnless((set(metadata.keys()) == set(["key", "tahoe", "ctime", "mtime"])) and + (metadata["key"] == "value"), metadata)) d.addCallback(lambda res: n.delete(u"e1")) d.addCallback(lambda res: n.delete(u"e2")) @@ -877,15 +876,14 @@ class Dirnode(GridTestMixin, unittest.TestCase, d.addCallback(lambda children: self.failIf(u"new" in children)) d.addCallback(lambda res: n.get_metadata_for(u"f1")) d.addCallback(lambda metadata: - self.failUnlessEqual(set(metadata.keys()), - set(["tahoe", "ctime", "mtime"]))) + self.failUnlessEqual(set(metadata.keys()), set(["tahoe", "ctime", "mtime"]))) d.addCallback(lambda res: n.get_metadata_for(u"f2")) - d.addCallback( - lambda metadata: self.failUnlessEqual(set(metadata.keys()), set(['tahoe']))) + d.addCallback(lambda metadata: + self.failUnlessEqual(set(metadata.keys()), set(["tahoe", "ctime", "mtime"]))) d.addCallback(lambda res: n.get_metadata_for(u"f3")) d.addCallback(lambda metadata: - self.failUnless((set(metadata.keys()) == set(["key", "tahoe"])) and - (metadata['key'] == "value"), metadata)) + self.failUnless((set(metadata.keys()) == set(["key", "tahoe", "ctime", "mtime"])) and + (metadata["key"] == "value"), metadata)) d.addCallback(lambda res: n.delete(u"f1")) d.addCallback(lambda res: n.delete(u"f2")) @@ -896,12 +894,10 @@ class Dirnode(GridTestMixin, unittest.TestCase, n.set_metadata_for(u"child", {"tags": ["web2.0-compatible"], "tahoe": {"bad": "mojo"}})) d.addCallback(lambda n1: n1.get_metadata_for(u"child")) - def _check_metadata(md): - self.failUnless("tags" in md, md) - self.failUnlessEqual(md["tags"], ["web2.0-compatible"]) - self.failUnless("tahoe" in md, md) - self.failIf("bad" in md["tahoe"], md) - d.addCallback(_check_metadata) + d.addCallback(lambda metadata: + self.failUnless((set(metadata.keys()) == set(["tags", "tahoe", "ctime", "mtime"])) and + metadata["tags"] == ["web2.0-compatible"] and + "bad" not in metadata["tahoe"], metadata)) def _start(res): self._start_timestamp = time.time() @@ -996,7 +992,7 @@ class Dirnode(GridTestMixin, unittest.TestCase, self.failUnless(IImmutableFileNode.providedBy(newnode))) d.addCallback(lambda res: n.get_metadata_for(u"newfile-metadata")) d.addCallback(lambda metadata: - self.failUnless((set(metadata.keys()) == set(["key", "tahoe"])) and + self.failUnless((set(metadata.keys()) == set(["key", "tahoe", "ctime", "mtime"])) and (metadata['key'] == "value"), metadata)) d.addCallback(lambda res: n.delete(u"newfile-metadata")) @@ -1058,6 +1054,21 @@ class Dirnode(GridTestMixin, unittest.TestCase, d.addErrback(self.explain_error) return d + def test_update_metadata(self): + (t1, t2, t3) = (626644800, 634745640, 892226160) + + md1 = dirnode.update_metadata({}, {"ctime": t1}, t2) + self.failUnlessEqual(md1, {"ctime": t1, "mtime": t2, + "tahoe":{"linkcrtime": t1, "linkmotime": t2}}) + + md2 = dirnode.update_metadata(md1, {"key": "value", "tahoe": {"bad": "mojo"}}, t3) + self.failUnlessEqual(md2, {"key": "value", "ctime": t1, "mtime": t3, + "tahoe":{"linkcrtime": t1, "linkmotime": t3}}) + + md3 = dirnode.update_metadata({}, None, t3) + self.failUnlessEqual(md3, {"ctime": t3, "mtime": t3, + "tahoe":{"linkcrtime": t3, "linkmotime": t3}}) + def test_create_subdirectory(self): self.basedir = "dirnode/Dirnode/test_create_subdirectory" self.set_up_grid() -- 2.45.2