Commit c3e0be24 authored by Jim Fulton's avatar Jim Fulton

Removed some extraneous doumentation.

Removed undo and version support.

Removed close, cleanup, and pack. Storages should implement these and
providing stubs encourages broken implementations.

history should return a sequence.

Renamed getSerial to getTid.

Added a ZEO-required storage tpc_transaction method to get a storage's
current transaction, if any.

Reduced loadBefore to an empty method.  This produces the same output
as before. :)  There was an elaborate implementation that only worked
with an implementation that didn't need it. :)

Removed getExtensionMethods, which is not part of the storage API.

Created a copy *function* from copyTransactionsFrom. Now
copyTransactionsFrom just uses that.  Now this logic, such as it is,
can be reused without inheritence.
parent 0562e446
......@@ -54,20 +54,6 @@ class BaseStorage(UndoLogCompatible):
If it stores multiple revisions, it should implement
loadSerial()
loadBefore()
iterator()
If the subclass wants to implement undo, it should implement the
multiple revision methods and:
undo()
undoInfo()
undoLog()
If the subclass wants to implement versions, it must implement:
abortVersion()
commitVersion()
modifiedInVersion()
versionEmpty()
versions()
Each storage will have two locks that are accessed via lock
acquire and release methods bound to the instance. (Yuck.)
......@@ -112,22 +98,6 @@ class BaseStorage(UndoLogCompatible):
else:
self._oid = oid
def abortVersion(self, src, transaction):
if transaction is not self._transaction:
raise POSException.StorageTransactionError(self, transaction)
return self._tid, []
def commitVersion(self, src, dest, transaction):
if transaction is not self._transaction:
raise POSException.StorageTransactionError(self, transaction)
return self._tid, []
def close(self):
pass
def cleanup(self):
pass
def sortKey(self):
"""Return a string that can be used to sort storage instances.
......@@ -144,10 +114,7 @@ class BaseStorage(UndoLogCompatible):
return len(self)*300 # WAG!
def history(self, oid, version, length=1, filter=None):
pass
def modifiedInVersion(self, oid):
return ''
return ()
def new_oid(self):
if self._is_read_only:
......@@ -183,12 +150,6 @@ class BaseStorage(UndoLogCompatible):
def isReadOnly(self):
return self._is_read_only
def supportsUndo(self):
return 0
def supportsVersions(self):
return 0
def tpc_abort(self, transaction):
self._lock_acquire()
try:
......@@ -243,6 +204,9 @@ class BaseStorage(UndoLogCompatible):
finally:
self._lock_release()
def tpc_transaction(self):
return self._transaction
def _begin(self, tid, u, d, e):
"""Subclasses should redefine this to supply transaction start actions.
"""
......@@ -292,28 +256,17 @@ class BaseStorage(UndoLogCompatible):
"""
pass
def undo(self, transaction_id, txn):
if self._is_read_only:
raise POSException.ReadOnlyError()
raise POSException.UndoError('non-undoable transaction')
def undoLog(self, first, last, filter=None):
return ()
def versionEmpty(self, version):
return 1
def versions(self, max=None):
return ()
def pack(self, t, referencesf):
if self._is_read_only:
raise POSException.ReadOnlyError()
def getSerial(self, oid):
def getTid(self, oid):
self._lock_acquire()
try:
v = self.modifiedInVersion(oid)
v = ''
try:
supportsVersions = self.supportsVersions
except AttributeError:
pass
else:
if supportsVersions():
v = self.modifiedInVersion(oid)
pickledata, serial = self.load(oid, v)
return serial
finally:
......@@ -325,57 +278,7 @@ class BaseStorage(UndoLogCompatible):
def loadBefore(self, oid, tid):
"""Return most recent revision of oid before tid committed."""
# Unsure: Is it okay for loadBefore() to return current data?
# There doesn't seem to be a good reason to forbid it, even
# though the typical use of this method will never find
# current data. But maybe we should call it loadByTid()?
n = 2
start_time = None
end_time = None
while start_time is None:
# The history() approach is a hack, because the dict
# returned by history() doesn't contain a tid. It
# contains a serialno, which is often the same, but isn't
# required to be. We'll pretend it is for now.
# A second problem is that history() doesn't say anything
# about whether the transaction status. If it falls before
# the pack time, we can't honor the MVCC request.
# Note: history() returns the most recent record first.
# TODO: The filter argument to history() only appears to be
# supported by FileStorage. Perhaps it shouldn't be used.
L = self.history(oid, "", n, lambda d: not d["version"])
if not L:
return
for d in L:
if d["serial"] < tid:
start_time = d["serial"]
break
else:
end_time = d["serial"]
if len(L) < n:
break
n *= 2
if start_time is None:
return None
data = self.loadSerial(oid, start_time)
return data, start_time, end_time
def getExtensionMethods(self):
"""getExtensionMethods
This returns a dictionary whose keys are names of extra methods
provided by this storage. Storage proxies (such as ZEO) should
call this method to determine the extra methods that they need
to proxy in addition to the standard storage methods.
Dictionary values should be None; this will be a handy place
for extra marshalling information, should we need it
"""
return {}
return None
def copyTransactionsFrom(self, other, verbose=0):
"""Copy transactions from another storage.
......@@ -383,61 +286,69 @@ class BaseStorage(UndoLogCompatible):
This is typically used for converting data from one storage to
another. `other` must have an .iterator() method.
"""
_ts=None
ok=1
preindex={};
preget=preindex.get # waaaa
# restore() is a new storage API method which has an identical
# signature to store() except that it does not return anything.
# Semantically, restore() is also identical to store() except that it
# doesn't do the ConflictError or VersionLockError consistency
# checks. The reason to use restore() over store() in this method is
# that store() cannot be used to copy transactions spanning a version
# commit or abort, or over transactional undos.
#
# We'll use restore() if it's available, otherwise we'll fall back to
# using store(). However, if we use store, then
# copyTransactionsFrom() may fail with VersionLockError or
# ConflictError.
restoring = hasattr(self, 'restore')
fiter = other.iterator()
for transaction in fiter:
tid=transaction.tid
if _ts is None:
_ts=TimeStamp(tid)
copy(other, self, verbose)
def copy(source, dest, verbose=0):
"""Copy transactions from a source to a destination storage
This is typically used for converting data from one storage to
another. `source` must have an .iterator() method.
"""
_ts = None
ok = 1
preindex = {};
preget = preindex.get
# restore() is a new storage API method which has an identical
# signature to store() except that it does not return anything.
# Semantically, restore() is also identical to store() except that it
# doesn't do the ConflictError or VersionLockError consistency
# checks. The reason to use restore() over store() in this method is
# that store() cannot be used to copy transactions spanning a version
# commit or abort, or over transactional undos.
#
# We'll use restore() if it's available, otherwise we'll fall back to
# using store(). However, if we use store, then
# copyTransactionsFrom() may fail with VersionLockError or
# ConflictError.
restoring = hasattr(dest, 'restore')
fiter = source.iterator()
for transaction in fiter:
tid = transaction.tid
if _ts is None:
_ts = TimeStamp(tid)
else:
t = TimeStamp(tid)
if t <= _ts:
if ok: print ('Time stamps out of order %s, %s' % (_ts, t))
ok = 0
_ts = t.laterThan(_ts)
tid = `_ts`
else:
t=TimeStamp(tid)
if t <= _ts:
if ok: print ('Time stamps out of order %s, %s' % (_ts, t))
ok=0
_ts=t.laterThan(_ts)
tid=`_ts`
else:
_ts = t
if not ok:
print ('Time stamps back in order %s' % (t))
ok=1
_ts = t
if not ok:
print ('Time stamps back in order %s' % (t))
ok = 1
if verbose:
print _ts
dest.tpc_begin(transaction, tid, transaction.status)
for r in transaction:
oid = r.oid
if verbose:
print _ts
self.tpc_begin(transaction, tid, transaction.status)
for r in transaction:
oid=r.oid
if verbose:
print oid_repr(oid), r.version, len(r.data)
if restoring:
self.restore(oid, r.tid, r.data, r.version,
r.data_txn, transaction)
else:
pre=preget(oid, None)
s=self.store(oid, pre, r.data, r.version, transaction)
preindex[oid]=s
self.tpc_vote(transaction)
self.tpc_finish(transaction)
fiter.close()
print oid_repr(oid), r.version, len(r.data)
if restoring:
dest.restore(oid, r.tid, r.data, r.version,
r.data_txn, transaction)
else:
pre = preget(oid, None)
s = dest.store(oid, pre, r.data, r.version, transaction)
preindex[oid] = s
dest.tpc_vote(transaction)
dest.tpc_finish(transaction)
fiter.close()
class TransactionRecord:
"""Abstract base class for iterator protocol"""
......
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