Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2b86070

Browse files
committed
Use repeatable read isolation level
2 parents b9bbb09 + c05a76f commit 2b86070

File tree

3 files changed

+107
-43
lines changed

3 files changed

+107
-43
lines changed

contrib/mmts/tests2/docker-entrypoint.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ if [ "$1" = 'postgres' ]; then
7373
max_replication_slots = 10
7474
max_wal_senders = 10
7575
shared_preload_libraries = 'raftable,multimaster'
76-
default_transaction_isolation = 'repeatable read'
76+
default_transaction_isolation = 'repeatable read'
77+
log_checkpoints = on
78+
log_autovacuum_min_duration = 0
7779
7880
raftable.id = $NODE_ID
7981
raftable.peers = '$RAFT_PEERS'

contrib/mmts/tests2/lib/bank_client.py

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import time
66
import sys
77
from event_history import *
8+
import select
9+
import signal
810

911
class ClientCollection(object):
1012
def __init__(self, connstrs):
@@ -38,8 +40,6 @@ def print_agg(self):
3840

3941
columns = ['running', 'running_latency', 'max_latency', 'finish']
4042

41-
#rows = [ k+str(i+1) for k in agg.keys() for i, agg in enumerate(aggs)]
42-
4343
print("\t\t", end="")
4444
for col in columns:
4545
print(col, end="\t")
@@ -61,17 +61,29 @@ def print_agg(self):
6161

6262
print("")
6363

64+
def set_acc_to_tx(self, max_acc):
65+
for client in self._clients:
66+
client.set_acc_to_tx(max_acc)
67+
6468

6569
class BankClient(object):
6670

67-
def __init__(self, connstr, node_id):
71+
def __init__(self, connstr, node_id, accounts = 10000):
6872
self.connstr = connstr
6973
self.node_id = node_id
7074
self.run = Value('b', True)
7175
self._history = EventHistory()
72-
self.accounts = 10000
76+
self.accounts = accounts
77+
self.accounts_to_tx = accounts
7378
self.show_errors = True
7479

80+
#x = self
81+
#def on_sigint(sig, frame):
82+
# x.stop()
83+
#
84+
#signal.signal(signal.SIGINT, on_sigint)
85+
86+
7587
def initialize(self):
7688
conn = psycopg2.connect(self.connstr)
7789
cur = conn.cursor()
@@ -88,6 +100,22 @@ def initialize(self):
88100
cur.close()
89101
conn.close()
90102

103+
def aconn(self):
104+
return psycopg2.connect(self.connstr, async=1)
105+
106+
@classmethod
107+
def wait(cls, conn):
108+
while 1:
109+
state = conn.poll()
110+
if state == psycopg2.extensions.POLL_OK:
111+
break
112+
elif state == psycopg2.extensions.POLL_WRITE:
113+
select.select([], [conn.fileno()], [])
114+
elif state == psycopg2.extensions.POLL_READ:
115+
select.select([conn.fileno()], [], [])
116+
else:
117+
raise psycopg2.OperationalError("poll() returned %s" % state)
118+
91119
@property
92120
def history(self):
93121
return self._history
@@ -105,25 +133,16 @@ def exec_tx(self, name, tx_block):
105133

106134
if conn.closed:
107135
self.history.register_finish(event_id, 'ReConnect')
108-
try :
109-
conn = psycopg2.connect(self.connstr)
110-
cur = conn.cursor()
111-
except :
112-
continue
113-
else :
114-
continue
136+
conn = psycopg2.connect(self.connstr)
137+
cur = conn.cursor()
115138

116139
try:
117-
tx_block(conn, cur)
140+
tx_block(conn, cur)
141+
self.history.register_finish(event_id, 'Commit')
118142
except psycopg2.InterfaceError:
119143
self.history.register_finish(event_id, 'InterfaceError')
120144
except psycopg2.Error:
121145
self.history.register_finish(event_id, 'PsycopgError')
122-
except :
123-
print(sys.exc_info())
124-
self.history.register_finish(event_id, 'OtherError')
125-
else :
126-
self.history.register_finish(event_id, 'Commit')
127146

128147
cur.close()
129148
conn.close()
@@ -135,17 +154,20 @@ def tx(conn, cur):
135154
res = cur.fetchone()
136155
conn.commit()
137156
if res[0] != 0:
138-
print("Isolation error, total = %d" % (res[0],))
157+
print("Isolation error, total = %d, node = %d" % (res[0],self.node_id))
139158
raise BaseException
140159

141160
self.exec_tx('total', tx)
142161

162+
def set_acc_to_tx(self, max_acc):
163+
self.accounts_to_tx = max_acc
164+
143165
def transfer_money(self):
144166

145167
def tx(conn, cur):
146168
amount = 1
147-
from_uid = random.randrange(1, self.accounts - 10)
148-
to_uid = from_uid + 1 #random.randrange(1, self.accounts + 1)
169+
from_uid = random.randrange(1, self.accounts_to_tx - 1)
170+
to_uid = random.randrange(1, self.accounts_to_tx - 1)
149171

150172
conn.commit()
151173
cur.execute('''update bank_test
@@ -161,7 +183,10 @@ def tx(conn, cur):
161183
self.exec_tx('transfer', tx)
162184

163185
def start(self):
164-
self.transfer_process = Process(target=self.transfer_money, args=())
186+
print('Starting client');
187+
self.run.value = True
188+
189+
self.transfer_process = Process(target=self.transfer_money, name="txor", args=())
165190
self.transfer_process.start()
166191

167192
self.total_process = Process(target=self.check_total, args=())
@@ -170,7 +195,7 @@ def start(self):
170195
return
171196

172197
def stop(self):
173-
print('Stopping!');
198+
print('Stopping client');
174199
self.run.value = False
175200
self.total_process.terminate()
176201
self.transfer_process.terminate()

contrib/mmts/tests2/test_recovery.py

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,80 @@
44
from lib.bank_client import *
55

66
class RecoveryTest(unittest.TestCase):
7-
def setUp(self):
7+
@classmethod
8+
def setUpClass(self):
89
#subprocess.check_call(['blockade','up'])
910
self.clients = ClientCollection([
1011
"dbname=postgres host=127.0.0.1 user=postgres",
1112
"dbname=postgres host=127.0.0.1 user=postgres port=5433",
1213
"dbname=postgres host=127.0.0.1 user=postgres port=5434"
1314
])
14-
self.clients.start()
1515

16-
def tearDown(self):
16+
@classmethod
17+
def tearDownClass(self):
1718
print('tearDown')
19+
#subprocess.check_call(['blockade','join'])
20+
21+
# in case of error
1822
self.clients.stop()
19-
self.clients[0].cleanup()
20-
subprocess.check_call(['blockade','join'])
23+
#self.clients[0].cleanup()
24+
25+
26+
def test_0_normal_operation(self):
27+
print('### normalOpsTest ###')
28+
29+
self.clients.set_acc_to_tx(10000)
30+
self.clients.start()
31+
32+
for i in range(5):
33+
time.sleep(3)
34+
for client in self.clients:
35+
agg = client.history.aggregate()
36+
print(agg)
37+
self.assertTrue(agg['transfer']['finish']['Commit'] > 0)
38+
print("\n")
39+
40+
self.clients.stop()
41+
42+
def test_1_distributed_deadlock(self):
43+
print('### DDD test ###')
44+
45+
self.clients.set_acc_to_tx(10)
46+
self.clients.start()
47+
48+
for i in range(5):
49+
time.sleep(3)
50+
for client in self.clients:
51+
agg = client.history.aggregate()
52+
print(agg)
53+
self.assertTrue(agg['transfer']['finish']['Commit'] > 0)
54+
print("\n")
2155

22-
# def test_0_normal_operation(self):
23-
# print('### normalOpsTest ###')
24-
# print('Waiting 5s to check operability')
25-
# time.sleep(5)
26-
#
27-
# for client in self.clients:
28-
# agg = client.history.aggregate()
29-
# print(agg)
30-
# self.assertTrue(agg['transfer']['finish']['Commit'] > 0)
31-
32-
def test_1_node_disconnect(self):
56+
self.clients.stop()
57+
58+
def test_2_node_disconnect(self):
3359
print('### disconnectTest ###')
3460

61+
self.clients.set_acc_to_tx(10000)
62+
self.clients.start()
63+
3564
subprocess.check_call(['blockade','partition','node3'])
3665
print('Node3 disconnected')
3766

38-
for i in range(1000):
67+
# give cluster some time to discover problem
68+
time.sleep(3)
69+
70+
for i in range(5):
3971
time.sleep(3)
40-
self.clients.print_agg()
72+
for client in self.clients:
73+
agg = client.history.aggregate()
74+
print(agg)
75+
self.assertTrue(agg['transfer']['finish']['Commit'] > 0)
76+
print("\n")
77+
78+
subprocess.check_call(['blockade','join'])
79+
self.clients.stop()
4180

4281
if __name__ == '__main__':
4382
unittest.main()
4483

45-
46-

0 commit comments

Comments
 (0)