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