[Checkins] SVN: ZODB/trunk/src/ZODB/ Fixed an undo bug that affects file storages that support blobs in

Jim Fulton jim at zope.com
Mon Jan 5 14:24:13 EST 2009


Log message for revision 94540:
  Fixed an undo bug that affects file storages that support blobs in
  special cases involving undo of undo of undo of object additions.
  

Changed:
  U   ZODB/trunk/src/ZODB/FileStorage/FileStorage.py
  U   ZODB/trunk/src/ZODB/tests/testFileStorage.py

-=-
Modified: ZODB/trunk/src/ZODB/FileStorage/FileStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/FileStorage/FileStorage.py	2009-01-05 16:53:07 UTC (rev 94539)
+++ ZODB/trunk/src/ZODB/FileStorage/FileStorage.py	2009-01-05 19:24:12 UTC (rev 94540)
@@ -984,15 +984,19 @@
             else:
 
                 if self.blob_dir and not p and prev:
-                    up, userial = self._loadBackTxn(h.oid, prev)
-                    if ZODB.blob.is_blob_record(up):
-                        # We're undoing a blob modification operation.
-                        # We have to copy the blob data
-                        tmp = ZODB.utils.mktemp(dir=self.fshelper.temp_dir)
-                        ZODB.utils.cp(
-                            self.openCommittedBlobFile(h.oid, userial),
-                            open(tmp, 'wb'))
-                        self._blob_storeblob(h.oid, self._tid, tmp)
+                    try:
+                        up, userial = self._loadBackTxn(h.oid, prev)
+                    except ZODB.POSException.POSKeyError:
+                        pass # It was removed, so no need to copy data
+                    else:
+                        if ZODB.blob.is_blob_record(up):
+                            # We're undoing a blob modification operation.
+                            # We have to copy the blob data
+                            tmp = ZODB.utils.mktemp(dir=self.fshelper.temp_dir)
+                            ZODB.utils.cp(
+                                self.openCommittedBlobFile(h.oid, userial),
+                                open(tmp, 'wb'))
+                            self._blob_storeblob(h.oid, self._tid, tmp)
 
                 new = DataHeader(h.oid, self._tid, ipos, otloc, 0, len(p))
 

Modified: ZODB/trunk/src/ZODB/tests/testFileStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/testFileStorage.py	2009-01-05 16:53:07 UTC (rev 94539)
+++ ZODB/trunk/src/ZODB/tests/testFileStorage.py	2009-01-05 19:24:12 UTC (rev 94540)
@@ -27,18 +27,8 @@
 from ZODB.tests import ReadOnlyStorage, RecoveryStorage
 from ZODB.tests.StorageTestBase import MinPO, zodb_pickle
 
-class BaseFileStorageTests(StorageTestBase.StorageTestBase):
-
-    def open(self, **kwargs):
-        self._storage = ZODB.FileStorage.FileStorage('FileStorageTests.fs',
-                                                     **kwargs)
-
-    def setUp(self):
-        StorageTestBase.StorageTestBase.setUp(self)
-        self.open(create=1)
-
 class FileStorageTests(
-    BaseFileStorageTests,
+    StorageTestBase.StorageTestBase,
     BasicStorage.BasicStorage,
     TransactionalUndoStorage.TransactionalUndoStorage,
     RevisionStorage.RevisionStorage,
@@ -55,6 +45,14 @@
     ReadOnlyStorage.ReadOnlyStorage
     ):
 
+    def open(self, **kwargs):
+        self._storage = ZODB.FileStorage.FileStorage('FileStorageTests.fs',
+                                                     **kwargs)
+
+    def setUp(self):
+        StorageTestBase.StorageTestBase.setUp(self)
+        self.open(create=1)
+
     def checkLongMetadata(self):
         s = "X" * 75000
         try:
@@ -287,7 +285,14 @@
             else:
                 self.assertNotEqual(next_oid, None)
 
+class FileStorageTestsWithBlobsEnabled(FileStorageTests):
 
+    def open(self, **kwargs):
+        if 'blob_dir' not in kwargs:
+            kwargs = kwargs.copy()
+            kwargs['blob_dir'] = 'blobs'
+        return FileStorageTests.open(self, **kwargs)
+
 class FileStorageRecoveryTest(
     StorageTestBase.StorageTestBase,
     RecoveryStorage.RecoveryStorage,
@@ -301,7 +306,6 @@
     def tearDown(self):
         self._dst.close()
         StorageTestBase.StorageTestBase.tearDown(self)
-        
 
     def new_dest(self):
         return ZODB.FileStorage.FileStorage('Dest.fs')
@@ -332,23 +336,6 @@
         pass
 
 
-class SlowFileStorageTest(BaseFileStorageTests):
-
-    def check10Kstores(self):
-        # The _get_cached_serial() method has a special case
-        # every 8000 calls.  Make sure it gets minimal coverage.
-        oids = [[self._storage.new_oid(), None] for i in range(100)]
-        for i in range(100):
-            t = transaction.Transaction()
-            self._storage.tpc_begin(t)
-            for j in range(100):
-                o = MinPO(j)
-                oid, revid = oids[j]
-                serial = self._storage.store(oid, revid, zodb_pickle(o), "", t)
-                oids[j][1] = serial
-            self._storage.tpc_vote(t)
-            self._storage.tpc_finish(t)
-
 # Raise an exception if the tids in FileStorage fs aren't
 # strictly increasing.
 def checkIncreasingTids(fs):
@@ -494,7 +481,7 @@
 
 def deal_with_finish_failures():
     r"""
-    
+
     It's really bad to get errors in FileStorage's _finish method, as
     that can cause the file storage to be in an inconsistent
     state. The data file will be fine, but the internal data
@@ -523,7 +510,7 @@
     ...
     TypeError: <lambda>() takes no arguments (1 given)
 
-    
+
     >>> print handler
     ZODB.FileStorage CRITICAL
       Failure in _finish. Closing.
@@ -559,7 +546,7 @@
     >>> conn1.add(conn1.root()[1])
     >>> conn1.root()[1].open('w').write('some data')
     >>> tm1.commit()
-    
+
     >>> tm2 = transaction.TransactionManager()
     >>> conn2 = db.open(tm2)
     >>> f = conn1.root()[1].open()
@@ -586,7 +573,8 @@
     suite = unittest.TestSuite()
     for klass in [FileStorageTests, Corruption.FileStorageCorruptTests,
                   FileStorageRecoveryTest, FileStorageNoRestoreRecoveryTest,
-                  SlowFileStorageTest]:
+                  FileStorageTestsWithBlobsEnabled,
+                  ]:
         suite.addTest(unittest.makeSuite(klass, "check"))
     suite.addTest(doctest.DocTestSuite(
         setUp=zope.testing.setupstack.setUpDirectory,



More information about the Checkins mailing list