Update of /cvs-repository/Packages/ZODB In directory cvs.zope.org:/tmp/cvs-serv20696/ZODB
Modified Files: Tag: Zope-2_7-branch BaseStorage.py DemoStorage.py Log Message: DemoStorage: Added implementations for registerDB() and new_oid(). As Tres discovered the hard way, wrapping a ZEO client storage as a DemoStorage base storage yields insane behavior otherwise. BaseStorage.new_oid(): Rewrite to eliminate recursion, and hence also the need for the undocumented and irregular `last=` argument. Other: removed the `last=` argument to new_oid() every place that felt compelled to spread that insanity ;-). Seriously, it served no purpose at all elsewhere, and looks like people just cut 'n pasted in fear. === Packages/ZODB/BaseStorage.py 1.34.4.3 => 1.34.4.4 === --- Packages/ZODB/BaseStorage.py:1.34.4.3 Mon Feb 28 16:20:41 2005 +++ Packages/ZODB/BaseStorage.py Fri Apr 22 15:36:07 2005 @@ -17,6 +17,7 @@ """ import cPickle import time +from struct import pack as _structpack, unpack as _structunpack import ThreadLock import zLOG @@ -48,10 +49,15 @@ t=time.time() t=self._ts=apply(TimeStamp,(time.gmtime(t)[:5]+(t%60,))) self._serial=`t` + + # ._oid is the highest oid in use (0 is always in use -- it's + # a reserved oid for the root object). Our new_oid() method + # increments it by 1, and returns the result. It's really a + # 64-bit integer stored as an 8-byte big-endian string. if base is None: - self._oid='\0\0\0\0\0\0\0\0' + self._oid = '\0\0\0\0\0\0\0\0' else: - self._oid=base._oid + self._oid = base._oid def abortVersion(self, src, transaction): if transaction is not self._transaction: @@ -87,24 +93,22 @@ def modifiedInVersion(self, oid): return '' - def new_oid(self, last=None): - # 'last' is only for internal use, not part of the public API + def new_oid(self): if self._is_read_only: raise POSException.ReadOnlyError() - if last is None: - self._lock_acquire() - try: - last=self._oid - d=ord(last[-1]) - if d < 255: last=last[:-1]+chr(d+1) - else: last=self.new_oid(last[:-1]) - self._oid=last - return last - finally: self._lock_release() - else: - d=ord(last[-1]) - if d < 255: return last[:-1]+chr(d+1)+'\0'*(8-len(last)) - else: return self.new_oid(last[:-1]) + self._lock_acquire() + try: + last = self._oid + d = ord(last[-1]) + if d < 255: # fast path for the usual case + last = last[:-1] + chr(d+1) + else: # there's a carry out of the last byte + last_as_long, = _structunpack(">Q", last) + last = _structpack(">Q", last_as_long + 1) + self._oid = last + return last + finally: + self._lock_release() # Update the maximum oid in use, under protection of a lock. The # maximum-in-use attribute is changed only if possible_new_max_oid is === Packages/ZODB/DemoStorage.py 1.18.10.1 => 1.18.10.2 === --- Packages/ZODB/DemoStorage.py:1.18.10.1 Mon Jul 21 12:37:18 2003 +++ Packages/ZODB/DemoStorage.py Fri Apr 22 15:36:07 2005 @@ -20,7 +20,7 @@ - Provide a volatile storage that is useful for giving demonstrations. -The demo strorage can have a "base" storage that is used in a +The demo storage can have a "base" storage that is used in a read-only fashion. The base storage must not not to contain version data. @@ -82,15 +82,16 @@ __version__='$Revision$'[11:-2] import base64, time, string -from ZODB import POSException, BaseStorage, utils +from ZODB import POSException, utils +from ZODB.BaseStorage import BaseStorage from TimeStamp import TimeStamp from cPickle import loads from BTrees import OOBTree -class DemoStorage(BaseStorage.BaseStorage): +class DemoStorage(BaseStorage): def __init__(self, name='Demo Storage', base=None, quota=None): - BaseStorage.BaseStorage.__init__(self, name, base) + BaseStorage.__init__(self, name, base) # We use a BTree because the items are sorted! self._data=OOBTree.OOBTree() @@ -104,6 +105,23 @@ raise POSException.StorageError, ( "Demo base storage has version data") + # While we officially don't support wrapping a non-read-only base + # storage, it has proved useful for test suites to wrap a ClientStorage + # in DemoStorage. The least we can do to help support that case is + # to arrange for invalidations to get delivered to the base storage. + def registerDB(self, db, limit): + if self._base is not None: # delegate + self._base.registerDB(db, limit) + + # When DemoStorage needs to create a new oid, and there is a base + # storage, it must use that storage's new_oid() method. Else + # DemoStorage may end up assigning "new" oids that are already in use + # by the base storage, leading to a variety of "impossible" problems. + def new_oid(self): + if self._base is None: + return BaseStorage.new_oid(self) + else: + return self._base.new_oid() def __len__(self): base=self._base _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins