bigfile/zodb: ZBlk._p_invalidate() can be called more than once, in particular in case of conflicts
When there is a conflict (on any object, but on ZBlk in particular) ZODB machinery calls its ._p_invalidate() twice: File ".../wendelin.core/bigfile/tests/test_filezodb.py", line 661, in test_bigfile_filezodb_vs_conflicts tm2.commit() # this should raise ConflictError and stay at 11 state File ".../transaction/_manager.py", line 111, in commit return self.get().commit() File ".../transaction/_transaction.py", line 271, in commit self._commitResources() File ".../transaction/_transaction.py", line 414, in _commitResources self._cleanup(L) File ".../transaction/_transaction.py", line 426, in _cleanup rm.abort(self) File ".../ZODB/Connection.py", line 436, in abort self._abort() File ".../ZODB/Connection.py", line 479, in _abort self._cache.invalidate(oid) File ".../wendelin.core/bigfile/file_zodb.py", line 148, in _p_invalidate traceback.print_stack() and File ".../wendelin.core/bigfile/tests/test_filezodb.py", line 661, in test_bigfile_filezodb_vs_conflicts tm2.commit() # this should raise ConflictError and stay at 11 state File ".../transaction/_manager.py", line 111, in commit return self.get().commit() File ".../transaction/_transaction.py", line 271, in commit self._commitResources() File ".../transaction/_transaction.py", line 416, in _commitResources self._synchronizers.map(lambda s: s.afterCompletion(self)) File ".../transaction/weakset.py", line 59, in map f(elt) File ".../transaction/_transaction.py", line 416, in <lambda> self._synchronizers.map(lambda s: s.afterCompletion(self)) File ".../ZODB/Connection.py", line 831, in _storage_sync self._flush_invalidations() File ".../ZODB/Connection.py", line 539, in _flush_invalidations self._cache.invalidate(invalidated) File ".../wendelin.core/bigfile/file_zodb.py", line 148, in _p_invalidate traceback.print_stack() i.e. first invalidation is done by commit cleanup: https://github.com/zopefoundation/transaction/blob/1.4.4/transaction/_transaction.py#L414 https://github.com/zopefoundation/ZODB/blob/3.10/src/ZODB/Connection.py#L479 and then Connection.afterCompletion() flushes invalidation again: https://github.com/zopefoundation/transaction/blob/1.4.4/transaction/_transaction.py#L416 https://github.com/zopefoundation/ZODB/blob/3.10/src/ZODB/Connection.py#L833 https://github.com/zopefoundation/ZODB/blob/3.10/src/ZODB/Connection.py#L539 If there was no conflict - there will be no ConflictError raised and thus no Transaction._cleanup() done in its ._commitResources() -> invalidation called only once. But with ConflictError - it is twice. Adjust ZBlk._p_invalidate() not to delve into real invalidation more than once - else we will fail, as ZBlk._v_zfile becomes unbound after invalidation done the first time.
Showing
Please register or sign in to comment