[Zodb-checkins] CVS: Zope3/src/zodb - connection.py:1.7.4.7

Jeremy Hylton jeremy@zope.com
Thu, 13 Mar 2003 11:05:45 -0500


Update of /cvs-repository/Zope3/src/zodb
In directory cvs.zope.org:/tmp/cvs-serv7707

Modified Files:
      Tag: opaque-pickles-branch
	connection.py 
Log Message:
Eliminate use of findrefs by making TmpStore store refs explicitly.


=== Zope3/src/zodb/connection.py 1.7.4.6 => 1.7.4.7 ===
--- Zope3/src/zodb/connection.py:1.7.4.6	Wed Mar 12 18:22:06 2003
+++ Zope3/src/zodb/connection.py	Thu Mar 13 11:05:42 2003
@@ -38,6 +38,7 @@
 """
 
 import logging
+import struct
 import tempfile
 import threading
 from types import StringType, ClassType, TupleType
@@ -48,6 +49,7 @@
 from zodb.interfaces import *
 from zodb.serialize import ConnectionObjectReader, ObjectWriter, findrefs
 from zodb.storage.interfaces import IStorage
+from zodb.storage.base import splitrefs
 from zodb.utils import p64, u64, Set
 
 from transaction import get_transaction
@@ -353,10 +355,9 @@
 
     def savepoint(self, txn):
         if self._tmp is None:
-            tmp = TmpStore(self._version)
+            tmp = TmpStore(self._db, self._storage, self._version)
             self._tmp = self._storage
             self._storage = tmp
-            tmp.registerDB(self._db)
         self._modified = Set()
         self._created = Set()
         self._storage.tpcBegin(txn)
@@ -492,11 +493,11 @@
         self._created |= tmp._created
 
         for oid in tmp._index:
-            data, serial = tmp.load(oid, tmp._bver)
-            refs = findrefs(data)
+            data, refs, serial = tmp.loadrefs(oid, tmp._bver)
             s = self._storage.store(oid, serial, (data, refs),
                                     self._version, txn)
             self._handle_serial(s, oid, change=False)
+        tmp.close()
 
     def _abort_sub(self):
         # Abort work done in subtransactions.
@@ -508,6 +509,7 @@
 
         self._cache.invalidateMany(tmp._index)
         self._invalidate_created(tmp._created)
+        tmp.close()
 
 class Rollback:
     """Rollback changes associated with savepoint"""
@@ -557,7 +559,16 @@
 
     _bver = ''
 
-    def __init__(self, base_version):
+    # The header format is oid, serial, nrefs, len(data).  Following
+    # the header are the refs and the data, where the size of refs is
+    # nrefs * 8.
+    
+    _fmt = ">8s8sQQ"
+    _header_size = 32
+
+    def __init__(self, db, storage, base_version):
+        self._db = db
+        self._storage = storage
         self._transaction = None
         if base_version:
             self._bver = base_version
@@ -576,52 +587,40 @@
         # XXX Is this necessary?
         self._file.close()
 
-    def getName(self):
-        return self._db.getName()
-
-    def getSize(self):
-        return self._pos
-
     def load(self, oid, version):
         pos = self._index.get(oid, None)
         if pos is None:
             return self._storage.load(oid, self._bver)
+        data, refs, serial = self.loadrefs(oid, version)
+        return data, serial
+
+    def loadrefs(self, oid, version):
+        # A version of load the returns data, refs, and serial.
+        pos = self._index.get(oid)
+        # We only call loadrefs() for objects in the TmpStore.
+        assert pos is not None
         self._file.seek(pos)
-        h = self._file.read(24)
-        if h[:8] != oid:
-            raise interfaces.StorageSystemError('Bad temporary storage')
-        size = u64(h[16:])
-        serial = h[8:16]
-        return self._file.read(size), serial
-
-    # XXX clarify difference between self._storage & self._db._storage
-
-    def modifiedInVersion(self, oid):
-        if self._index.has_key(oid):
-            return self._bver
-        return self._db._storage.modifiedInVersion(oid)
+        buf = self._file.read(self._header_size)
+        oid, serial, nrefs, size = struct.unpack(">8s8sQQ", buf)
+        refs = self._file.read(nrefs * 8)
+        data = self._file.read(size)
+        return data, splitrefs(refs), serial
 
     def newObjectId(self):
-        return self._db._storage.newObjectId()
-
-    def registerDB(self, db):
-        self._db = db
-        self._storage = db._storage
+        return self._storage.newObjectId()
 
-    def store(self, oid, serial, data, version, transaction):
+    def store(self, oid, serial, (data, refs), version, transaction):
         if transaction is not self._transaction:
             raise interfaces.StorageTransactionError(self, transaction)
-        # XXX Store this natively and get rid of the conditional split
-        if isinstance(data, tuple):
-            data, refs = data
         self._file.seek(self._pos)
-        l = len(data)
         if serial is None:
             serial = ZERO
-        self._file.write(oid + serial + p64(l))
+        buf = struct.pack(">8s8sQQ", oid, serial, len(refs), len(data))
+        self._file.write(buf)
+        self._file.write("".join(refs))
         self._file.write(data)
         self._tindex[oid] = self._pos
-        self._pos += l + 24
+        self._pos += len(refs) * 8 + len(data) + self._header_size
         return serial
 
     def tpcAbort(self, transaction):