Ok, I have the asyncore loop in, I've added explicit transaction begin
and aborts, and cleaned up the test case a bit:

import thread
import asyncore
import random
from ZEO.ClientStorage import ClientStorage
from ZODB import DB
from persistent.list import PersistentList
from ZODB.POSException import ConflictError
import transaction

storage = ClientStorage(('bw64node01', 12345))
db = DB(storage)
conn = db.open()
root = conn.root()
conn.sync()
thread.start_new_thread(asyncore.loop,())

if 'test' not in root:
   try:
       transaction.begin()
       root['test'] = PersistentList([0,1])
       transaction.commit()
   except ConflictError:
       transaction.abort()

g = root['test']
y = PersistentList()
while 1:
   try:
       transaction.begin()
       g[g.index(random.choice(g))] = y
#        g[g.index(random.choice(g))] = PersistentList()
       transaction.commit()
   except ConflictError:
       transaction.abort()

Now, when 4 or so instances are run in parallel, this will fail with
POSKeyError corruption of the ZODB database. However, if you uncomment
the commented out line, it's fine. Maybe I'm  missing something - why
can't I create a PersistentList outside of the transaction, and then
add multiple entries inside root['test'] pointing to it?

Another interesting thing; if I add time.sleep(1) to the end of the
while loop, then the problem goes away. Possibly there is some kind of
cache race condition, where the ZEO server sends invalidations
immediately after the client has commited?
_______________________________________________
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev

Reply via email to