[Zope-Checkins] CVS: Zope/lib/python/ZODB - ConflictResolution.py:1.8.16.2

Jeremy Hylton jeremy@zope.com
Wed, 14 Aug 2002 18:45:18 -0400


Update of /cvs-repository/Zope/lib/python/ZODB
In directory cvs.zope.org:/tmp/cvs-serv31990/lib/python/ZODB

Modified Files:
      Tag: Zope-2_5-branch
	ConflictResolution.py 
Log Message:
Backport bug fixes in ConflictResolution from the trunk.

The main idea in the bug fix is to recover more gracefully when
something goes wrong trying to load classes for conflict resolution.



=== Zope/lib/python/ZODB/ConflictResolution.py 1.8.16.1 => 1.8.16.2 ===
--- Zope/lib/python/ZODB/ConflictResolution.py:1.8.16.1	Wed Feb 13 11:37:03 2002
+++ Zope/lib/python/ZODB/ConflictResolution.py	Wed Aug 14 18:45:18 2002
@@ -13,20 +13,19 @@
 ##############################################################################
 from cStringIO import StringIO
 from cPickle import Unpickler, Pickler
-import sys
 
 from ZODB.POSException import ConflictError
+import zLOG
 
-#import traceback
+bad_classes = {}
 
-bad_classes={}
 def bad_class(class_tuple):
     if bad_classes.has_key(class_tuple) or class_tuple[0][0] == '*':
         # if we've seen the class before or if it's a ZClass, we know that
         # we can't resolve the conflict
         return 1
 
-ResolvedSerial='rs'
+ResolvedSerial = 'rs'
 
 def _classFactory(location, name,
                   _silly=('__doc__',), _globals={}):
@@ -34,12 +33,12 @@
                    name)
 
 def state(self, oid, serial, prfactory, p=''):
-    p=p or self.loadSerial(oid, serial)
-    file=StringIO(p)
-    unpickler=Unpickler(file)
-    unpickler.persistent_load=prfactory
-    class_tuple=unpickler.load()
-    state=unpickler.load()
+    p = p or self.loadSerial(oid, serial)
+    file = StringIO(p)
+    unpickler = Unpickler(file)
+    unpickler.persistent_load = prfactory.persistent_load
+    class_tuple = unpickler.load()
+    state = unpickler.load()
     return state
 
 
@@ -53,66 +52,66 @@
 
 class PersistentReferenceFactory:
 
-    data=None
-    
-    def __call__(self, oid,
-                 getattr=getattr, None=None):
+    data = None
 
-        data=self.data
-        if not data: data=self.data={}
+    def persistent_load(self, oid):
+        if self.data is None:
+            self.data = {}
 
-        r=data.get(oid, None)
+        r = self.data.get(oid, None)
         if r is None:
-            r=PersistentReference()
-            r.data=oid
-            data[oid]=r
+            r = PersistentReference()
+            r.data = oid
+            self.data[oid] = r
 
         return r
 
-def persistent_id(object,
-                  PersistentReference=PersistentReference,
-                  getattr=getattr
-                  ):
+def persistent_id(object):
     if getattr(object, '__class__', 0) is not PersistentReference:
         return None
     return object.data
 
+def load_class(class_tuple):
+    try:
+        klass = _classFactory(class_tuple[0], class_tuple[1])
+    except (ImportError, AttributeError):
+        zLOG.LOG("Conflict Resolution", zLOG.BLATHER,
+                 "Unable to load class", error=sys.exc_info())
+        bad_class[class_tuple] = 1
+        return None
+    return klass
+
 def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
                          committedData=''):
-    #class_tuple, old, committed, newstate = ('',''), 0, 0, 0
+    # class_tuple, old, committed, newstate = ('',''), 0, 0, 0
     try:
-        file=StringIO(newpickle)
-        unpickler=Unpickler(file)
-        prfactory=PersistentReferenceFactory()
-        unpickler.persistent_load=prfactory
-        class_tuple=unpickler.load()[0]
+        prfactory = PersistentReferenceFactory()
+        file = StringIO(newpickle)
+        unpickler = Unpickler(file)
+        unpickler.persistent_load = prfactory.persistent_load
+        class_tuple = unpickler.load()[0]
         if bad_class(class_tuple):
-            #sys.stderr.write(' b%s ' % class_tuple[1]); sys.stderr.flush()
             return 0
-
-        newstate=unpickler.load()
-        klass=_classFactory(class_tuple[0], class_tuple[1])
-        inst=klass.__basicnew__()
+        newstate = unpickler.load()
+        klass = load_class(class_tuple)
+        inst = klass.__basicnew__()
 
         try:
-            resolve=inst._p_resolveConflict
+            resolve = inst._p_resolveConflict
         except AttributeError:
-            bad_classes[class_tuple]=1
-            #traceback.print_exc()
-            #sys.stderr.write(' b%s ' % class_tuple[1]); sys.stderr.flush()
+            bad_classes[class_tuple] = 1
             return 0
 
-        old=state(self, oid, oldSerial, prfactory)
-        committed=state(self, oid, committedSerial, prfactory, committedData)
+        old = state(self, oid, oldSerial, prfactory)
+        committed = state(self, oid, committedSerial, prfactory, committedData)
 
-        resolved=resolve(old, committed, newstate)
+        resolved = resolve(old, committed, newstate)
 
-        file=StringIO()
-        pickler=Pickler(file,1)
-        pickler.persistent_id=persistent_id
+        file = StringIO()
+        pickler = Pickler(file,1)
+        pickler.persistent_id = persistent_id
         pickler.dump(class_tuple)
         pickler.dump(resolved)
-        #sys.stderr.write(' r%s ' % class_tuple[1]); sys.stderr.flush()
         return file.getvalue(1)
     except ConflictError:
         return 0
@@ -120,4 +119,4 @@
 class ConflictResolvingStorage:
     "Mix-in class that provides conflict resolution handling for storages"
 
-    tryToResolveConflict=tryToResolveConflict
+    tryToResolveConflict = tryToResolveConflict