Commit af381382 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent bb8587da
...@@ -166,7 +166,7 @@ error _Conn::_pinner(context::Context ctx) { ...@@ -166,7 +166,7 @@ error _Conn::_pinner(context::Context ctx) {
// mark the connection non-operational if the pinner fails // mark the connection non-operational if the pinner fails
wconn._downMu.lock(); wconn._downMu.lock();
if (wconn._downErr == nil) { if (wconn._downErr == nil) {
wconn._downErr = fmt::errorf("no longer operational due to: %s", v(err)); wconn._downErr = fmt::errorf("no longer operational due to: %w", err);
// XXX make all fileh and mapping invalid. // XXX make all fileh and mapping invalid.
} }
wconn._downMu.unlock(); wconn._downMu.unlock();
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
from __future__ import print_function from __future__ import print_function
from ZODB import DB from ZODB import DB
from ZODB.MappingStorage import MappingStorage
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
import transaction import transaction
from persistent import Persistent from persistent import Persistent
...@@ -24,20 +23,6 @@ from wendelin.lib.testing import TestDB_ZEO ...@@ -24,20 +23,6 @@ from wendelin.lib.testing import TestDB_ZEO
@func @func
def main(): def main():
"""
if 0:
zstor = MappingStorage()
db = DB(zstor)
else:
tdb = TestDB_ZEO('<zeo>')
tdb.setup()
defer(tdb.teardown)
zstor = tdb.getZODBStorage()
db = DB(zstor)
#zstor.app.poll_thread.name = 'C.poll'
"""
tdb = TestDB_ZEO('<zeo>') tdb = TestDB_ZEO('<zeo>')
tdb.setup() tdb.setup()
defer(tdb.teardown) defer(tdb.teardown)
...@@ -47,7 +32,6 @@ def main(): ...@@ -47,7 +32,6 @@ def main():
db = DB(zstor) db = DB(zstor)
return db return db
# init initializes the database with two integer objects - obj1/obj2 that are set to 0. # init initializes the database with two integer objects - obj1/obj2 that are set to 0.
@func @func
def init(): def init():
...@@ -65,20 +49,24 @@ def main(): ...@@ -65,20 +49,24 @@ def main():
zconn.close() zconn.close()
# T1 accesses obj1/obj2 in a loop and verifies that obj1.i == obj2.i # T is a worker that accesses obj1/obj2 in a loop and verifies
# `obj1.i == obj2.i` invariant.
# #
# access to obj1 is organized to always trigger loading from zstor. # access to obj1 is organized to always trigger loading from zstor.
# access to obj2 goes through zconn cache and so verifies whether the cache is not stale. # access to obj2 goes through zconn cache and so verifies whether the cache is not stale.
# #
# XXX + commit # Once in a while T tries to modify obj{1,2}.i maintaining the invariant as
# test source of changes for other workers.
@func @func
def T1(ctx, name, N): def T(ctx, name, N):
db = dbopen() db = dbopen()
defer(db.close) defer(db.close)
@func
def t1(): def t1():
transaction.begin() transaction.begin()
zconn = db.open() zconn = db.open()
defer(zconn.close)
root = zconn.root() root = zconn.root()
obj1 = root['obj1'] obj1 = root['obj1']
...@@ -92,7 +80,7 @@ def main(): ...@@ -92,7 +80,7 @@ def main():
i1 = obj1.i i1 = obj1.i
i2 = obj2.i i2 = obj2.i
if i1 != i2: if i1 != i2:
print('FAIL') #print('FAIL')
raise AssertionError("T%s: obj1.i (%d) != obj2.i (%d)" % (name, i1, i2)) raise AssertionError("T%s: obj1.i (%d) != obj2.i (%d)" % (name, i1, i2))
# change objects once in a while # change objects once in a while
...@@ -101,64 +89,27 @@ def main(): ...@@ -101,64 +89,27 @@ def main():
obj1.i += 1 obj1.i += 1
obj2.i += 1 obj2.i += 1
#transaction.abort() # we did not changed anything; also fails with commit
try: try:
transaction.commit() transaction.commit()
except ConflictError: except ConflictError:
#print('conflict -> ignore') #print('conflict -> ignore')
transaction.abort() transaction.abort()
zconn.close()
for i in range(N): for i in range(N):
if ready(ctx.done()): if ready(ctx.done()):
break break
#print('T%s.%d' % (name, i)) #print('T%s.%d' % (name, i))
t1() t1()
raise RuntimeError("T1: done")
"""
# T2 changes obj1/obj2 in a loop by doing `objX.i += 1`.
#
# Since both objects start from 0, the invariant that `obj1.i == obj2.i` is always preserved.
@func
def T2(ctx, N):
db = dbopen()
defer(db.close)
def t2():
transaction.begin()
zconn = db.open()
root = zconn.root()
obj1 = root['obj1']
obj2 = root['obj2']
obj1.i += 1
obj2.i += 1
assert obj1.i == obj2.i
transaction.commit()
zconn.close()
for i in range(N):
if ready(ctx.done()):
break
#print('T2.%d' % i)
t2()
"""
# run T1 and T2 concurrently. As of 20191210, due to race condition in # run 8 T workers concurrently. As of 20200123, likely due to race conditions
# Connection.open, it triggers the bug where T1 sees stale obj2 with obj1.i != obj2.i # in ZEO, it triggers the bug where T sees stale obj2 with obj1.i != obj2.i
init() init()
N = 100000 N = 100000
wg = sync.WorkGroup(context.background()) wg = sync.WorkGroup(context.background())
for x in 'abcdefgh': for x in range(8):
wg.go(T1, x, N) wg.go(T, x, N)
#wg.go(T2, N)
wg.wait() wg.wait()
print('OK') print('OK')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment