Is _p_resolveConflict method of Inceraser executed at all?
I wonder if traceback you see in console is from the
code you added:

or it is always shown when there is a conflict error.

   def _p_resolveConflict(self, old, state1, state2):
   print "called the _p_resolveConflict of the Increaser object",self
       number = max(old,state1,state2)
   except Exception,msg:
       import traceback
       return max(old, state1, state2)


Yes, The method was not called. However, the traceback was indeed printed by
the print_exc, since there were no tracebacks before I added this line. In
fact, as Gabriel Genellina said :

That might provoke a ConflictError, forcing a
transaction abort and the request to be re-tried (up to three times,
silently, then it goes logged).

as well as  Pascal Peregrina:

In general, retry is called when a ZODB Conflict Error has happened.
If I remember well, Zope will silently retry 3 times, and then actually
return an error page showing the Conflict Error.

as the documentation says :

"If an unhandled exception is raised during the publishing process, Zope
aborts the transaction. As detailed in Chapter 4. Zope handles
ConflictErrors by re-trying the request up to three times. This is done with
the zpublisher_exception_hook."

Thus, I don't think that the traceback is always shown when there's a
conflict error.

So I decided to look into the file suggested by Maciej Wisniowski :

You may take a look at lib/python/ZODB/
method: tryToResolveConflict. There is a call to _p_resolveConflict.

and edited it like this :

def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
   # class_tuple, old, committed, newstate = ('',''), 0, 0, 0
   print "in, called the tryToResolveConflict method
with arguments :"
       prfactory = PersistentReferenceFactory()
       file = StringIO(newpickle)
       unpickler = Unpickler(file)
       unpickler.find_global = find_global
       unpickler.persistent_load = prfactory.persistent_load
       meta = unpickler.load()
       if isinstance(meta, tuple):
           klass = meta[0]
           newargs = meta[1] or ()
           if isinstance(klass, tuple):
               klass = find_global(*klass)
           klass = meta
           newargs = ()

       if klass in _unresolvable:
       print "klass",klass.__repr__,"is unresolvable"
           return None

       newstate = unpickler.load()
       inst = klass.__new__(klass, *newargs)

           resolve = inst._p_resolveConflict
       except AttributeError:
       print inst.__repr__,"has no _p_resolveConflict method"
           _unresolvable[klass] = 1
           return None

       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
   print "everything's ok"
       return file.getvalue(1)
   except (ConflictError, BadClassName):
   print "ConflictError during conflict resolution in tryToResolveConflict,"
   import traceback
   import sys
   traceback.print_exc(file = sys.stdout)
       return None
   print "Exception raised in in tryToResolveConflict,"
   import traceback
   import sys
       # If anything else went wrong, catch it here and avoid passing an
       # arbitrary exception back to the client.  The error here will mask
       # the original ConflictError.  A client can recover from a
       # ConflictError, but not necessarily from other errors.  But log
       # the error so that any problems can be fixed.
       logger.error("Unexpected error", exc_info=True)
       return None


Now let's see what's going on in the console :

in, called the tryToResolveConflict method with
arguments :
self <tempstorage.TemporaryStorage.TemporaryStorage instance at 0x43fb6aac>
oid '\x00\x00\x00\x00\x00\x00\x00\t' committedSerial
'\x03k#\x93\x1d\xff\xf5\x11' oldSerial '\x03k#\x91^t\xf1D' newpickle '(
committedData ''
ConflictError during conflict resolution in tryToResolveConflict,
Traceback (most recent call last):
 File "/opt/aef/Zope-2.9.0/lib/python/ZODB/", line
126, in tryToResolveConflict
   old = state(self, oid, oldSerial, prfactory)
 File "/opt/aef/Zope-2.9.0/lib/python/ZODB/", line 53,
in state
   p = p or self.loadSerial(oid, serial)
 File "/opt/aef/Zope-2.9.0//lib/python/tempstorage/",
line 148, in loadSerial
   raise POSException.ConflictError(oid=oid)
ConflictError: database conflict error (oid 0x09)

<comment> the exception is raised up to the publish function, since it has
not been catched, and I added up a code to print traceback in the publish
function so here it is </comment>

exception raised in the publish module, in function publish
Traceback (most recent call last):
 File "/opt/aef/Zope-2.9.0/lib/python/ZPublisher/", line 119, in
 File "/opt/aef/Zope-2.9.0//lib/python/Zope2/App/", line 234, in
 File "/opt/aef/Zope-2.9.0//lib/python/transaction/", line 96,
in commit
   return self.get().commit(sub, deprecation_wng=False)
 File "/opt/aef/Zope-2.9.0//lib/python/transaction/", line
380, in commit
   self._saveCommitishError() # This raises!
 File "/opt/aef/Zope-2.9.0//lib/python/transaction/", line
378, in commit
 File "/opt/aef/Zope-2.9.0//lib/python/transaction/", line
433, in _commitResources
 File "/opt/aef/Zope-2.9.0//lib/python/ZODB/", line 484, in
 File "/opt/aef/Zope-2.9.0//lib/python/ZODB/", line 526, in
   self._store_objects(ObjectWriter(obj), transaction)
 File "/opt/aef/Zope-2.9.0//lib/python/ZODB/", line 554, in
   s =, serial, p, self._version, transaction)
 File "/opt/aef/Zope-2.9.0//lib/python/tempstorage/",
line 200, in store
ConflictError: database conflict error (oid 0x09, class
Products.Transience.Transience.Increaser, serial this txn started with
0x036b23915e74f144 2007-01-25 13:05:22.138314, serial currently committed
0x036b23931dfff511 2007-01-25 13:07:07.031211)

The exception is raised, as the traceback says, in File
line 148, in loadSerial
   raise POSException.ConflictError(oid=oid)

Is it normal that the oid, as an argument to tryToResloveConflict, was
"\x00\x00\x00\x00\x00\x00\x00\t" then became 0x09 when the exception was
raised ?

here's the loadSerial code :

   def loadSerial(self, oid, serial, marker=[]):
       """ this is only useful to make conflict resolution work.  It
       does not actually implement all the semantics that a revisioning
       storage needs! """
           data = self._conflict_cache.get((oid, serial), marker)
           if data is marker:
               # XXX Need 2 serialnos to pass them to ConflictError--
               # the old and the new
               raise POSException.ConflictError(oid=oid)
               return data[0] # data here is actually (data, t)


2007/1/25, Martijn Pieters <[EMAIL PROTECTED]>:

On 1/24/07, Maciej Wisniowski <[EMAIL PROTECTED]> wrote:
> Another question, do you use ZEO? I know there were some issues
> with _p_resolveConflict and ZEO (at last in Zope 2.8.x). Result
> was that with ZEO setup _p_resolveConflict was not called at all.
> There is solution for this but I don't know if this is your case
> especially that you are dealing with TemporaryStorage which is
> typically managed by ZEO Client...

If ZEO cannot reach your product (import it), it cannot run any
conflict resolution. Make sure that the ZEO server setup has access to
those Products that do conflict resolution.

Martijn Pieters

Zope maillist  -
**   No cross posts or HTML encoding!  **
(Related lists - )

Reply via email to