Commit 026c3746 authored by Jeremy Hylton's avatar Jeremy Hylton

Rename transactionalUndo() to undo().

The old undo was not used by Zope and shouldn't have been used by any
other client.  The newly named undo() is the preferred version of
undo.

XXX DemoStorage didn't implement transactionalUndo, so now it doesn't
implementation undo() at all.  We need to replace it with the demo
storage from ZODB4.

There are a few changes related to ZODB4 removal in this checkin.
parent ce3f3048
......@@ -994,7 +994,7 @@ class ClientStorage(object):
self._cache.store(oid, version, s, None, data)
self._tbuf.clear()
def transactionalUndo(self, trans_id, txn):
def undo(self, trans_id, txn):
"""Storage API: undo a transaction.
This is executed in a transactional context. It has no effect
......@@ -1004,7 +1004,7 @@ class ClientStorage(object):
a storage.
"""
self._check_trans(txn)
tid, oids = self._server.transactionalUndo(trans_id, id(txn))
tid, oids = self._server.undo(trans_id, id(txn))
for oid in oids:
self._tbuf.invalidate(oid, '')
return tid, oids
......
......@@ -268,11 +268,8 @@ class StorageServer:
def store(self, oid, serial, data, version, trans):
return self.rpc.call('store', oid, serial, data, version, trans)
def transactionalUndo(self, trans_id, trans):
return self.rpc.call('transactionalUndo', trans_id, trans)
def undo(self, trans_id):
return self.rpc.call('undo', trans_id)
def undo(self, trans_id, trans):
return self.rpc.call('undo', trans_id, trans)
def undoLog(self, first, last):
return self.rpc.call('undoLog', first, last)
......
......@@ -222,8 +222,6 @@ class ZEOStorage:
'name': self.storage.getName(),
'supportsUndo': self.storage.supportsUndo(),
'supportsVersions': self.storage.supportsVersions(),
'supportsTransactionalUndo':
self.storage.supportsTransactionalUndo(),
'extensionMethods': self.getExtensionMethods(),
}
......@@ -348,16 +346,6 @@ class ZEOStorage:
n = 1
return [self.storage.new_oid() for i in range(n)]
def undo(self, transaction_id):
if self.read_only:
raise ReadOnlyError()
oids = self.storage.undo(transaction_id)
if oids:
self.server.invalidate(self, self.storage_id, None,
map(lambda oid: (oid, ''), oids))
return oids
return ()
# undoLog and undoInfo are potentially slow methods
def undoInfo(self, first, last, spec):
......@@ -480,12 +468,12 @@ class ZEOStorage:
else:
return self._wait(lambda: self._commitVersion(src, dest))
def transactionalUndo(self, trans_id, id):
def undo(self, trans_id, id):
self._check_tid(id, exc=StorageTransactionError)
if self.locked:
return self._transactionalUndo(trans_id)
return self._undo(trans_id)
else:
return self._wait(lambda: self._transactionalUndo(trans_id))
return self._wait(lambda: self._undo(trans_id))
def _tpc_begin(self, txn, tid, status):
self.locked = 1
......@@ -557,8 +545,8 @@ class ZEOStorage:
self.invalidated.extend(inv)
return tid, oids
def _transactionalUndo(self, trans_id):
tid, oids = self.storage.transactionalUndo(trans_id, self.transaction)
def _undo(self, trans_id):
tid, oids = self.storage.undo(trans_id, self.transaction)
inv = [(oid, None) for oid in oids]
self.invalidated.extend(inv)
return tid, oids
......
......@@ -130,13 +130,6 @@ test_classes = [FileStorageConnectionTests,
MappingStorageConnectionTests,
MappingStorageTimeoutTests]
import BDBStorage
if BDBStorage.is_available:
test_classes += [BDBConnectionTests,
BDBReconnectionTests,
BDBInvqTests,
BDBTimeoutTests]
def test_suite():
suite = unittest.TestSuite()
for klass in test_classes:
......
......@@ -209,11 +209,6 @@ class MappingStorageTests(GenericTests):
test_classes = [FileStorageTests, MappingStorageTests]
import BDBStorage
if BDBStorage.is_available:
test_classes.append(BDBTests)
def test_suite():
suite = unittest.TestSuite()
for klass in test_classes:
......
......@@ -13,7 +13,7 @@
##############################################################################
"""Handy standard storage machinery
$Id: BaseStorage.py,v 1.40 2004/01/06 21:43:04 jeremy Exp $
$Id: BaseStorage.py,v 1.41 2004/02/18 01:13:01 jeremy Exp $
"""
import cPickle
import threading
......@@ -120,9 +120,6 @@ class BaseStorage(UndoLogCompatible):
def supportsUndo(self):
return 0
def supportsTransactionalUndo(self):
return 0
def supportsVersions(self):
return 0
......@@ -221,7 +218,7 @@ class BaseStorage(UndoLogCompatible):
"""
pass
def undo(self, transaction_id):
def undo(self, transaction_id, txn):
if self._is_read_only:
raise POSException.ReadOnlyError()
raise POSException.UndoError, 'non-undoable transaction'
......
......@@ -13,8 +13,8 @@
##############################################################################
"""Database objects
$Id: DB.py,v 1.59 2004/01/06 21:44:25 jeremy Exp $"""
__version__='$Revision: 1.59 $'[11:-2]
$Id: DB.py,v 1.60 2004/02/18 01:13:00 jeremy Exp $"""
__version__='$Revision: 1.60 $'[11:-2]
import cPickle, cStringIO, sys, POSException, UndoLogCompatible
from Connection import Connection
......@@ -574,82 +574,70 @@ class DB(UndoLogCompatible.UndoLogCompatible, object):
def cacheStatistics(self): return () # :(
def undo(self, id, transaction=None):
storage=self._storage
try: supportsTransactionalUndo = storage.supportsTransactionalUndo
except AttributeError:
supportsTransactionalUndo=0
else:
supportsTransactionalUndo=supportsTransactionalUndo()
if supportsTransactionalUndo:
# new style undo
if transaction is None:
transaction = get_transaction()
transaction.register(TransactionalUndo(self, id))
else:
# fall back to old undo
d = {}
for oid in storage.undo(id):
d[oid] = 1
# XXX I think we need to remove old undo to use mvcc
self.invalidate(None, d)
if transaction is None:
transaction = get_transaction()
transaction.register(TransactionalUndo(self, id))
def versionEmpty(self, version):
return self._storage.versionEmpty(version)
class CommitVersion:
"""An object that will see to version commit
class ResourceManager(object):
"""Transaction participation for a version or undo resource."""
in cooperation with a transaction manager.
"""
def __init__(self, db, version, dest=''):
self._db=db
s=db._storage
self._version=version
self._dest=dest
self.tpc_abort=s.tpc_abort
self.tpc_begin=s.tpc_begin
self.tpc_vote=s.tpc_vote
self.tpc_finish=s.tpc_finish
self._sortKey=s.sortKey
def __init__(self, db):
self._db = db
# Delegate the actual 2PC methods to the storage
self.tpc_begin = self._db._storage.tpc_begin
self.tpc_vote = self._db._storage.tpc_vote
self.tpc_finish = self._db._storage.tpc_finish
self.tpc_abort = self._db._storage.tpc_abort
def sortKey(self):
return "%s:%s" % (self._sortKey(), id(self))
return "%s:%s" % (self._db._storage.sortKey(), id(self))
# The object registers itself with the txn manager, so the ob
# argument to the methods below is self.
def abort(self, ob, t):
pass
def commit(self, ob, t):
pass
def abort(self, reallyme, t): pass
class CommitVersion(ResourceManager):
def commit(self, reallyme, t):
def __init__(self, db, version, dest=''):
super(CommitVersion, self).__init__(db)
self._version = version
self._dest = dest
def commit(self, ob, t):
dest=self._dest
tid, oids = self._db._storage.commitVersion(self._version, dest, t)
tid, oids = self._db._storage.commitVersion(self._version, self._dest,
t)
oids = list2dict(oids)
self._db.invalidate(tid, oids, version=dest)
if dest:
self._db.invalidate(tid, oids, version=self._dest)
if self._dest:
# the code above just invalidated the dest version.
# now we need to invalidate the source!
self._db.invalidate(tid, oids, version=self._version)
class AbortVersion(CommitVersion):
"""An object that will see to version abortion
in cooperation with a transaction manager.
"""
class AbortVersion(ResourceManager):
def commit(self, reallyme, t):
version = self._version
tid, oids = self._db._storage.abortVersion(version, t)
self._db.invalidate(tid, list2dict(oids), version=version)
def __init__(self, db, version):
super(AbortVersion, self).__init__(db)
self._version = version
def commit(self, ob, t):
tid, oids = self._db._storage.abortVersion(self._version, t)
self._db.invalidate(tid, list2dict(oids), version=self._version)
class TransactionalUndo(ResourceManager):
class TransactionalUndo(CommitVersion):
"""An object that will see to transactional undo
in cooperation with a transaction manager.
"""
# I (Jim) am lazy. I'm reusing __init__ and abort and reusing the
# version attr for the transaction id. There's such a strong
# similarity of rhythm that I think it's justified.
def __init__(self, db, tid):
super(TransactionalUndo, self).__init__(db)
self._tid = tid
def commit(self, reallyme, t):
tid, oids = self._db._storage.transactionalUndo(self._version, t)
def commit(self, ob, t):
tid, oids = self._db._storage.undo(self._tid, t)
self._db.invalidate(tid, list2dict(oids))
......@@ -79,7 +79,7 @@ method::
and call it to monitor the storage.
"""
__version__='$Revision: 1.23 $'[11:-2]
__version__='$Revision: 1.24 $'[11:-2]
import base64, time, string
from ZODB import POSException, BaseStorage, utils
......@@ -277,9 +277,6 @@ class DemoStorage(BaseStorage.BaseStorage):
finally: self._lock_release()
return self._tid
def supportsUndo(self):
return 1
def supportsVersions(self):
return 1
......@@ -321,57 +318,6 @@ class DemoStorage(BaseStorage.BaseStorage):
v[oid] = r
self._ltid = self._tid
def undo(self, transaction_id):
self._lock_acquire()
try:
transaction_id=base64.decodestring(transaction_id+'\n')
try: t=self._data[transaction_id][4]
except KeyError:
raise UndoError, 'Invalid undo transaction id'
index=self._index
vindex=self._vindex
vindex_get=self._vindex.get
for r in t:
if index[r[0]] is not r:
raise POSException.UndoError, 'non-undoable transaction'
oids=[]
for r in t:
oid, pre, vdata, p, tid = r
if pre:
index[oid] = pre
oids.append(oid)
# Delete old version data
if vdata:
version=vdata[0]
v=vindex.get(version, None)
if v: del v[oid]
# Add new version data (from pre):
oid, prepre, vdata, p, tid = pre
if vdata:
version=vdata[0]
v=vindex.get(version, None)
if v is None: v=vindex[version]={}
v[oid]=pre
else:
del index[oid]
if vdata:
version=vdata[0]
v=vindex.get(version, None)
if v: del v[oid]
if not v: del vindex[version]
del self._data[transaction_id]
return oids
finally: self._lock_release()
def undoLog(self, first, last, filter=None):
if last < 0:
last = first - last + 1
......
......@@ -13,7 +13,7 @@
##############################################################################
"""Storage implementation using a log written to a single file.
$Revision: 1.3 $
$Revision: 1.4 $
"""
import base64
......@@ -1076,7 +1076,7 @@ class FileStorage(BaseStorage.BaseStorage,
finally:
self._lock_release()
def transactionalUndo(self, transaction_id, transaction):
def undo(self, transaction_id, transaction):
"""Undo a transaction, given by transaction_id.
Do so by writing new data that reverses the action taken by
......
......@@ -162,7 +162,7 @@ class ConflictResolvingTransUndoStorage:
tid = info[1]['id']
t = Transaction()
self._storage.tpc_begin(t)
self._storage.transactionalUndo(tid, t)
self._storage.undo(tid, t)
self._storage.tpc_finish(t)
def checkUndoUnresolvable(self):
......@@ -183,6 +183,6 @@ class ConflictResolvingTransUndoStorage:
tid = info[1]['id']
t = Transaction()
self._storage.tpc_begin(t)
self.assertRaises(UndoError, self._storage.transactionalUndo,
self.assertRaises(UndoError, self._storage.undo,
tid, t)
self._storage.tpc_abort(t)
......@@ -100,7 +100,7 @@ class IteratorStorage(IteratorCompare):
# Undo the creation of the object, rendering it a zombie
t = Transaction()
self._storage.tpc_begin(t)
oids = self._storage.transactionalUndo(tid, t)
oids = self._storage.undo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
# Now attempt to iterator over the storage
......
......@@ -60,5 +60,5 @@ class ReadOnlyStorage:
'\000' * 8, None, '', '', t)
if self._storage.supportsTransactionalUndo():
self.assertRaises(ReadOnlyError, self._storage.transactionalUndo,
self.assertRaises(ReadOnlyError, self._storage.undo,
'\000' * 8, t)
......@@ -209,7 +209,7 @@ class StorageTestBase(unittest.TestCase):
t = Transaction()
t.note(note or "undo")
self._storage.tpc_begin(t)
tid, oids = self._storage.transactionalUndo(tid, t)
tid, oids = self._storage.undo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
if expected_oids is not None:
......
......@@ -41,7 +41,7 @@ substantially simplified.
New and/or unspecified methods:
tpc_vote(): handled like tpc_abort
transactionalUndo(): handled like undo() (which is how?)
undo(): how's that handled?
Methods that have nothing to do with committing/non-committing:
load(), loadSerial(), getName(), getSize(), __len__(), history(),
......
......@@ -11,9 +11,9 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Check transactionalUndo().
"""Check undo().
Any storage that supports transactionalUndo() must pass these tests.
Any storage that supports undo() must pass these tests.
"""
import time
......@@ -102,7 +102,7 @@ class TransactionalUndoStorage:
t = Transaction()
t.note(note)
self._storage.tpc_begin(t)
oids = self._storage.transactionalUndo(tid, t)
oids = self._storage.undo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
return oids
......@@ -150,7 +150,7 @@ class TransactionalUndoStorage:
t = Transaction()
t.note('undo1')
self._storage.tpc_begin(t)
self._storage.transactionalUndo(tid, t)
self._storage.undo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
# Check that calling getSerial on an uncreated object raises a KeyError
......@@ -279,8 +279,8 @@ class TransactionalUndoStorage:
tid1 = info[1]['id']
t = Transaction()
self._storage.tpc_begin(t)
tid, oids = self._storage.transactionalUndo(tid, t)
tid, oids1 = self._storage.transactionalUndo(tid1, t)
tid, oids = self._storage.undo(tid, t)
tid, oids1 = self._storage.undo(tid1, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
# We get the finalization stuff called an extra time:
......@@ -353,7 +353,7 @@ class TransactionalUndoStorage:
tid = info[1]['id']
t = Transaction()
self._storage.tpc_begin(t)
tid, oids = self._storage.transactionalUndo(tid, t)
tid, oids = self._storage.undo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
eq(len(oids), 1)
......@@ -379,7 +379,7 @@ class TransactionalUndoStorage:
t = Transaction()
self._storage.tpc_begin(t)
self.assertRaises(POSException.UndoError,
self._storage.transactionalUndo,
self._storage.undo,
tid, t)
self._storage.tpc_abort(t)
# Now have more fun: object1 and object2 are in the same transaction,
......@@ -418,7 +418,7 @@ class TransactionalUndoStorage:
t = Transaction()
self._storage.tpc_begin(t)
self.assertRaises(POSException.UndoError,
self._storage.transactionalUndo,
self._storage.undo,
tid, t)
self._storage.tpc_abort(t)
self._iterate()
......@@ -446,7 +446,7 @@ class TransactionalUndoStorage:
# And now attempt to undo the last transaction
t = Transaction()
self._storage.tpc_begin(t)
tid, oids = self._storage.transactionalUndo(tid, t)
tid, oids = self._storage.undo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
eq(len(oids), 1)
......@@ -652,7 +652,7 @@ class TransactionalUndoStorage:
base = i * OBJECTS + i
for j in range(OBJECTS):
tid = info[base + j]['id']
s.transactionalUndo(tid, t)
s.undo(tid, t)
s.tpc_vote(t)
s.tpc_finish(t)
......
......@@ -11,8 +11,8 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
# Check interactions between transactionalUndo() and versions. Any storage
# that supports both transactionalUndo() and versions must pass these tests.
# Check interactions between undo() and versions. Any storage that
# supports both undo() and versions must pass these tests.
import time
......
......@@ -43,6 +43,17 @@ class DemoStorageTests(StorageTestBase.StorageTestBase,
# XXX Need to implement a real loadBefore for DemoStorage?
pass
# the next three pack tests depend on undo
def checkPackVersionReachable(self):
pass
def checkPackVersions(self):
pass
def checkPackVersionsInPast(self):
pass
def test_suite():
suite = unittest.makeSuite(DemoStorageTests, 'check')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment