[Zodb-checkins] SVN: ZODB/branches/blob-merge-branch/src/ZODB/Blobs/ Still-broken undo code that doesn't pdb.set_trace ; -)

Chris McDonough chrism at plope.com
Tue Feb 28 14:47:15 EST 2006


Log message for revision 65605:
  Still-broken undo code that doesn't pdb.set_trace ;-)
  
  It was impossible to commit a transaction that involved a blob that hadn't
  had its 'open' method called, because the blob filename is computed during open.
  

Changed:
  U   ZODB/branches/blob-merge-branch/src/ZODB/Blobs/BlobStorage.py
  U   ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/connection.txt

-=-
Modified: ZODB/branches/blob-merge-branch/src/ZODB/Blobs/BlobStorage.py
===================================================================
--- ZODB/branches/blob-merge-branch/src/ZODB/Blobs/BlobStorage.py	2006-02-28 19:47:13 UTC (rev 65604)
+++ ZODB/branches/blob-merge-branch/src/ZODB/Blobs/BlobStorage.py	2006-02-28 19:47:14 UTC (rev 65605)
@@ -61,21 +61,24 @@
                                        # something else
 
         self._lock_acquire()
-        try:
-            targetpath = self.fshelper.getPathForOID(oid)
-            if not os.path.exists(targetpath):
-                os.makedirs(targetpath, 0700)
-                              
-            targetname = self.fshelper.getBlobFilename(oid, serial)
-            os.rename(blobfilename, targetname)
+        # the user may not have called "open" on the blob object,
+        # in which case, the blob will not have a filename.
+        if blobfilename is not None:
+            try:
+                targetpath = self.fshelper.getPathForOID(oid)
+                if not os.path.exists(targetpath):
+                    os.makedirs(targetpath, 0700)
 
-            # XXX if oid already in there, something is really hosed.
-            # The underlying storage should have complained anyway
-            self.dirty_oids.append((oid, serial))
-        finally:
-            self._lock_release()
-        return self._tid
+                targetname = self.fshelper.getBlobFilename(oid, serial)
+                os.rename(blobfilename, targetname)
 
+                # XXX if oid already in there, something is really hosed.
+                # The underlying storage should have complained anyway
+                self.dirty_oids.append((oid, serial))
+            finally:
+                self._lock_release()
+            return self._tid
+
     def tpc_finish(self, *arg, **kw):
         """ We need to override the base storage's tpc_finish instead of
         providing a _finish method because methods found on the proxied object
@@ -193,29 +196,52 @@
         return orig_size + blob_size
 
     def undo(self, serial_id, transaction):
-        import pdb; pdb.set_trace() 
-        serial, keys = getProxiedObject(self).undo(serial_id, transaction)
+        undo_serial, keys = getProxiedObject(self).undo(serial_id, transaction)
+        # serial_id is the transaction id of the txn that we wish to undo.
+        # "undo_serial" is the transaction id of txn in which the undo is
+        # performed.  "keys" is the list of oids that are involved in the
+        # undo transaction.
+
+        # The serial_id is assumed to be given to us base-64 encoded
+        # (belying the web UI legacy of the ZODB code :-()
+        serial_id = base64.decodestring(serial_id+'\n')
+
         self._lock_acquire()
+
         try:
-            # The old serial_id is given in base64 encoding ...
-            serial_id = base64.decodestring(serial_id+ '\n')
+            # we get all the blob oids on the filesystem related to the
+            # transaction we want to undo.
             for oid in self.fshelper.getOIDsForSerial(serial_id):
-                load_result = self.loadBefore(oid, serial_id) 
 
+                # we want to find the serial id of the previous revision
+                # of this blob object.
+                load_result = self.loadBefore(oid, serial_id)
+                
                 if load_result is None:
-                    continue
-
-                data, serial_before, serial_after = load_result
-                                                    
-                orig_fn = self.fshelper.getBlobFilename(oid, serial_before)
+                    # There was no previous revision of this blob
+                    # object.  The blob was created in the transaction
+                    # represented by serial_id.  We copy the blob data
+                    # to a new file that references the undo
+                    # transaction in case a user wishes to undo this
+                    # undo.
+                    orig_fn = self.fshelper.getBlobFilename(oid, serial_id)
+                    new_fn = self.fshelper.getBlobFilename(oid, undo_serial)
+                else:
+                    # A previous revision of this blob existed before the
+                    # transaction implied by "serial_id".  We copy the blob
+                    # data to a new file that references the undo transaction
+                    # in case a user wishes to undo this undo.
+                    data, serial_before, serial_after = load_result
+                    orig_fn = self.fshelper.getBlobFilename(oid, serial_before)
+                    new_fn = self.fshelper.getBlobFilename(oid, undo_serial)
                 orig = open(orig_fn, "r")
-                new_fn = self.fshelper.getBlobFilename(oid, serial)
                 new = open(new_fn, "wb")
                 utils.cp(orig, new)
                 orig.close()
                 new.close()
-                self.dirty_oids.append((oid, serial))
+                self.dirty_oids.append((oid, undo_serial))
+
         finally:
             self._lock_release()
-        return serial, keys
+        return undo_serial, keys
 

Modified: ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/connection.txt
===================================================================
--- ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/connection.txt	2006-02-28 19:47:13 UTC (rev 65604)
+++ ZODB/branches/blob-merge-branch/src/ZODB/Blobs/tests/connection.txt	2006-02-28 19:47:14 UTC (rev 65605)
@@ -19,6 +19,7 @@
 
     >>> from ZODB.Blobs.interfaces import IBlob
     >>> from ZODB.Blobs.Blob import Blob
+    >>> import transaction
     >>> blob = Blob()
     >>> data = blob.open("w")
     >>> data.write("I'm a happy Blob.")
@@ -40,9 +41,16 @@
     >>> connection = database.open()
     >>> root = connection.root()
     >>> root['myblob'] = blob
-    >>> import transaction
     >>> transaction.commit()
 
+We can also commit a transaction that seats a blob into place without
+calling the blob's open method (this currently fails):
+
+    >>> nothing = transaction.begin()
+    >>> anotherblob = Blob()
+    >>> root['anotherblob'] = anotherblob
+    >>> nothing = transaction.commit()
+
 Getting stuff out of there works similar:
 
     >>> connection2 = database.open()
@@ -65,7 +73,8 @@
         ...
     Unsupported: Storing Blobs in <ZODB.MappingStorage.MappingStorage instance at ...> is not supported.
 
-While we are testing this, we don't need the storage directory and databases anymore:
+While we are testing this, we don't need the storage directory and
+databases anymore:
 
     >>> import shutil
     >>> shutil.rmtree(blob_dir)



More information about the Zodb-checkins mailing list