[Zope-Checkins] CVS: StandaloneZODB/ZODB - FileStorage.py:1.77.4.1

Barry Warsaw barry@wooz.org
Wed, 23 Jan 2002 16:42:04 -0500


Update of /cvs-repository/StandaloneZODB/ZODB
In directory cvs.zope.org:/tmp/cvs-serv12297

Modified Files:
      Tag: Recovery
	FileStorage.py 
Log Message:
We're defining a new API method called recover() that looks a lot like
store() but which has some important differences:

- The `serial' argument to recover() names the serial number of the
  /current/ object revision, not the previous one.

- recover() skips various consistency checks that store() performs,
  including the checks for ConflictError and VersionLockError.  Thus
  it believes the data its given, which /must/ be known to be accurate
  (or you could end up corrupting your storage).  Also, it ought to be
  a bit faster since it does less work than store().

- recover() doesn't return anything.

Note that recover() must still be called within a two-phase commit.


=== StandaloneZODB/ZODB/FileStorage.py 1.77 => 1.77.4.1 ===
             self._lock_release()
 
+    def recover(self, oid, serial, data, version, transaction):
+        # A lot like store() but without all the consistency checks.  This
+        # should only be used when we /know/ the data is good, hence the
+        # method name.  While the signature looks like store() there are some
+        # differences:
+        #
+        # - serial is the serial number of /this/ revision, not of the
+        #   previous revision.  It is used instead of self._serial, which is
+        #   ignored.
+        #
+        # - Nothing is returned
+        if self._is_read_only:
+            raise POSException.ReadOnlyError()
+        if transaction is not self._transaction:
+            raise POSException.StorageTransactionError(self, transaction)
+
+        self._lock_acquire()
+        try:
+            # Position of the non-version data
+            pnv = None
+            # We need to get some information about previous revisions of the
+            # object.  Specifically, we need the position of the non-version
+            # data if this update is in a version.  We also need the position
+            # of the previous record in this version.
+            old = self._index_get(oid, 0)
+            if old:
+                self._file.seek(old)
+                # Read the previous revision record
+                h = self._file.read(42)
+                doid,oserial,sprev,stloc,vlen,splen = unpack(">8s8s8s8sH8s", h)
+                if doid != oid:
+                    raise CorruptedDataError, h
+            # Calculate the file position in the temporary file
+            here = self._pos + self._tfile.tell() + self._thl
+            # And update the temp file index
+            self._tindex[oid] = here
+            # Write the recovery data record
+            self._tfile.write(pack('>8s8s8s8sH8s',
+                              oid, serial, p64(old), p64(self._pos),
+                              len(version), p64(len(data))))
+            # We need to write some version information if this revision is
+            # happening in a version.
+            if version:
+                # If there's a previous revision in this version, write the
+                # position, otherwise write the position of the previous
+                # non-version revision.
+                if pnv:
+                    self._tfile.write(pnv)
+                else:
+                    self._tfile.write(p64(old))
+                # Link to the last record for this version
+                pv = self._tvindex.get(version, 0)
+                if not pv:
+                    self._vindex_get(version, 0)
+                self._tfile.write(p64(pv))
+                self._tvindex[version] = here
+                self._tfile.write(version)
+            # And finally, write the data
+            self._tfile.write(data)
+        finally:
+            self._lock_release()
+
     def supportsUndo(self):
         return 1