[Zope] Zope pretends to receive and send XMLRPC data, but strace sees nothing ! (fwd)

yacine chaouche yacinechaouche at gmail.com
Thu Jan 25 09:48:53 EST 2007


>Is _p_resolveConflict method of Inceraser executed at all?
>I wonder if traceback you see in console is from the
>code you added:
>traceback.print_exc(file=stdin)
>
>or it is always shown when there is a conflict error.

<code>
    def _p_resolveConflict(self, old, state1, state2):
    print "called the _p_resolveConflict of the Increaser object",self
    try:
        number = max(old,state1,state2)
    except Exception,msg:
        import traceback
        traceback.print_exc(file=sys.stdin)
        return max(old, state1, state2)

</code>

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
http://www.zope.org/Documentation/Books/ZDG/current/ObjectPublishing.stx :

"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/ConflictResolution.py
>method: tryToResolveConflict. There is a call to _p_resolveConflict.

and edited it like this :

<code>
def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
                         committedData=''):
    # class_tuple, old, committed, newstate = ('',''), 0, 0, 0
    print "in ConflictResolution.py, called the tryToResolveConflict method
with arguments :"
    print
"self",self,"oid",oid.__repr__(),"committedSerial",committedSerial.__repr__(),"oldSerial",oldSerial.__repr__(),"newpickle",newpickle.__repr__(),"committedData",committedData.__repr__()
    try:
        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)
        else:
            klass = meta
            newargs = ()

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

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

        try:
            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,
committedData)

        resolved = resolve(old, committed, newstate)

        file = StringIO()
        pickler = Pickler(file,1)
        pickler.persistent_id = persistent_id
        pickler.dump(meta)
        pickler.dump(resolved)
    print "everything's ok"
        return file.getvalue(1)
    except (ConflictError, BadClassName):
    print "ConflictError during conflict resolution in tryToResolveConflict,
ConflictResolution.py"
    import traceback
    import sys
    traceback.print_exc(file = sys.stdout)
        return None
    except:
    print "Exception raised in in tryToResolveConflict,
ConflictResolution.py"
    import traceback
    import sys
    traceback.print_exc(file=sys.stdout)
        # 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

</code>

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

<console>
in ConflictResolution.py, 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 '(
cProducts.Transience.Transience\nIncreaser\nq\x01)tq\x02.J\x88\xa6\xb8E.'
committedData ''
ConflictError during conflict resolution in tryToResolveConflict,
ConflictResolution.py
Traceback (most recent call last):
  File "/opt/aef/Zope-2.9.0/lib/python/ZODB/ConflictResolution.py", line
126, in tryToResolveConflict
    old = state(self, oid, oldSerial, prfactory)
  File "/opt/aef/Zope-2.9.0/lib/python/ZODB/ConflictResolution.py", line 53,
in state
    p = p or self.loadSerial(oid, serial)
  File "/opt/aef/Zope-2.9.0//lib/python/tempstorage/TemporaryStorage.py",
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/Publish.py", line 119, in
publish
    transactions_manager.commit()
  File "/opt/aef/Zope-2.9.0//lib/python/Zope2/App/startup.py", line 234, in
commit
    transaction.commit()
  File "/opt/aef/Zope-2.9.0//lib/python/transaction/_manager.py", line 96,
in commit
    return self.get().commit(sub, deprecation_wng=False)
  File "/opt/aef/Zope-2.9.0//lib/python/transaction/_transaction.py", line
380, in commit
    self._saveCommitishError() # This raises!
  File "/opt/aef/Zope-2.9.0//lib/python/transaction/_transaction.py", line
378, in commit
    self._commitResources()
  File "/opt/aef/Zope-2.9.0//lib/python/transaction/_transaction.py", line
433, in _commitResources
    rm.commit(self)
  File "/opt/aef/Zope-2.9.0//lib/python/ZODB/Connection.py", line 484, in
commit
    self._commit(transaction)
  File "/opt/aef/Zope-2.9.0//lib/python/ZODB/Connection.py", line 526, in
_commit
    self._store_objects(ObjectWriter(obj), transaction)
  File "/opt/aef/Zope-2.9.0//lib/python/ZODB/Connection.py", line 554, in
_store_objects
    s = self._storage.store(oid, serial, p, self._version, transaction)
  File "/opt/aef/Zope-2.9.0//lib/python/tempstorage/TemporaryStorage.py",
line 200, in store
    data=data)
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)
</console>

The exception is raised, as the traceback says, in File
"/opt/aef/Zope-2.9.0//lib/python/tempstorage/TemporaryStorage.py",
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 :

<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! """
        self._lock_acquire()
        try:
            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)
            else:
                return data[0] # data here is actually (data, t)
        finally:
            self._lock_release()

</code>

2007/1/25, Martijn Pieters <mj at zopatista.com>:
>
> On 1/24/07, Maciej Wisniowski <maciej.wisniowski at coig.katowice.pl> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.zope.org/pipermail/zope/attachments/20070125/066fa7af/attachment-0001.htm


More information about the Zope mailing list