[Zope-dev] Coroner's toolkit for zope, or how to figure out what went wrong.

Romain Slootmaekers romain@zzict.com
Tue, 13 Aug 2002 00:31:34 +0200


This is a multi-part message in MIME format.
--------------030209060005010408090602
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Jim Fulton wrote:
> Romain Slootmaekers wrote:
> 
> 
> I think you are pretty far off here. You said you saw a read conflict.
> No conflict resolution is done for a read conflict. Further, from the very
> brief description of your DB class, it doesn't appear to use any objects
> that actually try to resolve conflicts. I doubt seriously that this has
> anything to do with conflict resolution. It is very doubtful that a 
> database
> error would cause your data to simply disappear without some sort of error,
> like a database corruption error or an error about invalid object ids 
> (dangling
> references). Have you considered an application error?

yes, that's the first thing one does: doubt your own code.

the object in question is created once, and there is no code to delete 
it since in that application, it is of no use.
The only thing that happens is that we add/moify/delete other object to
that rootnode.



> 
> If you still have the data file with the lost data, it should be 
> possible to
> analyze it to figure out what went wrong. In particular, it would be 
> helpful
> to figure out just what transaction made the data go away to figure out 
> what it
> might have been doing.

that was exactly the question I was asking in the first place :
tools to browse the ZODB, to see where it broke.


> It simply causes the transaction with the read conflict to be reexecuted.
> 


Ok, I figured that out by now as well. the read conflict error has 
indeed nothing to do with our problem. sorry 'bout that...

But we found something else:

I included a script below that produces a stripped down analogy
of our problem. (no zope needed, just ZODB, and you might wanna modify 
the first line to get it working)

The script produces the following output:


C:\zope\devel>bin\python.exe \temp\test.py
<Foo instance at 008DCAC8> 0
<Foo instance at 008E1280> 0
Traceback (most recent call last):
   File "\temp\test.py", line 68, in ?
     get_transaction().commit()
   File "C:\zope\devel\lib\python\ZODB\Transaction.py", line 234, in commit
     j.commit(o,self)
   File "C:\zope\devel\lib\python\ZODB\Connection.py", line 348, in commit
     s=dbstore(oid,serial,p,version,transaction)
   File "C:\zope\devel\lib\python\ZODB\FileStorage.py", line 665, in store
     data=self.tryToResolveConflict(oid, oserial, serial, data)
   File "C:\zope\devel\lib\python\ZODB\ConflictResolution.py", line 108, 
in tryTo
ResolveConflict
     resolved=resolve(old, committed, newstate)
   File "\temp\test.py", line 30, in _p_resolveConflict
     print savedState['data'].getHello()
AttributeError: PersistentReference instance has no attribute 'getHello'


The question is: is intended ZODB behaviour or not, and is there a work 
around ?

have fun,

Sloot.

--------------030209060005010408090602
Content-Type: text/plain;
 name="test.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="test.py"

swhome=r'C:\zope\devel'
import sys
sys.path.insert(0, '%s/lib/python' % swhome)
sys.path.insert(1, '%s/bin/lib' % swhome)

import ZODB
from Persistence import Persistent

class Dummy(Persistent):
    
    def __init__(self):
        self.hello = "Hello there..."
        
    def getHello(self):
        return self.hello

class Foo(Persistent):

    def __init__(self):
        self.data = Dummy()
        self.count = 0

    def incCounter(self):
        self.count += 1

    def getCount(self):
        return self.count

    def _p_resolveConflict(self, oldState, savedState, newState):
        print savedState['data'].getHello()
        print newState['data'].getHello()
        print oldState['data'].getHello()
        diffsaved = savedState['count'] - oldState['count']
        diffnew = newState['count'] - oldState['count']
        newState['count'] = oldState['count'] + diffsaved + diffnew
        return newState


from ZODB import FileStorage, DB

storage = FileStorage.FileStorage('/temp/test.fs')
db = DB( storage )

# Init van test object
conn = db.open()

root = conn.root()
root['foo'] = Foo()
get_transaction().commit()
    
conn.close()

conn1 = db.open()
root1 = conn1.root()
foo1 = root1['foo']

conn2 = db.open()
root2 = conn2.root()
foo2 = root2['foo']

print foo1, foo1.getCount()
print foo2, foo2.getCount()

foo1.incCounter()
get_transaction().commit()

foo2.incCounter()
get_transaction().commit()

print foo1, foo1.getCount()
print foo2, foo2.getCount()

--------------030209060005010408090602--