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