[Zope3-checkins] CVS: ZODB4/src/zodb/storage - tmpstore.py:1.1.2.1
Barry Warsaw
barry@wooz.org
Mon, 10 Feb 2003 18:16:36 -0500
Update of /cvs-repository/ZODB4/src/zodb/storage
In directory cvs.zope.org:/tmp/cvs-serv6430/src/zodb/storage
Added Files:
Tag: opaque-pickles-branch
tmpstore.py
Log Message:
Move TmpStore and UndoInfo.
.store(): Unpack the data when it's a tuple.
=== Added File ZODB4/src/zodb/storage/tmpstore.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import tempfile
from zodb import interfaces
from zodb.interfaces import ZERO
from zodb.utils import p64, u64, Set
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)
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)
# 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))
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()