[Zodb-checkins]
SVN: ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/
- fixed bug in consumeFile() because it forgot to set
_p_changed correctly
Christian Theune
ct at gocept.com
Thu Mar 8 14:38:42 EST 2007
Log message for revision 73071:
- fixed bug in consumeFile() because it forgot to set _p_changed correctly
Changed:
U ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/Blob.py
U ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/tests/test_undo.py
-=-
Modified: ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/Blob.py
===================================================================
--- ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/Blob.py 2007-03-08 18:46:17 UTC (rev 73070)
+++ ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/Blob.py 2007-03-08 19:38:41 UTC (rev 73071)
@@ -101,35 +101,7 @@
raise IOError('invalid mode: %s ' % mode)
if result is not None:
- # We join the transaction with our own data manager in order to be
- # notified of commit/vote/abort events. We do this because at
- # transaction boundaries, we need to fix up _p_ reference counts
- # that keep track of open readers and writers and close any
- # writable filehandles we've opened.
- if self._p_blob_manager is None:
- # Blobs need to always participate in transactions.
- if self._p_jar is not None:
- # If we are connected to a database, then we use the
- # transaction manager that belongs to this connection
- tm = self._p_jar.transaction_manager
- else:
- # If we are not connected to a database, we check whether
- # we have been given an explicit transaction manager
- if self._p_blob_transaction:
- tm = self._p_blob_transaction
- else:
- # Otherwise we use the default
- # transaction manager as an educated guess.
- tm = transaction.manager
- # Create our datamanager and join he current transaction.
- dm = BlobDataManager(self, result, tm)
- tm.get().join(dm)
- else:
- # Each blob data manager should manage only the one blob
- # assigned to it. Assert that this is the case and it is the
- # correct blob
- assert self._p_blob_manager.blob is self
- self._p_blob_manager.register_fh(result)
+ self._setup_transaction_manager(result)
return result
def openDetached(self, class_=file):
@@ -189,6 +161,10 @@
# set aside.
os.unlink(target_aside)
+ # We changed the blob state and have to make sure we join the
+ # transaction.
+ self._change()
+
# utility methods
def _current_filename(self):
@@ -205,6 +181,37 @@
def _change(self):
self._p_changed = 1
+ def _setup_transaction_manager(self, result):
+ # We join the transaction with our own data manager in order to be
+ # notified of commit/vote/abort events. We do this because at
+ # transaction boundaries, we need to fix up _p_ reference counts
+ # that keep track of open readers and writers and close any
+ # writable filehandles we've opened.
+ if self._p_blob_manager is None:
+ # Blobs need to always participate in transactions.
+ if self._p_jar is not None:
+ # If we are connected to a database, then we use the
+ # transaction manager that belongs to this connection
+ tm = self._p_jar.transaction_manager
+ else:
+ # If we are not connected to a database, we check whether
+ # we have been given an explicit transaction manager
+ if self._p_blob_transaction:
+ tm = self._p_blob_transaction
+ else:
+ # Otherwise we use the default
+ # transaction manager as an educated guess.
+ tm = transaction.manager
+ # Create our datamanager and join he current transaction.
+ dm = BlobDataManager(self, result, tm)
+ tm.get().join(dm)
+ elif result:
+ # Each blob data manager should manage only the one blob
+ # assigned to it. Assert that this is the case and it is the
+ # correct blob
+ assert self._p_blob_manager.blob is self
+ self._p_blob_manager.register_fh(result)
+
# utility methods which should not cause the object's state to be
# loaded if they are called while the object is a ghost. Thus,
# they are named with the _p_ convention and only operate against
Modified: ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/tests/test_undo.py
===================================================================
--- ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/tests/test_undo.py 2007-03-08 18:46:17 UTC (rev 73070)
+++ ZODB/branches/ctheune-blobszerocopy/src/ZODB/Blobs/tests/test_undo.py 2007-03-08 19:38:41 UTC (rev 73071)
@@ -94,6 +94,47 @@
self.assertEqual(blob.open('r').read(), 'this is state 1')
transaction.abort()
+ def testUndoAfterConsumption(self):
+ base_storage = FileStorage(self.storagefile)
+ blob_storage = BlobStorage(self.blob_dir, base_storage)
+ database = DB(blob_storage)
+ connection = database.open()
+ root = connection.root()
+ transaction.begin()
+ to_consume = tempfile.NamedTemporaryFile()
+ to_consume.write('this is state 1')
+ to_consume.flush()
+
+ blob = Blob()
+ blob.consumeFile(to_consume.name)
+
+ root['blob'] = blob
+ transaction.commit()
+
+ transaction.begin()
+ blob = root['blob']
+ to_consume = tempfile.NamedTemporaryFile()
+ to_consume.write('this is state 2')
+ to_consume.flush()
+ blob.consumeFile(to_consume.name)
+ transaction.commit()
+
+ transaction.begin()
+ blob = root['blob']
+ self.assertEqual(blob.open('r').read(), 'this is state 2')
+ transaction.abort()
+
+ serial = base64.encodestring(blob_storage._tid)
+
+ transaction.begin()
+ blob_storage.undo(serial, blob_storage._transaction)
+ transaction.commit()
+
+ transaction.begin()
+ blob = root['blob']
+ self.assertEqual(blob.open('r').read(), 'this is state 1')
+ transaction.abort()
+
def testRedo(self):
base_storage = FileStorage(self.storagefile)
blob_storage = BlobStorage(self.blob_dir, base_storage)
More information about the Zodb-checkins
mailing list