[Zodb-checkins]
SVN: ZODB/branches/blob-merge-branch/src/ZODB/Blobs/
Fix bug in transaction abort which results in uncommitted
data building
Michael Kerrin
michael.kerrin at openapp.biz
Mon Dec 5 13:43:13 EST 2005
Log message for revision 40553:
Fix bug in transaction abort which results in uncommitted data building
up on the system. Also add some tests for the configuration of BlobStorage.
Changed:
U ZODB/branches/blob-merge-branch/src/ZODB/Blobs/Blob.py
A ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/test_config.py
U ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/transaction.txt
-=-
Modified: ZODB/branches/blob-merge-branch/src/ZODB/Blobs/Blob.py
===================================================================
--- ZODB/branches/blob-merge-branch/src/ZODB/Blobs/Blob.py 2005-12-05 18:26:49 UTC (rev 40552)
+++ ZODB/branches/blob-merge-branch/src/ZODB/Blobs/Blob.py 2005-12-05 18:43:12 UTC (rev 40553)
@@ -2,7 +2,6 @@
import os
import time
import tempfile
-import weakref
from zope.interface import implements
@@ -22,6 +21,11 @@
_p_blob_uncommitted = None
_p_blob_data = None
+ # All persistent object store a reference to their data manager, a database
+ # connection in the _p_jar attribute. So we are going to do the same with
+ # blobs here.
+ _p_blob_manager = None
+
def open(self, mode="r"):
""" Returns a file(-like) object representing blob data. This
method will either return the file object, raise a BlobError
@@ -86,8 +90,14 @@
# counts that keep track of open readers and writers and
# close any writable filehandles we've opened.
- dm = BlobDataManager(self, result)
- transaction.get().register(dm)
+ if self._p_blob_manager is None:
+ dm = BlobDataManager(self, result)
+ transaction.get().register(dm)
+ else:
+ # each blob data manager should manage only the one blob
+ # 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)
return result
@@ -144,10 +154,14 @@
# we keep a weakref to the file handle because we don't want to
# keep it alive if all other references to it die (e.g. in the
# case it's opened without assigning it to a name).
- self.fhref = weakref.ref(filehandle)
+ self.fhrefs = utils.WeakSet()
+ self.register_fh(filehandle)
self.subtransaction = False
self.sortkey = time.time()
+ def register_fh(self, filehandle):
+ self.fhrefs.add(filehandle)
+
def abort_sub(self, transaction):
pass
@@ -169,16 +183,15 @@
def commit(self, object, transaction):
if not self.subtransaction:
self.blob._p_blob_clear() # clear all blob refcounts
- filehandle = self.fhref()
- if filehandle is not None:
- filehandle.close()
+ self.fhrefs.map(lambda fhref: fhref.close())
def abort(self, object, transaction):
if not self.subtransaction:
self.blob._p_blob_clear()
- filehandle = self.fhref()
- if filehandle is not None:
- filehandle.close()
+ self.fhrefs.map(lambda fhref: fhref.close())
+ if self.blob._p_blob_uncommitted is not None and \
+ os.path.exists(self.blob._p_blob_uncommitted):
+ os.unlink(self.blob._p_blob_uncommitted)
def sortKey(self):
return self.sortkey
Added: ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/test_config.py
===================================================================
--- ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/test_config.py 2005-12-05 18:26:49 UTC (rev 40552)
+++ ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/test_config.py 2005-12-05 18:43:12 UTC (rev 40553)
@@ -0,0 +1,78 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import tempfile, shutil, unittest
+
+from ZODB.tests.testConfig import ConfigTestBase
+from ZConfig import ConfigurationSyntaxError
+
+class BlobConfigTestBase(ConfigTestBase):
+
+ def setUp(self):
+ super(BlobConfigTestBase, self).setUp()
+
+ self.blob_dir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ super(BlobConfigTestBase, self).tearDown()
+
+ shutil.rmtree(self.blob_dir)
+
+
+class ZODBBlobConfigTest(BlobConfigTestBase):
+
+ def test_map_config1(self):
+ self._test(
+ """
+ <zodb>
+ <blobstorage>
+ blob-dir %s
+ <mappingstorage/>
+ </blobstorage>
+ </zodb>
+ """ % self.blob_dir)
+
+ def test_file_config1(self):
+ path = tempfile.mktemp()
+ self._test(
+ """
+ <zodb>
+ <blobstorage>
+ blob-dir %s
+ <filestorage>
+ path %s
+ </filestorage>
+ </blobstorage>
+ </zodb>
+ """ %(self.blob_dir, path))
+
+ def test_blod_dir_needed(self):
+ self.assertRaises(ConfigurationSyntaxError,
+ self._test,
+ """
+ <zodb>
+ <blobstorage>
+ <mappingstorage/>
+ </blobstorage>
+ </zodb>
+ """)
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(ZODBBlobConfigTest))
+
+ return suite
+
+if __name__ == '__main__':
+ unittest.main(defaultTest = 'test_suite')
Property changes on: ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/test_config.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/transaction.txt
===================================================================
--- ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/transaction.txt 2005-12-05 18:26:49 UTC (rev 40552)
+++ ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/transaction.txt 2005-12-05 18:43:12 UTC (rev 40553)
@@ -109,6 +109,8 @@
>>> bool(blob1a._p_changed)
False
+ >>> blob1a.open('r').read()
+ 'this is blob 1'
>>> blob1afh3 = blob1a.open('a')
>>> blob1afh3.write('woot!')
>>> blob1a._p_blob_refcounts()
@@ -125,6 +127,8 @@
>>> transaction.commit()
>>> blob2._p_blob_refcounts()
(0, 0)
+ >>> blob1._p_blob_refcounts()
+ (0, 0)
Since we committed the current transaction above, the aggregate
changes we've made to blob, blob1a (these refer to the same object) and
More information about the Zodb-checkins
mailing list