diff --git a/BTrees/tests/common.py b/BTrees/tests/common.py index 28eb33a..37e6074 100644 --- a/BTrees/tests/common.py +++ b/BTrees/tests/common.py @@ -70,6 +70,11 @@ def _getRoot(self): return self.db.open().root() def _closeRoot(self, root): + import transaction + # If we don't commit/abort the transaction, then + # closing the Connection tends to fail with + # "Cannot close connection joined to transaction" + transaction.abort() root._p_jar.close() @_skip_wo_ZODB diff --git a/BTrees/tests/testConflict.py b/BTrees/tests/testConflict.py index 68af153..2726521 100644 --- a/BTrees/tests/testConflict.py +++ b/BTrees/tests/testConflict.py @@ -24,6 +24,32 @@ def _getTargetClass(self): from BTrees.OOBTree import OOBTree return OOBTree + def openDB(self): + # The conflict tests tend to open two or more connections + # and then try to commit them. A standard FileStorage + # is not MVCC aware, and so each connection would have the same + # instance of the storage, leading to the error + # "Duplicate tpc_begin calls for same transaction" on commit; + # thus we use a MVCCMappingStorage for these tests, ensuring each + # connection has its own storage. + # Unfortunately, it wants to acquire the identically same + # non-recursive lock in each of its *its* tpc_* methods, which deadlocks. + # The solution is to give each instance its own lock, and trust in the + # serialization (ordering) of the datamanager, and the fact that these tests are + # single-threaded. + import threading + from ZODB.tests.MVCCMappingStorage import MVCCMappingStorage + class _MVCCMappingStorage(MVCCMappingStorage): + def new_instance(self): + inst = MVCCMappingStorage.new_instance(self) + inst._commit_lock = threading.Lock() + return inst + from ZODB.DB import DB + self.storage = _MVCCMappingStorage() + self.db = DB(self.storage) + return self.db + + @_skip_wo_ZODB def testSimpleConflict(self): # Invoke conflict resolution by committing a transaction and @@ -478,7 +504,7 @@ def testConflictWithOneEmptyBucket(self): @_skip_wo_ZODB def testConflictOfInsertAndDeleteOfFirstBucketItem(self): - """ + """ testConflictOfInsertAndDeleteOfFirstBucketItem Recently, BTrees became careful about removing internal keys (keys in internal aka BTree nodes) when they were deleted from buckets. This poses a problem for conflict resolution.