[Zope-Checkins] CVS: Zope2 - ConflictResolution.py:1.1.2.2

Jim Fulton jim@digiciool.com
Wed, 14 Mar 2001 11:46:45 -0500 (EST)


Update of /cvs-repository/Zope2/lib/python/ZODB
In directory korak:/tmp/cvs-serv8196

Modified Files:
      Tag: Catalog-BTrees-Integration
	ConflictResolution.py 
Log Message:
Added support for objects with persistent references.  This was to
allow conflict resolution of buckets containing persistent objects and
to handle buckets with next-buckets.

Note that the persistent references don't have meaningful values other
than addresses and aren't of the normal object type. This means that
conflict-resolution logic can't rely on the any semantics of refered
objects other than identity-based comparison.



--- Updated File ConflictResolution.py in package Zope2 --
--- ConflictResolution.py	2001/03/01 00:36:37	1.1.2.1
+++ ConflictResolution.py	2001/03/14 16:46:45	1.1.2.2
@@ -85,6 +85,8 @@
 from cStringIO import StringIO
 from cPickle import Unpickler, Pickler
 
+#import sys, traceback
+
 bad_classes={}
 bad_class=bad_classes.has_key
 
@@ -95,23 +97,62 @@
     return getattr(__import__(location, _globals, _globals, _silly),
                    name)
 
-def state(self, oid, serial):
+def state(self, oid, serial, prfactory):
     p=self.loadSerial(oid, serial)
     file=StringIO(p)
     unpickler=Unpickler(file)
+    unpickler.persistent_load=prfactory
     class_tuple=unpickler.load()
     state=unpickler.load()
     return state
 
+
+class PersistentReference:
+
+    def __repr__(self):
+        return "PR(%s %s)" % (id(self), self.data)
+
+class PersistentReferenceFactory:
+
+    data=None
+    
+    def __call__(self, oid,
+                 getattr=getattr, None=None):
+
+        data=self.data
+        if not data: data=self.data={}
+
+        r=data.get(oid, None)
+        if r is None:
+            r=PersistentReference()
+            r.data=oid
+            data[oid]=r
+
+        return r
+
+def persistent_id(object,
+                  PersistentReference=PersistentReference,
+                  getattr=getattr
+                  ):
+    if getattr(object, '__class__', 0) is not PersistentReference:
+        return None
+    return object.data
+
 class ConflictResolvingStorage:
     "Mix-in class that provides conflict resolution handling for storages"
 
     def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle):
+        #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]
-            if bad_class(class_tuple): return 0
+            if bad_class(class_tuple):
+                #sys.stderr.write(' b%s ' % class_tuple[1]); sys.stderr.flush()
+                return 0
+            
             try:
                 newstate=unpickler.load()
                 klass=_classFactory(class_tuple[0], class_tuple[1])
@@ -120,15 +161,34 @@
                 resolve=inst._p_resolveConflict
             except:
                 bad_classes[class_tuple]=1
+                #traceback.print_exc()
+                #sys.stderr.write(' b%s ' % class_tuple[1]); sys.stderr.flush()
                 return 0
             
-            old=state(self, oid, oldSerial)
-            committed=state(self, oid, committedSerial)
+            old=state(self, oid, oldSerial, prfactory)
+            committed=state(self, oid, committedSerial, prfactory)
 
             resolved=resolve(old, committed, newstate)
+                
             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: return 0
+        except Exception, v:
+            #print '='*70
+            #print v, v.args
+            #print '='*70
+            #print old
+            #print '='*70
+            #print committed
+            #print '='*70
+            #print newstate
+            #print '='*70
+            
+            #traceback.print_exc()
+            #sys.stderr.write(' c%s ' % class_tuple[1]); sys.stderr.flush()
+            return 0
+