[Zodb-checkins] SVN: ZODB/trunk/src/ Fixed yet another threading bug in handling new oids.
Jim Fulton
jim at zope.com
Thu Nov 6 16:13:43 EST 2008
Log message for revision 92817:
Fixed yet another threading bug in handling new oids.
Changed:
U ZODB/trunk/src/CHANGES.txt
U ZODB/trunk/src/ZODB/DemoStorage.py
U ZODB/trunk/src/ZODB/DemoStorage.test
U ZODB/trunk/src/ZODB/tests/testDemoStorage.py
-=-
Modified: ZODB/trunk/src/CHANGES.txt
===================================================================
--- ZODB/trunk/src/CHANGES.txt 2008-11-06 17:41:17 UTC (rev 92816)
+++ ZODB/trunk/src/CHANGES.txt 2008-11-06 21:13:41 UTC (rev 92817)
@@ -22,6 +22,15 @@
XXX There are known issues with this implementation that need to be
sorted out before it is "released".
+3.9.0a4 (2008-11-04)
+====================
+
+Bug Fixes
+---------
+
+- DemoStorage could sometimes hand out the same new object id more
+ than once.
+
3.9.0a3 (2008-11-04)
====================
Modified: ZODB/trunk/src/ZODB/DemoStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/DemoStorage.py 2008-11-06 17:41:17 UTC (rev 92816)
+++ ZODB/trunk/src/ZODB/DemoStorage.py 2008-11-06 21:13:41 UTC (rev 92817)
@@ -58,13 +58,16 @@
self.changes = changes
self._issued_oids = set()
+ self._stored_oids = set()
+ self._commit_lock = threading.Lock()
+ self._transaction = None
+
if name is None:
name = 'DemoStorage(%r, %r)' % (base.getName(), changes.getName())
self.__name__ = name
self._copy_methods_from_changes(changes)
-
def _blobify(self):
if (self._temporary_changes and
@@ -92,8 +95,7 @@
for meth in (
'_lock_acquire', '_lock_release',
'getSize', 'history', 'isReadOnly', 'registerDB',
- 'sortKey', 'tpc_begin', 'tpc_abort', 'tpc_finish',
- 'tpc_transaction', 'tpc_vote',
+ 'sortKey', 'tpc_transaction', 'tpc_vote',
):
setattr(self, meth, getattr(changes, meth))
@@ -229,10 +231,12 @@
def store(self, oid, serial, data, version, transaction):
assert version=='', "versions aren't supported"
+ if transaction is not self._transaction:
+ raise ZODB.POSException.StorageTransactionError(self, transaction)
# Since the OID is being used, we don't have to keep up with it any
- # more.
- self._issued_oids.discard(oid)
+ # more. Save it now so we can forget it later. :)
+ self._stored_oids.add(oid)
# See if we already have changes for this oid
try:
@@ -251,18 +255,21 @@
def storeBlob(self, oid, oldserial, data, blobfilename, version,
transaction):
+ assert version=='', "versions aren't supported"
+ if transaction is not self._transaction:
+ raise ZODB.POSException.StorageTransactionError(self, transaction)
# Since the OID is being used, we don't have to keep up with it any
- # more.
- self._issued_oids.discard(oid)
+ # more. Save it now so we can forget it later. :)
+ self._stored_oids.add(oid)
try:
return self.changes.storeBlob(
- oid, oldserial, data, blobfilename, version, transaction)
+ oid, oldserial, data, blobfilename, '', transaction)
except AttributeError:
if self._blobify():
return self.changes.storeBlob(
- oid, oldserial, data, blobfilename, version, transaction)
+ oid, oldserial, data, blobfilename, '', transaction)
raise
def temporaryDirectory(self):
@@ -273,6 +280,37 @@
return self.changes.temporaryDirectory()
raise
+ @ZODB.utils.locked
+ def tpc_abort(self, transaction):
+ if transaction is not self._transaction:
+ return
+ self._stored_oids = set()
+ self._transaction = None
+ self.changes.tpc_abort(transaction)
+ self._commit_lock.release()
+
+ @ZODB.utils.locked
+ def tpc_begin(self, transaction, *a, **k):
+ # The tid argument exists to support testing.
+ if transaction is self._transaction:
+ return
+ self._lock_release()
+ self._commit_lock.acquire()
+ self._lock_acquire()
+ self.changes.tpc_begin(transaction, *a, **k)
+ self._transaction = transaction
+ self._stored_oids = set()
+
+ @ZODB.utils.locked
+ def tpc_finish(self, transaction, func = lambda tid: None):
+ if (transaction is not self._transaction):
+ return
+ self._issued_oids.difference_update(self._stored_oids)
+ self._stored_oids = set()
+ self._transaction = None
+ self.changes.tpc_finish(transaction, func)
+ self._commit_lock.release()
+
_temporary_blobdirs = {}
def cleanup_temporary_blobdir(
ref,
Modified: ZODB/trunk/src/ZODB/DemoStorage.test
===================================================================
--- ZODB/trunk/src/ZODB/DemoStorage.test 2008-11-06 17:41:17 UTC (rev 92816)
+++ ZODB/trunk/src/ZODB/DemoStorage.test 2008-11-06 21:13:41 UTC (rev 92817)
@@ -365,6 +365,10 @@
>>> t = transaction.begin()
>>> storage.tpc_begin(t)
>>> tid = storage.store(oid, 0, 'data', '', t)
+ >>> storage.tpc_vote(t)
+ >>> oid in storage._issued_oids
+ True
+ >>> storage.tpc_finish(t)
...there's no need to remember it any longer:
Modified: ZODB/trunk/src/ZODB/tests/testDemoStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/testDemoStorage.py 2008-11-06 17:41:17 UTC (rev 92816)
+++ ZODB/trunk/src/ZODB/tests/testDemoStorage.py 2008-11-06 21:13:41 UTC (rev 92817)
@@ -128,7 +128,7 @@
... print self.name, 'closed'
... sortKey = getSize = __len__ = history = getTid = None
... tpc_finish = tpc_vote = tpc_transaction = None
- ... _lock_acquire = _lock_release = lambda: None
+ ... _lock_acquire = _lock_release = lambda self: None
... getName = lambda self: 'S'
... isReadOnly = tpc_transaction = None
... supportsUndo = undo = undoLog = undoInfo = None
More information about the Zodb-checkins
mailing list