[ZODB-Dev] ZEO and 'new' (Zope3/)ZODB: ConflictError trouble

Ury Marshak um@hottech-israel.com
Wed, 26 Jun 2002 14:34:11 +0200


Now that we learned ;) that btrees are ok with sequential
inserts I tried to actually start using them, and ran into
some problems in case of conflicts

My setup - win2k machine, python 2.2.1, ZODB from Zope3/ cvs
(main trunk), ZEO from cvs (also main), running the same
prog (source below) in two windows. The program asks for
user input before doing commits, which allows me to start it,
press Enter a couple of times to add some object, start
another copy, add some more objects, go back, press Enter
and get a ConflictError.

The first surprize was that instead of ConflictError I was
getting an ImportError. Investigation revealed that the ZEO
_server_ was demanding to import my classes. I tracked it down
to line 88 in ZODB/ConflictResolution.py, in function
tryToResolveConflict(...) that was importing the class to
call _p_resolveConflict on it. Since I wasn't using that
feature, I wrapped the offending line in a 'try:' block:

    try:
        klass = _classFactory(class_tuple[0], class_tuple[1])
    except ImportError:
        bad_classes[class_tuple]=1
        return 0


This helped - at least I started getting the ConflictError,
instead of ImportError (although it still did not work with
classes defined in the main module -- that's why I cannot narrow
the example to one file). But then I ran into another problem:
when after catching the 'ConflictError' I try to redo the
offending transaction, I get a KeyError raised by the server.
Running the ZEO server with full logging produces the following:

2002-06-26T12:17:51 INFO(0) ZEO Server:1576:1 registered storage 1:
<ZODB.FileStorage.FileStorage instance at

0x00832600>
------
2002-06-26T12:17:54 ERROR(200) ZEO Server:1576:C:\Temp\bug\Data.fs store
error:

ZODB.POSException.ConflictError, database conflict error (oid
0000000000000001, serial was 0345b261dee0bbdd,

now 0345b261cc1434f7)
Traceback (innermost last):
  File C:\Python22\Lib\site-packages\ZEO\StorageServer.py, line 458, in
store
  File C:\Python22\Lib\site-packages\ZODB\FileStorage.py, line 679, in store
    (Object: C:\Temp\bug\Data.fs)
ConflictError: database conflict error (oid 0000000000000001, serial was
0345b261dee0bbdd, now

0345b261cc1434f7)


------
2002-06-26T12:17:54 ERROR(200) ZEO Server:1576:C:\Temp\bug\Data.fs store
error:

Persistence.BTrees.Exception.BTreesConflictError, BTrees conflict error
at -1/10/10: Conflicting inserts
Traceback (innermost last):
  File C:\Python22\Lib\site-packages\ZEO\StorageServer.py, line 458, in
store
  File C:\Python22\Lib\site-packages\ZODB\FileStorage.py, line 676, in store
    (Object: C:\Temp\bug\Data.fs)
  File C:\Python22\Lib\site-packages\ZODB\ConflictResolution.py, line 104,
in tryToResolveConflict
    (Object: C:\Temp\bug\Data.fs)
BTreesConflictError: BTrees conflict error at -1/10/10: Conflicting inserts


------
2002-06-26T12:17:56 ERROR(200) (<class exceptions.KeyError at 0x00771F00>,
<exceptions.KeyError instance at

0x0098BE48>) zeoLoad() raised exception:       1



Now I'm stuck, this requires some knowledge of how this operates....
Here is the code, in two files:

-------------- file ObjectList.py -----------------
import ZODB
import Persistence
from Persistence.BTrees.IOBTree import IOBTree

from ZODB.POSException import ConflictError

class ObjectList(Persistence.Persistent):
    def __init__(self):
        self._tree = IOBTree()
        self._next_id = 1

    def add_new(self, obj):
        """Adds new object, returns id"""
        while 1:
            try:
                new_id = self._next_id
                self._next_id +=1
                self._tree[new_id] = obj
                print 'new id: ',new_id, ', press enter to commit'
                raw_input()
                get_transaction().commit()
            except ConflictError:
                print 'conflict'
            else:
                break
        return new_id



-------------- file runme.py -----------------
from ZEO import ClientStorage
from ZODB import DB
import Persistence

from ObjectList import ObjectList


class C(Persistence.Persistent): pass

if __name__ == "__main__":

    host='127.0.0.1'   #'10.0.1.40'
    port=7980
    addr = (host, port)

    storage = ClientStorage.ClientStorage(addr)
    db = DB( storage )
    conn = db.open()
    root = conn.root()

    treename = 'aaaa'
    if not root.has_key(treename):
        root[treename]=ObjectList()
        get_transaction().commit()

    obj_tree = root[treename]

    for i in range(0,20):
        c = C()
        c_id = obj_tree.add_new(c)
        print 'added with id=',c_id


-------------- and the batch file to start ZEO-----------------
set STUPID_LOG_FILE=aaa.txt
C:\Python22\Lib\site-packages\ZEO\start.py -d -p 7980

-----------
Thanks for any pointers,
Ury