[Zope-Checkins] CVS: Zope/lib/python/ZODB - FileStorage.py:1.98.2.3 ConflictResolution.py:1.13.6.2

Jeremy Hylton jeremy@zope.com
Wed, 11 Dec 2002 11:30:46 -0500


Update of /cvs-repository/Zope/lib/python/ZODB
In directory cvs.zope.org:/tmp/cvs-serv20407

Modified Files:
      Tag: Zope-2_6-branch
	FileStorage.py ConflictResolution.py 
Log Message:
Backport several changes from the ZODB3-3_1-branch.

Fix subtle bug in restore().
Provide much simpler version of getSerial().
Add bogus __len__ to get tests work with Python 2.1.
load_class() returns None on error.

Add some extra tests that cover bugs fixed.







=== Zope/lib/python/ZODB/FileStorage.py 1.98.2.2 => 1.98.2.3 ===
--- Zope/lib/python/ZODB/FileStorage.py:1.98.2.2	Fri Nov 15 12:45:03 2002
+++ Zope/lib/python/ZODB/FileStorage.py	Wed Dec 11 11:30:45 2002
@@ -568,31 +568,6 @@
         if plen != z64: return read(U64(plen)), version, nv
         return _loadBack(file, oid, read(8))[0], version, nv
 
-    def getSerial(self, oid):
-        self._lock_acquire()
-        try:
-            pos = self._index[oid]
-            self._file.seek(pos)
-            h = self._file.read(34)
-            _oid = h[:8]
-            if _oid != oid:
-                raise CorruptedDataError, h
-            vlen = unpack(">H", h[-2:])[0]
-            if vlen:
-                # If there is a version, find out its name and let
-                # _load() do all the work.  This is less efficient
-                # than possible, because _load() will load the pickle
-                # data.  Being more efficient is too complicated.
-                self._file.seek(24, 1) # skip plen, pnv, and pv
-                version = self._file.read(vlen)
-                pickledata, serial = self._load(oid, version,
-                                                self._index, self._file)
-                return serial
-            return h[8:16]
-        finally:
-            self._lock_release()
-
-
     def _load(self, oid, version, _index, file):
         try:
             pos = _index[oid]
@@ -808,7 +783,7 @@
         try:
             prev_pos = 0
             if prev_txn is not None:
-                prev_txn_pos = self._txn_find(prev_txn)
+                prev_txn_pos = self._txn_find(prev_txn, 0)
                 if prev_txn_pos:
                     prev_pos = self._data_find(prev_txn_pos, oid, data)
             old = self._index_get(oid, 0)
@@ -1090,6 +1065,13 @@
         else:
             return '', ''
 
+    def getSerial(self, oid):
+        self._lock_acquire()
+        try:
+            return self._getSerial(oid, self._index[oid])
+        finally:
+            self._lock_release()
+
     def _getSerial(self, oid, pos):
         self._file.seek(pos)
         h = self._file.read(16)
@@ -1223,12 +1205,12 @@
         # Find the right transaction to undo and call _txn_undo_write().
         tid = base64.decodestring(transaction_id + '\n')
         assert len(tid) == 8
-        tpos = self._txn_find(tid)
+        tpos = self._txn_find(tid, 1)
         tindex = self._txn_undo_write(tpos, tid)
         self._tindex.update(tindex)
         return tindex.keys()
 
-    def _txn_find(self, tid):
+    def _txn_find(self, tid, stop_at_pack):
         pos = self._pos
         # XXX Why 39?  Only because undoLog() uses it as a boundary.
         while pos > 39:
@@ -1239,9 +1221,10 @@
             _tid = h[:8]
             if _tid == tid:
                 return pos
-            status = h[16] # get the c in 8s8sc
-            if status == 'p' or _tid < self._packt:
-                break
+            if stop_at_pack:
+                # If the status indicates the record is packed, stop.
+                if h[16] == 'p' or _tid < self._packt:
+                    break
         raise UndoError("Invalid transaction id")
 
     def _txn_undo_write(self, tpos, tid):
@@ -2287,6 +2270,14 @@
         if start:
             self._skip_to_start(start)
         self._stop = stop
+
+    def __len__(self):
+        # Define a bogus __len__() to make the iterator work
+        # with code like builtin list() and tuple() in Python 2.1.
+        # There's a lot of C code that expects a sequence to have
+        # an __len__() but can cope with any sort of mistake in its
+        # implementation.  So just return 0.
+        return 0
 
     def close(self):
         file = self._file


=== Zope/lib/python/ZODB/ConflictResolution.py 1.13.6.1 => 1.13.6.2 ===
--- Zope/lib/python/ZODB/ConflictResolution.py:1.13.6.1	Tue Nov 12 16:13:58 2002
+++ Zope/lib/python/ZODB/ConflictResolution.py	Wed Dec 11 11:30:45 2002
@@ -95,6 +95,8 @@
             return 0
         newstate = unpickler.load()
         klass = load_class(class_tuple)
+        if klass is None:
+            return 0
         inst = klass.__basicnew__()
 
         try: