Rev 4715: Merge bzr.stable, resolve NEWS in http://bazaar.launchpad.net/~jameinel/bzr/2.0.4-update-exception-495023

John Arbash Meinel john at arbash-meinel.com
Mon Jan 4 22:21:30 GMT 2010


At http://bazaar.launchpad.net/~jameinel/bzr/2.0.4-update-exception-495023

------------------------------------------------------------
revno: 4715 [merge]
revision-id: john at arbash-meinel.com-20100104222114-gqzeifmg7wa36h6f
parent: john at arbash-meinel.com-20100104200630-p5qhylc0mr2qm5ws
parent: pqm at pqm.ubuntu.com-20100104011521-lkufz3tammak5mxx
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.0.4-update-exception-495023
timestamp: Mon 2010-01-04 16:21:14 -0600
message:
  Merge bzr.stable, resolve NEWS
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/_readdir_pyx.pyx        readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
  bzrlib/lockdir.py              lockdir.py-20060220222025-98258adf27fbdda3
  bzrlib/repofmt/groupcompress_repo.py repofmt.py-20080715094215-wp1qfvoo7093c8qr-1
  bzrlib/tests/per_pack_repository.py test_pack_repository-20080801043947-eaw0e6h2gu75kwmy-1
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS	2010-01-04 20:06:30 +0000
+++ b/NEWS	2010-01-04 22:21:14 +0000
@@ -31,11 +31,21 @@
   This will likely have an impact on any other process that is serving for
   an extended period of time.  (John Arbash Meinel, #494406)
 
+* Check for SIGINT (Ctrl-C) and other signals immediately if ``readdir``
+  returns ``EINTR`` by calling ``PyErr_CheckSignals``.  This affected the
+  optional ``_readdir_pyx`` extension.  (Andrew Bennetts, #495023)
+
+* Give a clearer message if the lockdir disappears after being apparently
+  successfully taken.  (Martin Pool, #498378)
+
+* The 2a format wasn't properly restarting autopacks when something
+  changed underneath it (like another autopack). Now concurrent
+  autopackers will properly succeed. (John Arbash Meinel, #495000)
+
 * ``_update_current_block`` no longer suppresses exceptions, so ^C at just
   the right time will get propagated, rather than silently failing to move
   the block pointer. (John Arbash Meinel, #495023)
 
-
 Improvements
 ************
 

=== modified file 'bzrlib/_readdir_pyx.pyx'
--- a/bzrlib/_readdir_pyx.pyx	2009-10-08 07:03:05 +0000
+++ b/bzrlib/_readdir_pyx.pyx	2009-12-23 02:19:04 +0000
@@ -78,6 +78,7 @@
 
 
 cdef extern from 'Python.h':
+    int PyErr_CheckSignals() except -1
     char * PyString_AS_STRING(object)
     ctypedef int Py_ssize_t # Required for older pyrex versions
     ctypedef struct PyObject:
@@ -271,6 +272,12 @@
         return result
 
 
+cdef raise_os_error(int errnum, char *msg_prefix, path):
+    if errnum == EINTR:
+        PyErr_CheckSignals()
+    raise OSError(errnum, msg_prefix + strerror(errnum), path)
+
+
 cdef _read_dir(path):
     """Like os.listdir, this reads the contents of a directory.
 
@@ -298,16 +305,16 @@
         # passing full paths every time.
         orig_dir_fd = open(".", O_RDONLY, 0)
         if orig_dir_fd == -1:
-            raise OSError(errno, "open: " + strerror(errno), ".")
+            raise_os_error(errno, "open: ", ".")
         if -1 == chdir(path):
-            raise OSError(errno, "chdir: " + strerror(errno), path)
+            raise_os_error(errno, "chdir: ", path)
     else:
         orig_dir_fd = -1
 
     try:
         the_dir = opendir(".")
         if NULL == the_dir:
-            raise OSError(errno, "opendir: " + strerror(errno), path)
+            raise_os_error(errno, "opendir: ", path)
         try:
             result = []
             entry = &sentinel
@@ -319,6 +326,8 @@
                     errno = 0
                     entry = readdir(the_dir)
                     if entry == NULL and (errno == EAGAIN or errno == EINTR):
+                        if errno == EINTR:
+                            PyErr_CheckSignals()
                         # try again
                         continue
                     else:
@@ -330,7 +339,7 @@
                         # we consider ENOTDIR to be 'no error'.
                         continue
                     else:
-                        raise OSError(errno, "readdir: " + strerror(errno), path)
+                        raise_os_error(errno, "readdir: ", path)
                 name = entry.d_name
                 if not (name[0] == c"." and (
                     (name[1] == 0) or 
@@ -340,7 +349,7 @@
                     stat_result = lstat(entry.d_name, &statvalue._st)
                     if stat_result != 0:
                         if errno != ENOENT:
-                            raise OSError(errno, "lstat: " + strerror(errno),
+                            raise_os_error(errno, "lstat: ",
                                 path + "/" + entry.d_name)
                         else:
                             # the file seems to have disappeared after being
@@ -358,7 +367,7 @@
                         statvalue, None))
         finally:
             if -1 == closedir(the_dir):
-                raise OSError(errno, "closedir: " + strerror(errno), path)
+                raise_os_error(errno, "closedir: ", path)
     finally:
         if -1 != orig_dir_fd:
             failed = False
@@ -366,7 +375,7 @@
                 # try to close the original directory anyhow
                 failed = True
             if -1 == close(orig_dir_fd) or failed:
-                raise OSError(errno, "return to orig_dir: " + strerror(errno))
+                raise_os_error(errno, "return to orig_dir: ", "")
 
     return result
 

=== modified file 'bzrlib/lockdir.py'
--- a/bzrlib/lockdir.py	2009-07-27 05:24:02 +0000
+++ b/bzrlib/lockdir.py	2009-12-21 06:17:05 +0000
@@ -240,8 +240,16 @@
         # incorrect.  It's possible some other servers or filesystems will
         # have a similar bug allowing someone to think they got the lock
         # when it's already held.
+        #
+        # See <https://bugs.edge.launchpad.net/bzr/+bug/498378> for one case.
+        #
+        # Strictly the check is unnecessary and a waste of time for most
+        # people, but probably worth trapping if something is wrong.
         info = self.peek()
         self._trace("after locking, info=%r", info)
+        if info is None:
+            raise LockFailed(self, "lock was renamed into place, but "
+                "now is missing!")
         if info['nonce'] != self.nonce:
             self._trace("rename succeeded, "
                 "but lock is still held by someone else")

=== modified file 'bzrlib/repofmt/groupcompress_repo.py'
--- a/bzrlib/repofmt/groupcompress_repo.py	2009-09-24 20:03:43 +0000
+++ b/bzrlib/repofmt/groupcompress_repo.py	2009-12-16 20:20:04 +0000
@@ -352,7 +352,8 @@
         """Build a VersionedFiles instance on top of this group of packs."""
         index_name = index_name + '_index'
         index_to_pack = {}
-        access = knit._DirectPackAccess(index_to_pack)
+        access = knit._DirectPackAccess(index_to_pack,
+                                        reload_func=self._reload_func)
         if for_write:
             # Use new_pack
             if self.new_pack is None:

=== modified file 'bzrlib/tests/per_pack_repository.py'
--- a/bzrlib/tests/per_pack_repository.py	2009-09-07 03:00:23 +0000
+++ b/bzrlib/tests/per_pack_repository.py	2009-12-16 22:00:39 +0000
@@ -546,6 +546,42 @@
         finally:
             tree.unlock()
 
+    def test_concurrent_pack_during_autopack(self):
+        tree = self.make_branch_and_tree('tree')
+        tree.lock_write()
+        try:
+            for i in xrange(9):
+                tree.commit('rev %d' % (i,))
+            r2 = repository.Repository.open('tree')
+            r2.lock_write()
+            try:
+                # Monkey patch so that pack occurs while the other repo is
+                # autopacking. This is slightly bad, but all current pack
+                # repository implementations have a _pack_collection, and we
+                # test that it gets triggered. So if a future format changes
+                # things, the test will fail rather than succeed accidentally.
+                autopack_count = [0]
+                r1 = tree.branch.repository
+                orig = r1._pack_collection.pack_distribution
+                def trigger_during_auto(*args, **kwargs):
+                    ret = orig(*args, **kwargs)
+                    if not autopack_count[0]:
+                        r2.pack()
+                    autopack_count[0] += 1
+                    return ret
+                r1._pack_collection.pack_distribution = trigger_during_auto
+                tree.commit('autopack-rev')
+                # This triggers 2 autopacks. The first one causes r2.pack() to
+                # fire, but r2 doesn't see the new pack file yet. The
+                # autopack restarts and sees there are 2 files and there
+                # should be only 1 for 10 commits. So it goes ahead and
+                # finishes autopacking.
+                self.assertEqual([2], autopack_count)
+            finally:
+                r2.unlock()
+        finally:
+            tree.unlock()
+
     def test_lock_write_does_not_physically_lock(self):
         repo = self.make_repository('.', format=self.get_format())
         repo.lock_write()



More information about the bazaar-commits mailing list