Commit 6f9ac178 authored by Jim Fulton's avatar Jim Fulton

Added a storage tpc_transaction method to get a storage's current

transaction, if any.

Treat the undo and version APIs as optional.

Implement loadEx internally, so storages don't have to provide it.

Cache a storage's getTid during setup.
parent fd7ad4e0
......@@ -22,11 +22,12 @@ exported for invocation by the server.
import asyncore
import cPickle
import logging
import os
import sys
import threading
import time
import logging
import warnings
import transaction
......@@ -141,8 +142,8 @@ class ZEOStorage:
def __repr__(self):
tid = self.transaction and repr(self.transaction.id)
if self.storage:
stid = (self.storage._transaction and
repr(self.storage._transaction.id))
stid = (self.tpc_transaction() and
repr(self.tpc_transaction().id))
else:
stid = None
name = self.__class__.__name__
......@@ -152,33 +153,63 @@ class ZEOStorage:
log(msg, level=level, label=self.log_label, exc_info=exc_info)
def setup_delegation(self):
"""Delegate several methods to the storage"""
self.versionEmpty = self.storage.versionEmpty
self.versions = self.storage.versions
self.getSerial = self.storage.getSerial
self.history = self.storage.history
self.load = self.storage.load
self.loadSerial = self.storage.loadSerial
self.modifiedInVersion = self.storage.modifiedInVersion
record_iternext = getattr(self.storage, 'record_iternext', None)
"""Delegate several methods to the storage
"""
storage = self.storage
info = self.get_info()
if info['supportsVersions']:
self.versionEmpty = storage.versionEmpty
self.versions = storage.versions
self.modifiedInVersion = storage.modifiedInVersion
else:
self.versionEmpty = lambda version: True
self.versions = lambda max=None: ()
self.modifiedInVersion = lambda oid: ''
def commitVersion(*a, **k):
raise NotImplementedError
self.commitVersion = self.abortVersion = commitVersion
if not info['supportsUndo']:
self.undoLog = self.undoInfo = lambda *a,**k: ()
def undo(*a, **k):
raise NotImplementedError
self.undo = undo
self.getTid = storage.getTid
self.history = storage.history
self.load = storage.load
self.loadSerial = storage.loadSerial
record_iternext = getattr(storage, 'record_iternext', None)
if record_iternext is not None:
self.record_iternext = record_iternext
try:
fn = self.storage.getExtensionMethods
fn = storage.getExtensionMethods
except AttributeError:
# We must be running with a ZODB which
# predates adding getExtensionMethods to
# BaseStorage. Eventually this try/except
# can be removed
pass
pass # no extension methods
else:
d = fn()
self._extensions.update(d)
for name in d.keys():
for name in d:
assert not hasattr(self, name)
setattr(self, name, getattr(self.storage, name))
self.lastTransaction = self.storage.lastTransaction
setattr(self, name, getattr(storage, name))
self.lastTransaction = storage.lastTransaction
try:
self.tpc_transaction = storage.tpc_transaction
except AttributeError:
if hasattr(storage, '_transaction'):
log("Storage %r doesn't have a tpc_transaction method.\n"
"See ZEO.interfaces.IServeable."
"Falling back to using _transaction attribute, which\n."
"is icky.",
logging.ERROR)
self.tpc_transaction = lambda : storage._transaction
else:
raise
def _check_tid(self, tid, exc=None):
if self.read_only:
......@@ -240,11 +271,27 @@ class ZEOStorage:
self)
def get_info(self):
return {'length': len(self.storage),
'size': self.storage.getSize(),
'name': self.storage.getName(),
'supportsUndo': self.storage.supportsUndo(),
'supportsVersions': self.storage.supportsVersions(),
storage = self.storage
try:
supportsVersions = storage.supportsVersions
except AttributeError:
supportsVersions = False
else:
supportsVersions = supportsVersions()
try:
supportsUndo = storage.supportsUndo
except AttributeError:
supportsUndo = False
else:
supportsUndo = supportsUndo()
return {'length': len(storage),
'size': storage.getSize(),
'name': storage.getName(),
'supportsUndo': supportsUndo,
'supportsVersions': supportsVersions,
'extensionMethods': self.getExtensionMethods(),
'supports_record_iternext': hasattr(self, 'record_iternext'),
}
......@@ -259,7 +306,14 @@ class ZEOStorage:
def loadEx(self, oid, version):
self.stats.loads += 1
return self.storage.loadEx(oid, version)
if version:
oversion = self.storage.modifiedInVersion(oid)
if oversion == version:
data, serial = self.storage.load(oid, version)
return data, serial, version
data, serial = self.storage.load(oid, '')
return data, serial, ''
def loadBefore(self, oid, tid):
self.stats.loads += 1
......@@ -292,7 +346,7 @@ class ZEOStorage:
def verify(self, oid, version, tid):
try:
t = self.storage.getTid(oid)
t = self.getTid(oid)
except KeyError:
self.client.invalidateVerify((oid, ""))
else:
......@@ -309,7 +363,7 @@ class ZEOStorage:
self.verifying = 1
self.stats.verifying_clients += 1
try:
os = self.storage.getTid(oid)
os = self.getTid(oid)
except KeyError:
self.client.invalidateVerify((oid, ''))
# It's not clear what we should do now. The KeyError
......@@ -624,7 +678,7 @@ class ZEOStorage:
def _wait(self, thunk):
# Wait for the storage lock to be acquired.
self._thunk = thunk
if self.storage._transaction:
if self.tpc_transaction():
d = Delay()
self.storage._waiting.append((d, self))
self.log("Transaction blocked waiting for storage. "
......
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