[Zodb-checkins] SVN: ZODB/trunk/src/ Renamed IStorageDB to IStorageWrapper and expanded it to provide
Jim Fulton
jim at zope.com
Thu May 13 15:06:48 EDT 2010
Log message for revision 112295:
Renamed IStorageDB to IStorageWrapper and expanded it to provide
methods for transforming and untransforming data records. This was
needed to make storage wrappers that transform data work with
conflict resolution.
Changed:
U ZODB/trunk/src/CHANGES.txt
U ZODB/trunk/src/ZEO/StorageServer.py
U ZODB/trunk/src/ZODB/ConflictResolution.py
U ZODB/trunk/src/ZODB/DB.py
U ZODB/trunk/src/ZODB/interfaces.py
U ZODB/trunk/src/ZODB/tests/ConflictResolution.py
-=-
Modified: ZODB/trunk/src/CHANGES.txt
===================================================================
--- ZODB/trunk/src/CHANGES.txt 2010-05-13 19:06:45 UTC (rev 112294)
+++ ZODB/trunk/src/CHANGES.txt 2010-05-13 19:06:47 UTC (rev 112295)
@@ -32,6 +32,11 @@
- You can now pass None (rather than a storage or file name) to get
a database with a mapping storage.
+- Renamed IStorageDB to IStorageWrapper and expanded it to provide
+ methods for transforming and untransforming data records. This was
+ needed to make storage wrappers that transform data work with
+ conflict resolution.
+
Bugs Fixed
----------
Modified: ZODB/trunk/src/ZEO/StorageServer.py
===================================================================
--- ZODB/trunk/src/ZEO/StorageServer.py 2010-05-13 19:06:45 UTC (rev 112294)
+++ ZODB/trunk/src/ZEO/StorageServer.py 2010-05-13 19:06:47 UTC (rev 112295)
@@ -778,6 +778,7 @@
def invalidateCache(self):
self.server._invalidateCache(self.storage_id)
+ transform_record_data = untransform_record_data = lambda self, data: data
class StorageServer:
Modified: ZODB/trunk/src/ZODB/ConflictResolution.py
===================================================================
--- ZODB/trunk/src/ZODB/ConflictResolution.py 2010-05-13 19:06:45 UTC (rev 112294)
+++ ZODB/trunk/src/ZODB/ConflictResolution.py 2010-05-13 19:06:47 UTC (rev 112295)
@@ -53,6 +53,7 @@
def state(self, oid, serial, prfactory, p=''):
p = p or self.loadSerial(oid, serial)
+ p = self._crs_wrapper.untransform_record_data(p)
file = StringIO(p)
unpickler = Unpickler(file)
unpickler.find_global = find_global
@@ -80,13 +81,13 @@
def __cmp__(other):
'''if other is equivalent reference, return 0; else raise ValueError.
-
+
Equivalent in this case means that oid and database_name are the same.
If either is a weak reference, we only support `is` equivalence, and
otherwise raise a ValueError even if the datbase_names and oids are
the same, rather than guess at the correct semantics.
-
+
It is impossible to sort reliably, since the actual persistent
class may have its own comparison, and we have no idea what it is.
We assert that it is reasonably safe to assume that an object is
@@ -135,7 +136,7 @@
def __cmp__(self, other):
if self is other or (
- isinstance(other, PersistentReference) and
+ isinstance(other, PersistentReference) and
self.oid == other.oid and
self.database_name == other.database_name and
not self.weak and
@@ -179,6 +180,7 @@
# class_tuple, old, committed, newstate = ('',''), 0, 0, 0
try:
prfactory = PersistentReferenceFactory()
+ newpickle = self._crs_wrapper.untransform_record_data(newpickle)
file = StringIO(newpickle)
unpickler = Unpickler(file)
unpickler.find_global = find_global
@@ -215,7 +217,7 @@
pickler.inst_persistent_id = persistent_id
pickler.dump(meta)
pickler.dump(resolved)
- return file.getvalue(1)
+ return self._crs_wrapper.transform_record_data(file.getvalue(1))
except (ConflictError, BadClassName):
return None
except:
@@ -227,7 +229,11 @@
logger.error("Unexpected error", exc_info=True)
return None
-class ConflictResolvingStorage:
+class ConflictResolvingStorage(object):
"Mix-in class that provides conflict resolution handling for storages"
tryToResolveConflict = tryToResolveConflict
+
+ def registerDB(self, wrapper):
+ self._crs_wrapper = wrapper
+ super(ConflictResolvingStorage, self).registerDB(wrapper)
Modified: ZODB/trunk/src/ZODB/DB.py
===================================================================
--- ZODB/trunk/src/ZODB/DB.py 2010-05-13 19:06:45 UTC (rev 112294)
+++ ZODB/trunk/src/ZODB/DB.py 2010-05-13 19:06:47 UTC (rev 112295)
@@ -705,6 +705,8 @@
"""
self._connectionMap(lambda c: c.invalidateCache())
+ transform_record_data = untransform_record_data = lambda self, data: data
+
def objectCount(self):
return len(self.storage)
Modified: ZODB/trunk/src/ZODB/interfaces.py
===================================================================
--- ZODB/trunk/src/ZODB/interfaces.py 2010-05-13 19:06:45 UTC (rev 112294)
+++ ZODB/trunk/src/ZODB/interfaces.py 2010-05-13 19:06:47 UTC (rev 112295)
@@ -287,24 +287,33 @@
"""
-class IStorageDB(Interface):
- """Database interface exposed to storages
+class IStorageWrapper(Interface):
+ """Storage wrapper interface
- This interface provides 2 facilities:
+ This interface provides 3 facilities:
- Out-of-band invalidation support
- A storage can notify it's database of object invalidations that
+ A storage can notify it's wrapper of object invalidations that
don't occur due to direct operations on the storage. Currently
this is only used by ZEO client storages to pass invalidation
messages sent from a server.
- - Record-reference extraction.
+ - Record-reference extraction
The references method can be used to extract referenced object
IDs from a database record. This can be used by storages to
- provide more advanced garbage collection.
+ provide more advanced garbage collection. A wrapper storage
+ that transforms data will provide a references method that
+ untransforms data passed to it and then pass the data to the
+ layer above it.
+ - Record transformation
+
+ A storage wrapper may transform data, for example for
+ compression or encryption. Methods are provided to transform or
+ untransform data.
+
This interface may be implemented by storage adapters or other
intermediaries. For example, a storage adapter that provides
encryption and/or compresssion will apply record transformations
@@ -337,7 +346,17 @@
be created and returned.
"""
+ def transform_record_data(data):
+ """Return transformed data
+ """
+ def untransform_record_data(data):
+ """Return untransformed data
+ """
+
+IStorageDB = IStorageWrapper # for backward compatibility
+
+
class IDatabase(IStorageDB):
"""ZODB DB.
"""
@@ -595,12 +614,18 @@
revisions.
"""
- def registerDB(db):
- """Register an IStorageDB.
+ def registerDB(wrapper):
+ """Register a storage wrapper IStorageWrapper.
+ The passed object is a wrapper object that provides an upcall
+ interface to support composition.
+
Note that, for historical reasons, an implementation may
require a second argument, however, if required, the None will
be passed as the second argument.
+
+ Also, for historical reasons, this is called registerDB rather
+ than register_wrapper.
"""
def sortKey():
Modified: ZODB/trunk/src/ZODB/tests/ConflictResolution.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/ConflictResolution.py 2010-05-13 19:06:45 UTC (rev 112294)
+++ ZODB/trunk/src/ZODB/tests/ConflictResolution.py 2010-05-13 19:06:47 UTC (rev 112295)
@@ -53,9 +53,15 @@
def _p_resolveConflict(self, oldState, savedState):
raise RuntimeError("Can't get here; not enough args")
+class StorageWrapper:
+
+ transform_record_data = untransform_record_data = lambda self, data: data
+
class ConflictResolvingStorage:
def checkResolve(self):
+ self._storage.registerDB(StorageWrapper())
+
obj = PCounter()
obj.inc()
@@ -76,6 +82,8 @@
self.assertEqual(inst._value, 5)
def checkUnresolvable(self):
+ self._storage.registerDB(StorageWrapper())
+
obj = PCounter2()
obj.inc()
@@ -97,11 +105,15 @@
self.fail("Expected ConflictError")
def checkZClassesArentResolved(self):
+ self._storage.registerDB(StorageWrapper())
+
from ZODB.ConflictResolution import find_global, BadClassName
dummy_class_tuple = ('*foobar', ())
self.assertRaises(BadClassName, find_global, '*foobar', ())
def checkBuggyResolve1(self):
+ self._storage.registerDB(StorageWrapper())
+
obj = PCounter3()
obj.inc()
@@ -120,6 +132,8 @@
oid, revid=revid1, data=zodb_pickle(obj))
def checkBuggyResolve2(self):
+ self._storage.registerDB(StorageWrapper())
+
obj = PCounter4()
obj.inc()
@@ -144,6 +158,8 @@
# TransactionalUndoStorage test suite. Except here, conflict
# resolution should allow us to undo the transaction anyway.
+ self._storage.registerDB(StorageWrapper())
+
obj = PCounter()
obj.inc()
oid = self._storage.new_oid()
@@ -166,6 +182,8 @@
# TransactionalUndoStorage test suite. Except here, conflict
# resolution should allow us to undo the transaction anyway.
+ self._storage.registerDB(StorageWrapper())
+
obj = PCounter2()
obj.inc()
oid = self._storage.new_oid()
More information about the Zodb-checkins
mailing list