[Zope3-checkins] CVS: Zope3/src/zodb - serialize.py:1.7 interfaces.py:1.5 export.py:1.3 connection.py:1.4
Jeremy Hylton
jeremy@zope.com
Tue, 28 Jan 2003 11:42:28 -0500
Update of /cvs-repository/Zope3/src/zodb
In directory cvs.zope.org:/tmp/cvs-serv21250
Modified Files:
serialize.py interfaces.py export.py connection.py
Log Message:
A bit of simple refactoring.
Move TmpStore definition below Connection definition in
connection.py. The namegeddon merged two files in an unfortunate
order.
Rename Connection __getitem__() to get() and fixup all uses.
Define IAppConnection.
=== Zope3/src/zodb/serialize.py 1.6 => 1.7 ===
--- Zope3/src/zodb/serialize.py:1.6 Fri Jan 24 18:20:58 2003
+++ Zope3/src/zodb/serialize.py Tue Jan 28 11:42:25 2003
@@ -251,7 +251,7 @@
obj = self._cache.get(oid)
if obj is not None:
return obj
- return self._conn[oid]
+ return self._conn.get(oid)
class CopyReference:
def __init__(self, ref):
=== Zope3/src/zodb/interfaces.py 1.4 => 1.5 ===
--- Zope3/src/zodb/interfaces.py:1.4 Fri Jan 24 18:20:58 2003
+++ Zope3/src/zodb/interfaces.py Tue Jan 28 11:42:25 2003
@@ -231,13 +231,19 @@
o A reference to an object in a different database connection.
"""
+class IAppConnection(Interface):
+ """Interface exported by database connection to applications."""
+
+ def root():
+ """Return the root of the database."""
+
class IConnection(Interface):
"""Interface required of Connection by ZODB DB.
The Connection also implements IPersistentDataManager.
"""
- def reset(version):
+ def reset(version=""):
"""Reset connection to use specified version."""
def getVersion():
@@ -249,10 +255,6 @@
This marks the oid as invalid, but doesn't actually invalidate
it. The object data will be actually invalidated at certain
transaction boundaries.
-
- XXX The code suggests that invalidate() may sometimes be
- called with None as the oid, which would mean the "entire
- transaction" is invalidated.
"""
def close():
=== Zope3/src/zodb/export.py 1.2 => 1.3 ===
--- Zope3/src/zodb/export.py:1.2 Wed Dec 25 09:12:16 2002
+++ Zope3/src/zodb/export.py Tue Jan 28 11:42:25 2003
@@ -84,7 +84,7 @@
t.savepoint()
# Return the root imported object.
if L:
- return self[L[0]]
+ return self.get(L[0])
else:
return None
=== Zope3/src/zodb/connection.py 1.3 => 1.4 ===
--- Zope3/src/zodb/connection.py:1.3 Tue Jan 21 13:18:44 2003
+++ Zope3/src/zodb/connection.py Tue Jan 28 11:42:25 2003
@@ -11,139 +11,6 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-from zodb import interfaces
-from zodb.utils import p64, u64, Set, z64
-
-import tempfile
-
-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 new_oid(self):
- return self._db._storage.new_oid()
-
- 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 tpc_abort(self, transaction):
- if transaction is not self._transaction:
- return
- self._tindex.clear()
- self._transaction = None
- self._pos = self._tpos
-
- def tpc_begin(self, transaction):
- if self._transaction is transaction:
- return
- self._transaction = transaction
- self._tindex.clear() # Just to be sure!
- self._pos = self._tpos
-
- def tpc_vote(self, transaction):
- pass
-
- def tpc_finish(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:
-
- 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)
-
-
"""Database connection support
The Connection object serves as a data manager. ZODB is organized so
@@ -176,28 +43,27 @@
$Id$
"""
-from zodb import export
-
-from zodb.conflict import ResolvedSerial
-from zodb.interfaces import IConnection
-from zodb.interfaces import ConflictError, RollbackError
-from zodb.serialize import ConnectionObjectReader, \
- getClassMetadata, ObjectWriter
-from zodb.utils import u64, Set, z64
-
-from transaction import get_transaction
-from persistence.cache import Cache
-from persistence.interfaces import IPersistentDataManager
-
import cPickle
from cStringIO import StringIO
+import logging
import sys
+import tempfile
import threading
import time
from types import StringType, ClassType, TupleType
-import logging
-class Connection(export.ExportImport):
+from zodb import interfaces
+from zodb.conflict import ResolvedSerial
+from zodb.export import ExportImport
+from zodb.interfaces import IConnection, ConflictError
+from zodb.serialize import ConnectionObjectReader, ObjectWriter
+from zodb.utils import p64, u64, Set, z64
+
+from transaction import get_transaction
+from persistence.cache import Cache
+from persistence.interfaces import IPersistentDataManager
+
+class Connection(ExportImport):
"""Object managers for individual object space.
An object space is a version of collection of objects. In a
@@ -208,25 +74,19 @@
storage.
"""
- # instance variable that holds a TmpStore object used by sub-transactions
- _tmp = None
-
- # instance variable is None, or time.time() when opened
- _opened = None
-
- # Experimental. Other connections can register to be closed
- # when we close by putting something here.
-
__implements__ = IConnection, IPersistentDataManager
def __init__(self, db, version='', cache_size=400):
self._db = db
self._storage = db._storage
- self.new_oid = db._storage.new_oid
self._version = version
self._cache = cache = Cache(cache_size)
self._reader = ConnectionObjectReader(self, self._cache)
self._logger = logging.getLogger("zodb")
+ # a TmpStore object used by sub-transactions
+ self._tmp = None
+ # None, or time.time() when opened
+ self._opened = None
# _invalidated queues invalidate messages delivered from the DB
# _inv_lock prevents one thread from modifying the set while
@@ -241,8 +101,11 @@
self._modified = Set()
self._created = Set()
- def getVersion(self):
- return self._version
+ # new_oid is used by serialize
+ self.new_oid = self._storage.new_oid
+
+ def root(self):
+ return self.get(z64)
def modifiedInVersion(self, oid):
try:
@@ -250,10 +113,7 @@
except KeyError:
return self._version
- def root(self):
- return self.__getitem__(z64)
-
- def __getitem__(self, oid):
+ def get(self, oid):
# assume that a cache cannot store None as a valid object
object = self._cache.get(oid)
if object is not None:
@@ -276,8 +136,7 @@
return object
######################################################################
- # IPersistentDataManager
- # requires the next three methods:
+ # IPersistentDataManager requires the next three methods:
# setstate(), register(), mtime()
def setstate(self, object):
@@ -344,6 +203,13 @@
# required by the IPersistentDataManager interface, but unimplemented
return None
+ ######################################################################
+ # IConnection requires the next three methods:
+ # getVersion(), reset(), cacheGC(), invalidate(), close()
+
+ def getVersion(self):
+ return self._version
+
def reset(self, version=""):
if version != self._version:
# XXX I think it's necessary to clear the cache here, because
@@ -360,6 +226,20 @@
def cacheGC(self):
self._cache.incrgc()
+ def invalidate(self, oid):
+ """Invalidate a particular oid
+
+ This marks the oid as invalid, but doesn't actually invalidate
+ it. The object data will be actually invalidated at certain
+ transaction boundaries.
+ """
+ assert oid is not None
+ self._inv_lock.acquire()
+ try:
+ self._invalidated.add(oid)
+ finally:
+ self._inv_lock.release()
+
def close(self):
self._cache.incrgc()
self.applyCloseCallbacks()
@@ -396,20 +276,6 @@
def cacheMinimize(self, dt=0):
self._cache.minimize(dt)
- def invalidate(self, oid):
- """Invalidate a particular oid
-
- This marks the oid as invalid, but doesn't actually invalidate
- it. The object data will be actually invalidated at certain
- transaction boundaries.
- """
- assert oid is not None
- self._inv_lock.acquire()
- try:
- self._invalidated.add(oid)
- finally:
- self._inv_lock.release()
-
def _flush_invalidations(self):
self._inv_lock.acquire()
try:
@@ -425,7 +291,7 @@
self._logger.debug("commit object %s", u64(oid))
if oid is None or object._p_jar is not self:
- oid = self.new_oid()
+ oid = self._storage.new_oid()
object._p_jar = self
object._p_oid = oid
self._created.add(oid)
@@ -658,6 +524,133 @@
def rollback(self):
if not self._tmp_undo.current(self._conn._storage):
msg = "savepoint has already been committed"
- raise RollbackError(msg)
+ 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 new_oid(self):
+ return self._db._storage.new_oid()
+
+ 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 tpc_abort(self, transaction):
+ if transaction is not self._transaction:
+ return
+ self._tindex.clear()
+ self._transaction = None
+ self._pos = self._tpos
+
+ def tpc_begin(self, transaction):
+ if self._transaction is transaction:
+ return
+ self._transaction = transaction
+ self._tindex.clear() # Just to be sure!
+ self._pos = self._tpos
+
+ def tpc_vote(self, transaction):
+ pass
+
+ def tpc_finish(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:
+
+ 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)