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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy