1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2002,2008 Oracle.  All rights reserved.
4#
5# $Id: rep003.tcl,v 12.14 2008/01/08 20:58:53 bostic Exp $
6#
7# TEST  	rep003
8# TEST	Repeated shutdown/restart replication test
9# TEST
10# TEST	Run a quick put test in a replicated master environment;
11# TEST	start up, shut down, and restart client processes, with
12# TEST	and without recovery.  To ensure that environment state
13# TEST	is transient, use DB_PRIVATE.
14
15proc rep003 { method { tnum "003" } args } {
16	source ./include.tcl
17	global rep003_dbname rep003_omethod rep003_oargs
18
19	if { $is_windows9x_test == 1 } {
20		puts "Skipping replication test on Win 9x platform."
21		return
22	}
23
24	# Skip for record-based methods.
25	if { $checking_valid_methods } {
26		set test_methods {}
27		foreach method $valid_methods {
28			if { [is_record_based $method] != 1 } {
29				lappend test_methods $method
30			}
31		}
32		return $test_methods
33	}
34	if { [is_record_based $method] } {
35		puts "Rep$tnum: Skipping for method $method"
36		return
37	}
38
39	set rep003_dbname rep003.db
40	set rep003_omethod [convert_method $method]
41	set rep003_oargs [convert_args $method $args]
42
43	# Run the body of the test with and without recovery.  If we're
44	# testing in-memory logging, skip the combination of recovery
45	# and in-memory logging -- it doesn't make sense.
46
47	set logsets [create_logsets 2]
48	foreach recopt $test_recopts {
49		foreach l $logsets {
50			set logindex [lsearch -exact $l "in-memory"]
51			if { $recopt == "-recover" && $logindex != -1 } {
52				puts "Rep$tnum: Skipping for\
53				    in-memory logs with -recover."
54				continue
55			}
56			puts "Rep$tnum ($method $recopt):\
57			    Replication repeated-startup test."
58			puts "Rep$tnum: Master logs are [lindex $l 0]"
59			puts "Rep$tnum: Client logs are [lindex $l 1]"
60			rep003_sub $method $tnum $l $recopt $args
61		}
62	}
63}
64
65proc rep003_sub { method tnum logset recargs largs } {
66	source ./include.tcl
67	global rep_verbose
68	global verbose_type
69
70	set verbargs ""
71	if { $rep_verbose == 1 } {
72		set verbargs " -verbose {$verbose_type on} "
73	}
74
75	env_cleanup $testdir
76
77	replsetup $testdir/MSGQUEUEDIR
78
79	set masterdir $testdir/MASTERDIR
80	set clientdir $testdir/CLIENTDIR
81
82	file mkdir $masterdir
83	file mkdir $clientdir
84
85	set m_logtype [lindex $logset 0]
86	set c_logtype [lindex $logset 1]
87
88	# In-memory logs require a large log buffer, and cannot
89	# be used with -txn nosync.  This test already requires
90	# -txn, so adjust the logargs only.
91	set m_logargs [adjust_logargs $m_logtype]
92	set c_logargs [adjust_logargs $c_logtype]
93
94	# Open a master.
95	repladd 1
96	set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 \
97	    -errpfx MASTER $verbargs \
98	    -home $masterdir -txn $m_logargs -rep_master \
99	    -rep_transport \[list 1 replsend\]"
100	set masterenv [eval $env_cmd(M) $recargs]
101	error_check_good master_env [is_valid_env $masterenv] TRUE
102
103	puts "\tRep$tnum.a: Simple client startup test."
104
105	# Put item one.
106	rep003_put $masterenv A1 a-one
107
108	# Open a client.
109	repladd 2
110	set env_cmd(C) "berkdb_env_noerr -create -private -home $clientdir \
111	    -txn $c_logargs -errpfx CLIENT $verbargs \
112	    -rep_client -rep_transport \[list 2 replsend\]"
113	set clientenv [eval $env_cmd(C) $recargs]
114	error_check_good client_env [is_valid_env $clientenv] TRUE
115
116	# Put another quick item.
117	rep003_put $masterenv A2 a-two
118
119	# Loop, processing first the master's messages, then the client's,
120	# until both queues are empty.
121	set envlist "{$masterenv 1} {$clientenv 2}"
122	process_msgs $envlist
123
124	rep003_check $clientenv A1 a-one
125	rep003_check $clientenv A2 a-two
126
127	error_check_good clientenv_close [$clientenv close] 0
128	replclear 2
129
130	# Now reopen the client after doing another put.
131	puts "\tRep$tnum.b: Client restart."
132	rep003_put $masterenv B1 b-one
133
134	set clientenv [eval $env_cmd(C)]
135	error_check_good client_env [is_valid_env $clientenv] TRUE
136
137	# Loop letting the client and master sync up and get the
138	# environment initialized.  It's a new client env so
139	# reinitialize the envlist as well.
140	set envlist "{$masterenv 1} {$clientenv 2}"
141	process_msgs $envlist
142
143	# The items from part A should be present at all times--
144	# if we roll them back, we've screwed up. [#5709]
145	rep003_check $clientenv A1 a-one
146	rep003_check $clientenv A2 a-two
147
148	rep003_put $masterenv B2 b-two
149
150	# Loop, processing first the master's messages, then the client's,
151	# until both queues are empty.
152	while { 1 } {
153		set nproced 0
154
155		incr nproced [replprocessqueue $masterenv 1]
156		incr nproced [replprocessqueue $clientenv 2]
157
158		# The items from part A should be present at all times--
159		# if we roll them back, we've screwed up. [#5709]
160		rep003_check $clientenv A1 a-one
161		rep003_check $clientenv A2 a-two
162
163		if { $nproced == 0 } {
164			break
165		}
166	}
167
168	rep003_check $clientenv B1 b-one
169	rep003_check $clientenv B2 b-two
170
171	error_check_good clientenv_close [$clientenv close] 0
172
173	replclear 2
174
175	# Now reopen the client after a recovery.
176	puts "\tRep$tnum.c: Client restart after recovery."
177	rep003_put $masterenv C1 c-one
178
179	set clientenv [eval $env_cmd(C) -recover]
180	error_check_good client_env [is_valid_env $clientenv] TRUE
181
182	# Loop, processing first the master's messages, then the client's,
183	# until both queues are empty.
184	set envlist "{$masterenv 1} {$clientenv 2}"
185	process_msgs $envlist
186
187	# The items from part A should be present at all times--
188	# if we roll them back, we've screwed up. [#5709]
189	rep003_check $clientenv A1 a-one
190	rep003_check $clientenv A2 a-two
191	rep003_check $clientenv B1 b-one
192	rep003_check $clientenv B2 b-two
193
194	rep003_put $masterenv C2 c-two
195
196	# Loop, processing first the master's messages, then the client's,
197	# until both queues are empty.
198	while { 1 } {
199		set nproced 0
200
201		# The items from part A should be present at all times--
202		# if we roll them back, we've screwed up. [#5709]
203		rep003_check $clientenv A1 a-one
204		rep003_check $clientenv A2 a-two
205		rep003_check $clientenv B1 b-one
206		rep003_check $clientenv B2 b-two
207
208		incr nproced [replprocessqueue $masterenv 1]
209		incr nproced [replprocessqueue $clientenv 2]
210
211		if { $nproced == 0 } {
212			break
213		}
214	}
215
216	rep003_check $clientenv C1 c-one
217	rep003_check $clientenv C2 c-two
218
219	error_check_good clientenv_close [$clientenv close] 0
220
221	replclear 2
222
223	# Now reopen the client after a catastrophic recovery.
224	puts "\tRep$tnum.d: Client restart after catastrophic recovery."
225	rep003_put $masterenv D1 d-one
226
227	set clientenv [eval $env_cmd(C) -recover_fatal]
228	error_check_good client_env [is_valid_env $clientenv] TRUE
229
230	# Loop, processing first the master's messages, then the client's,
231	# until both queues are empty.
232	set envlist "{$masterenv 1} {$clientenv 2}"
233	process_msgs $envlist
234	rep003_put $masterenv D2 d-two
235
236	# Loop, processing first the master's messages, then the client's,
237	# until both queues are empty.
238	while { 1 } {
239		set nproced 0
240
241		# The items from part A should be present at all times--
242		# if we roll them back, we've screwed up. [#5709]
243		rep003_check $clientenv A1 a-one
244		rep003_check $clientenv A2 a-two
245		rep003_check $clientenv B1 b-one
246		rep003_check $clientenv B2 b-two
247		rep003_check $clientenv C1 c-one
248		rep003_check $clientenv C2 c-two
249
250		incr nproced [replprocessqueue $masterenv 1]
251		incr nproced [replprocessqueue $clientenv 2]
252
253		if { $nproced == 0 } {
254			break
255		}
256	}
257
258	rep003_check $clientenv D1 d-one
259	rep003_check $clientenv D2 d-two
260
261	error_check_good clientenv_close [$clientenv close] 0
262
263	error_check_good masterenv_close [$masterenv close] 0
264	replclose $testdir/MSGQUEUEDIR
265}
266
267proc rep003_put { masterenv key data } {
268	global rep003_dbname rep003_omethod rep003_oargs
269
270	set db [eval {berkdb_open_noerr -create -env $masterenv -auto_commit} \
271	    $rep003_omethod $rep003_oargs $rep003_dbname]
272	error_check_good rep3_put_open($key,$data) [is_valid_db $db] TRUE
273
274	set txn [$masterenv txn]
275	error_check_good rep3_put($key,$data) [$db put -txn $txn $key $data] 0
276	error_check_good rep3_put_txn_commit($key,$data) [$txn commit] 0
277
278	error_check_good rep3_put_close($key,$data) [$db close] 0
279}
280
281proc rep003_check { env key data } {
282	global rep003_dbname
283
284	set db [berkdb_open_noerr -rdonly -env $env $rep003_dbname]
285	error_check_good rep3_check_open($key,$data) [is_valid_db $db] TRUE
286
287	set dbt [$db get $key]
288	error_check_good rep3_check($key,$data) \
289	    [lindex [lindex $dbt 0] 1] $data
290
291	error_check_good rep3_put_close($key,$data) [$db close] 0
292}
293