Skip to content

Commit

Permalink
Merge pull request #68 from zopefoundation/load-calls-loadBefore
Browse files Browse the repository at this point in the history
Load calls load before
  • Loading branch information
jimfulton committed Jun 17, 2016
2 parents 7d81f21 + addec00 commit 1e78342
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 29 deletions.
41 changes: 26 additions & 15 deletions src/ZODB/DemoStorage.py
Expand Up @@ -31,7 +31,9 @@
import ZODB.POSException
import ZODB.utils
import zope.interface

from .ConflictResolution import ConflictResolvingStorage, ResolvedSerial
from .utils import load_current, maxtid

@zope.interface.implementer(
ZODB.interfaces.IStorage,
Expand Down Expand Up @@ -167,11 +169,8 @@ def lastTransaction(self):
def __len__(self):
return len(self.changes)

def load(self, oid, version=''):
try:
return self.changes.load(oid, version)
except ZODB.POSException.POSKeyError:
return self.base.load(oid, version)
# still want load for old clients (e.g. zeo servers)
load = load_current

def loadBefore(self, oid, tid):
try:
Expand All @@ -190,12 +189,27 @@ def loadBefore(self, oid, tid):
pass
else:
if result and not result[-1]:
end_tid = None
t = self.changes.load(oid)
# The oid is current in the base. We need to find
# the end tid in the base by fining the first tid
# in the changes. Unfortunately, there isn't an
# api for this, so we have to walk back using
# loadBefore.

if tid == maxtid:
# Special case: we were looking for the
# current value. We won't find anything in
# changes, so we're done.
return result

end_tid = maxtid
t = self.changes.loadBefore(oid, end_tid)
while t:
end_tid = t[1]
t = self.changes.loadBefore(oid, end_tid)
result = result[:2] + (end_tid,)
result = result[:2] + (
end_tid if end_tid != maxtid else None,
)

return result

def loadBlob(self, oid, serial):
Expand Down Expand Up @@ -240,10 +254,10 @@ def new_oid(self):
oid = ZODB.utils.p64(self._next_oid )
if oid not in self._issued_oids:
try:
self.changes.load(oid, '')
load_current(self.changes, oid)
except ZODB.POSException.POSKeyError:
try:
self.base.load(oid, '')
load_current(self.base, oid)
except ZODB.POSException.POSKeyError:
self._next_oid += 1
self._issued_oids.add(oid)
Expand Down Expand Up @@ -288,12 +302,9 @@ def store(self, oid, serial, data, version, transaction):

# See if we already have changes for this oid
try:
old = self.changes.load(oid, '')[1]
old = load_current(self, oid)[1]
except ZODB.POSException.POSKeyError:
try:
old = self.base.load(oid, '')[1]
except ZODB.POSException.POSKeyError:
old = serial
old = serial

if old != serial:
rdata = self.tryToResolveConflict(oid, old, serial, data)
Expand Down
5 changes: 4 additions & 1 deletion src/ZODB/FileStorage/FileStorage.py
Expand Up @@ -70,6 +70,7 @@
from ZODB.utils import as_bytes
from ZODB.utils import as_text
from ZODB.utils import cp
from ZODB.utils import load_current
from ZODB.utils import mktemp
from ZODB.utils import p64
from ZODB.utils import u64
Expand Down Expand Up @@ -443,6 +444,8 @@ def _lookup_pos(self, oid):
except TypeError:
raise TypeError("invalid oid %r" % (oid,))

load = load_current # Keep load for now for old clients

def load(self, oid, version=''):
"""Return pickle data and serial number."""
assert not version
Expand Down Expand Up @@ -1314,7 +1317,7 @@ def record_iternext(self, next=None):
except ValueError: # "empty tree" error
next_oid = None

data, tid = self.load(oid, "")
data, tid = load_current(self, oid)

return oid, tid, data, next_oid

Expand Down
10 changes: 1 addition & 9 deletions src/ZODB/MappingStorage.py
Expand Up @@ -134,15 +134,7 @@ def lastTransaction(self):
def __len__(self):
return len(self._data)

# ZODB.interfaces.IStorage
@ZODB.utils.locked(opened)
def load(self, oid, version=''):
assert not version, "Versions are not supported"
tid_data = self._data.get(oid)
if tid_data:
tid = tid_data.maxKey()
return tid_data[tid], tid
raise ZODB.POSException.POSKeyError(oid)
load = ZODB.utils.load_current

# ZODB.interfaces.IStorage
@ZODB.utils.locked(opened)
Expand Down
5 changes: 2 additions & 3 deletions src/ZODB/tests/hexstorage.py
Expand Up @@ -13,6 +13,7 @@
##############################################################################
import ZODB.blob
import ZODB.interfaces
import ZODB.utils
import zope.interface
from binascii import hexlify, unhexlify

Expand Down Expand Up @@ -45,9 +46,7 @@ def __getattr__(self, name):
def __len__(self):
return len(self.base)

def load(self, oid, version=''):
data, serial = self.base.load(oid, version)
return unhexlify(data[2:]), serial
load = ZODB.utils.load_current

def loadBefore(self, oid, tid):
r = self.base.loadBefore(oid, tid)
Expand Down
24 changes: 23 additions & 1 deletion src/ZODB/utils.py
Expand Up @@ -28,7 +28,6 @@
from ZODB._compat import BytesIO
from ZODB._compat import ascii_bytes


__all__ = ['z64',
'p64',
'u64',
Expand Down Expand Up @@ -375,3 +374,26 @@ def notify_all(self):
else:

from threading import Condition, Lock, RLock


import ZODB.POSException

def load_current(storage, oid, version=''):
"""Load the most recent revision of an object by calling loadBefore
Starting in ZODB 5, it's no longer necessary for storages to
provide a load method.
This function is mainly intended to facilitate transitioning from
load to loadBefore. It's mainly useful for tests that are meant
to test storages, but do so by calling load on the storages.
This function will likely become unnecessary and be deprecated
some time in the future.
"""
assert not version
r = storage.loadBefore(oid, maxtid)
if r is None:
raise ZODB.POSException.POSKeyError(oid)
assert r[2] is None
return r[:2]

0 comments on commit 1e78342

Please sign in to comment.