[Zope-CVS] CVS: Products/AdaptableStorage/zodb - ASConnection.py:1.22 ASStorage.py:1.11 consts.py:1.6
Shane Hathaway
shane@zope.com
Sat, 1 Mar 2003 10:23:42 -0500
Update of /cvs-repository/Products/AdaptableStorage/zodb
In directory cvs.zope.org:/tmp/cvs-serv19690/zodb
Modified Files:
ASConnection.py ASStorage.py consts.py
Log Message:
Renamed the 'serial' concept to 'hash' because it's easier to explain in
documentation. Also expanded ILoadEvent so that gateways can return the
hash without loading the entire object.
=== Products/AdaptableStorage/zodb/ASConnection.py 1.21 => 1.22 ===
--- Products/AdaptableStorage/zodb/ASConnection.py:1.21 Fri Feb 21 12:16:50 2003
+++ Products/AdaptableStorage/zodb/ASConnection.py Sat Mar 1 10:23:42 2003
@@ -25,11 +25,12 @@
from Acquisition import aq_base
from ZODB import Persistent
from ZODB.POSException \
- import ConflictError, ReadConflictError, InvalidObjectReference
+ import ConflictError, ReadConflictError, InvalidObjectReference, \
+ StorageError
from ZODB.Connection import Connection
from zLOG import LOG, ERROR
-from consts import SERIAL0, DEBUG
+from consts import HASH0, DEBUG
from mapper_public import IKeyedObjectSystem, SerializationEvent, \
DeserializationEvent
@@ -249,7 +250,7 @@
if ext_refs:
for (ext_keychain, ext_ref) in ext_refs:
if (not ext_ref._p_serial
- or ext_ref._p_serial == SERIAL0):
+ or ext_ref._p_serial == HASH0):
ext_oid = oid_encoder.encode(ext_keychain)
if ext_ref._p_jar:
if ext_ref._p_jar != self:
@@ -433,6 +434,22 @@
def classFactory(self, module, name):
return self._db._classFactory(self, module, name)
+
+
+ def checkSerials(self):
+ """Verifies that all cached objects are in sync with the data.
+
+ This is useful for finding gateways that generate inconsistent
+ hashes.
+ """
+ for oid, ob in self._cache.items():
+ if ob._p_changed is not None:
+ p, serial = self._storage.load(oid, self._version)
+ if serial != ob._p_serial:
+ keychain = self._db._oid_encoder.decode(oid)
+ raise StorageError(
+ "Inconsistent hash for keychain %s" % repr(keychain))
+
def exportFile(self, oid, file=None):
raise NotImplementedError, 'ZEXP Export not implemented'
=== Products/AdaptableStorage/zodb/ASStorage.py 1.10 => 1.11 ===
--- Products/AdaptableStorage/zodb/ASStorage.py:1.10 Thu Jan 9 09:34:08 2003
+++ Products/AdaptableStorage/zodb/ASStorage.py Sat Mar 1 10:23:42 2003
@@ -25,7 +25,7 @@
import MapperEvent, LoadEvent, StoreEvent, \
ITPCConnection, NoStateFoundError
-from consts import SERIAL0, SERIAL1, DEBUG
+from consts import HASH0, HASH1, DEBUG
from OIDEncoder import OIDEncoder
from interfaces.public import IResourceAccess, IOIDEncoder
@@ -75,15 +75,18 @@
def getMapperResource(self):
return self._mapper_resource
- def hashSerial(self, serial):
- """Returns an 8-byte checksum.
+ def hash64(self, value):
+ """Returns an 8-byte hash value.
"""
- h = '%08x' % hash(serial)
+ h = '%08x' % hash(value)
+ if h == HASH0:
+ # Avoid the special zero hash.
+ h = HASH1
if DEBUG:
- print 'hash of %r is %r' % (serial, h)
+ print '64-bit hash of %r is %r' % (value, h)
return h
- def _load(self, root_mapper, keychain):
+ def _load(self, root_mapper, keychain, hash_only=0):
mapper = root_mapper
mapper_names = []
# Follow the keychain to find the right mapper.
@@ -97,8 +100,10 @@
mapper_names.append(sub_mapper_name)
mapper = mapper.getSubMapper(sub_mapper_name)
event = LoadEvent(mapper, keychain)
- full_state, serial = mapper.getGateway().load(event)
- return full_state, serial, classification, mapper_names
+ if hash_only:
+ event.hash_only = 1
+ full_state, hash_value = mapper.getGateway().load(event)
+ return full_state, hash_value, classification, mapper_names
def load(self, oid, version):
@@ -108,21 +113,21 @@
try:
keychain = self._oid_encoder.decode(oid)
root_mapper = self._mapper_resource.access(self)
- full_state, serial, classification, mapper_names = self._load(
+ full_state, hash_value, classification, mapper_names = self._load(
root_mapper, keychain)
file = StringIO()
p = Pickler(file)
p.dump((classification, mapper_names))
p.dump(full_state)
data = file.getvalue()
- h = self.hashSerial(serial)
+ h = self.hash64(hash_value)
if DEBUG:
print 'loaded', `oid`, `h`
return data, h
finally:
self._lock_release()
- def store(self, oid, serial_hash, data, version, transaction):
+ def store(self, oid, h64, data, version, transaction):
if transaction is not self._transaction:
raise POSException.StorageTransactionError(self, transaction)
@@ -135,32 +140,32 @@
keychain = self._oid_encoder.decode(oid)
# First detect conflicts.
- # The "serial" argument, if its value is not 0,
- # was previously generated by hashSerial().
+ # The "h64" argument, if its value is not 0,
+ # was previously generated by hash64().
if DEBUG:
- print 'storing', `oid`, `serial_hash`
- if serial_hash != SERIAL0:
- # Overwriting an old object. Use the serial to verify
+ print 'storing', `oid`, `h64`
+ if h64 != HASH0:
+ # Overwriting an old object. Use the hash to verify
# that the new data was derived from the old data.
- info = self._load(root_mapper, keychain)
- old_state, old_serial = info[:2]
- old_serial_hash = self.hashSerial(old_serial)
- if serial_hash != old_serial_hash:
+ info = self._load(root_mapper, keychain, 1)
+ old_state, old_hash = info[:2]
+ old_h64 = self.hash64(old_hash)
+ if h64 != old_h64:
raise POSException.ConflictError(
"Storing %s based on old data. %s != %s" % (
repr(keychain),
- repr(serial_hash), repr(old_serial_hash)))
+ repr(h64), repr(old_h64)))
else:
# A new object. Attempts to load should lead to
- # NoStateFoundError or a serial of None, otherwise
+ # NoStateFoundError or a hash of None, otherwise
# there's a conflict.
try:
- info = self._load(root_mapper, keychain)
+ info = self._load(root_mapper, keychain, 1)
except NoStateFoundError:
pass
else:
- old_serial = info[1]
- if old_serial is not None:
+ old_hash = info[1]
+ if old_hash is not None:
raise POSException.ConflictError(
"%s already exists" % repr(keychain))
@@ -176,16 +181,16 @@
cfr = mapper.getClassifier()
mapper = mapper.getSubMapper(mapper_name)
event = StoreEvent(mapper, keychain)
- new_serial = mapper.getGateway().store(event, state)
+ new_hash = mapper.getGateway().store(event, state)
if cfr is not None:
cfr.store(event, classification)
- new_hash = self.hashSerial(new_serial)
+ new_h64 = self.hash64(new_hash)
finally:
self._lock_release()
if DEBUG:
- print 'stored', `oid`, `serial_hash`, `new_hash`
- return new_hash
+ print 'stored', `oid`, `h64`, `new_h64`
+ return new_h64
def new_oid(self):
# Try to use the root keychain generator to make a keychain.
=== Products/AdaptableStorage/zodb/consts.py 1.5 => 1.6 ===
--- Products/AdaptableStorage/zodb/consts.py:1.5 Tue Jan 14 12:47:09 2003
+++ Products/AdaptableStorage/zodb/consts.py Sat Mar 1 10:23:42 2003
@@ -18,8 +18,11 @@
import os
-DEBUG = not not os.environ.get('ZODB_MAPPER_DEBUG')
+if os.environ.get('ZODB_MAPPER_DEBUG'):
+ DEBUG = 1
+else:
+ DEBUG = 0
-SERIAL0 = '\0' * 8
-SERIAL1 = '\0' * 7 + '\001'
ROOT_OID = '\0' * 8
+HASH0 = '\0' * 8
+HASH1 = '\0' * 7 + '\001'