Rev 4721: Test that read-lock changes to a IndirectedDirstate preserve concurrent write-lock changes. in http://bazaar.launchpad.net/~lifeless/bzr/dirstate2

Robert Collins robertc at robertcollins.net
Tue Sep 29 05:02:42 BST 2009


At http://bazaar.launchpad.net/~lifeless/bzr/dirstate2

------------------------------------------------------------
revno: 4721
revision-id: robertc at robertcollins.net-20090929040224-ofiqnl04w3e8v1i2
parent: robertc at robertcollins.net-20090929033218-b1os6edaaf8n2ame
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate2
timestamp: Tue 2009-09-29 14:02:24 +1000
message:
  Test that read-lock changes to a IndirectedDirstate preserve concurrent write-lock changes.
=== modified file 'NEWS'
--- a/NEWS	2009-09-28 04:21:52 +0000
+++ b/NEWS	2009-09-29 04:02:24 +0000
@@ -141,6 +141,11 @@
 Internals
 *********
 
+* A new dirstate class ``IndirectedDirState`` has been introduced which
+  uses a link pointer to manage multiple dirstate files, permitting disk
+  bisection, stat cache updates, and writers and readers to not mutually
+  exclude. (Robert Collins)
+
 * ``BTreeLeafParser.extract_key`` has been tweaked slightly to reduce
   mallocs while parsing the index (approx 3=>1 mallocs per key read).
   This results in a 10% speedup while reading an index.

=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2009-09-29 03:32:18 +0000
+++ b/bzrlib/dirstate.py	2009-09-29 04:02:24 +0000
@@ -3341,7 +3341,7 @@
                 # file.
                 self._transport.rename(name_check, 'current')
                 self._transport.delete(current_new)
-                self._read_link.delete(name)
+                self._transport.delete(name)
                 # not saving in _save in a 'r' lock is not an error.
                 return True
         # Claim that we're committing

=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py	2009-09-29 03:32:18 +0000
+++ b/bzrlib/tests/test_dirstate.py	2009-09-29 04:02:24 +0000
@@ -626,6 +626,62 @@
         finally:
             state.unlock()
 
+    def test_save_from_read_lock_preserves_concurrent_changes(self):
+        """If dirstate is locked, save will fail without complaining."""
+        self.build_tree(['a-file', 'b-file'])
+        state = self._dirstate_class.initialize('dirstate')
+        try:
+            # No stat and no sha1 sum.
+            state.add('a-file', 'a-file-id', 'file', None, '')
+            state.save()
+        finally:
+            state.unlock()
+
+        state = self._dirstate_class.on_file('dirstate')
+        state.lock_read()
+        try:
+            entry = state._get_entry(0, path_utf8='a-file')
+            sha1sum = dirstate.update_entry(state, entry, 'a-file',
+                os.lstat('a-file'))
+            # No sha - too new
+            self.assertEqual(None, sha1sum)
+            self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
+                             state._dirblock_state)
+
+            # Now, before we try to save, grab another dirstate, and take out
+            # a write lock (it could be a read lock, but write locks are the
+            # ones we really care MUST NOT have their changes lost).
+            state2 = self._dirstate_class.on_file('dirstate')
+            try:
+                state2.lock_write()
+            except errors.LockContention:
+                if self._dirstate_class == dirstate.DirState:
+                    # clearly we can't overwrite the write locks changes if we
+                    # can't get a write lock at the same time ;)
+                    return
+                else:
+                    self.fail("unexpected lock contention")
+            try:
+                # The write executes a change:
+                state2.add('b-file', 'b-file-id', 'file', None, '')
+                state2.save()
+                # The read-locked state saves its hash update, which must not
+                # result in b-file being lost, not error.
+                state.save()
+            finally:
+                state2.unlock()
+        finally:
+            state.unlock()
+
+        # The file on disk should still contain b-file.
+        state = self._dirstate_class.on_file('dirstate')
+        state.lock_read()
+        try:
+            entry = state._get_entry(0, path_utf8='b-file')
+            self.assertEqual('', entry[1][0][1])
+        finally:
+            state.unlock()
+
     def test_save_fails_quietly_if_locked(self):
         """If dirstate is locked, save will fail without complaining."""
         self.build_tree(['a-file'])




More information about the bazaar-commits mailing list