[Zodb-checkins] CVS: ZODB4/src/zodb - connection.py:1.7.4.1

Barry Warsaw barry@wooz.org
Mon, 10 Feb 2003 17:54:11 -0500


Update of /cvs-repository/ZODB4/src/zodb
In directory cvs.zope.org:/tmp/cvs-serv32188/src/zodb

Modified Files:
      Tag: opaque-pickles-branch
	connection.py 
Log Message:
The start of opaque pickles (from the p.o.v. of the storages).  This
will eventually allow us to pass compressed pickles to the storage if
we want.

The approach basically changes store() so that the data argument is a
2-tuple of the pickle and the list of oids referenced in the pickle.
This is the first step in the changes, but currently, only Berkeley
storages natively store the refs included in the store() API call.

Changes here include:

- _commit_sub(): tmp.load() returns the data and serial number, but
  since we're turnng around and calling .store() on the storage, we
  need to extract the referent oids and pass this 2-tuple as the 3rd
  argument to .store().

- Use ZERO instead of z64

- Move classes TmpStore and UndoInfo to src/zodb/storage/tmpstore.py


=== ZODB4/src/zodb/connection.py 1.7 => 1.7.4.1 ===
--- ZODB4/src/zodb/connection.py:1.7	Wed Feb  5 18:28:34 2003
+++ ZODB4/src/zodb/connection.py	Mon Feb 10 17:54:09 2003
@@ -47,7 +47,6 @@
 from cStringIO import StringIO
 import logging
 import sys
-import tempfile
 import threading
 import time
 from types import StringType, ClassType, TupleType
@@ -55,9 +54,10 @@
 from zodb import interfaces
 from zodb.conflict import ResolvedSerial
 from zodb.export import ExportImport
-from zodb.interfaces import IConnection, ConflictError, IAppConnection
-from zodb.serialize import ConnectionObjectReader, ObjectWriter
-from zodb.utils import p64, u64, Set, z64
+from zodb.interfaces import IConnection, ConflictError, IAppConnection, ZERO
+from zodb.serialize import ConnectionObjectReader, ObjectWriter, findrefs
+from zodb.utils import p64, u64, Set
+from zodb.storage.tmpstore import TmpStore
 
 from transaction import get_transaction
 import transaction.interfaces
@@ -111,7 +111,7 @@
     # root() and sync()
     
     def root(self):
-        return self.get(z64)
+        return self.get(ZERO)
 
     def sync(self):
         get_transaction().abort()
@@ -141,7 +141,7 @@
         object._p_serial = serial
 
         self._cache[oid] = object
-        if oid == z64:
+        if oid == ZERO:
             # Keep a reference to the root so that the pickle cache
             # won't evict it.  XXX Not sure if this is necessary.  If
             # the cache is LRU, it should know best if the root is needed.
@@ -444,7 +444,9 @@
 
         for oid in tmp._index:
             data, serial = tmp.load(oid, tmp._bver)
-            s = self._storage.store(oid, serial, data, self._version, txn)
+            refs = findrefs(data)
+            s = self._storage.store(oid, serial, (data, refs),
+                                    self._version, txn)
             self._handle_serial(s, oid, change=False)
 
     def _abort_sub(self):
@@ -498,135 +500,3 @@
             raise interfaces.RollbackError(msg)
         self._tmp_undo.rollback()
         self._conn._cache.invalidateMany(self._conn._modified)
-
-class TmpStore:
-    """A storage to support savepoints."""
-
-    _bver = ''
-
-    def __init__(self, base_version):
-        self._transaction = None
-        if base_version:
-            self._bver = base_version
-        self._file = tempfile.TemporaryFile()
-        # _pos: current file position
-        # _tpos: file position at last commit point
-        self._pos = self._tpos = 0
-        # _index: map oid to pos of last committed version
-        self._index = {}
-        # _tindex: map oid to pos for new updates
-        self._tindex = {}
-        self._created = Set()
-        self._db = None
-
-    def close(self):
-        # 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)
-        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)
-
-    def newObjectId(self):
-        return self._db._storage.newObjectId()
-
-    def registerDB(self, db):
-        self._db = db
-        self._storage = db._storage
-
-    def store(self, oid, serial, data, version, transaction):
-        if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
-        self._file.seek(self._pos)
-        l = len(data)
-        if serial is None:
-            serial = z64
-        self._file.write(oid + serial + p64(l))
-        self._file.write(data)
-        self._tindex[oid] = self._pos
-        self._pos += l + 24
-        return serial
-
-    def tpcAbort(self, transaction):
-        if transaction is not self._transaction:
-            return
-        self._tindex.clear()
-        self._transaction = None
-        self._pos = self._tpos
-
-    def tpcBegin(self, transaction):
-        if self._transaction is transaction:
-            return
-        self._transaction = transaction
-        self._tindex.clear() # Just to be sure!
-        self._pos = self._tpos
-
-    def tpcVote(self, transaction):
-        pass
-
-    def tpcFinish(self, transaction, f=None):
-        if transaction is not self._transaction:
-            return
-        if f is not None:
-            f()
-        undo = UndoInfo(self, self._tpos, self._index.copy())
-        self._index.update(self._tindex)
-        self._tindex.clear()
-        self._tpos = self._pos
-        return undo
-
-    def undoLog(self, first, last, filter=None):
-        return ()
-
-    def versionEmpty(self, version):
-        # XXX what is this supposed to do?
-        if version == self._bver:
-            return len(self._index)
-
-    def rollback(self, pos, index):
-        if not (pos <= self._tpos <= self._pos):
-            msg = "transaction rolled back to early point"
-            raise interfaces.RollbackError(msg)
-        self._tpos = self._pos = pos
-        self._index = index
-        self._tindex.clear()
-
-class UndoInfo:
-    """A helper class for rollback.
-
-    The class stores the state necessary for rolling back to a
-    particular time.
-    """
-
-    def __init__(self, store, pos, index):
-        self._store = store
-        self._pos = pos
-        self._index = index
-
-    def current(self, cur_store):
-        """Return true if the UndoInfo is for cur_store."""
-        return self._store is cur_store
-
-    def rollback(self):
-        self._store.rollback(self._pos, self._index)