1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2001-2009 Oracle.  All rights reserved.
4#
5# $Id$
6#
7# TEST	rep050
8# TEST	Replication and delay syncing clients - change master test.
9# TEST
10# TEST	Open and start up master and 4 clients.  Turn on delay for 3 clients.
11# TEST	Switch masters, add data and verify delayed clients are out of date.
12# TEST	Make additional changes to master.  And change masters again.
13# TEST	Sync/update delayed client and verify.  The 4th client is a brand
14# TEST	new delayed client added in to test the non-verify path.
15# TEST
16# TEST	Then test two different things:
17# TEST	1. Swap master again while clients are still delayed.
18# TEST	2. Swap master again while sync is proceeding for one client.
19#
20proc rep050 { method { niter 10 } { tnum "050" } args } {
21	source ./include.tcl
22	global databases_in_memory
23	global repfiles_in_memory
24
25	if { $is_windows9x_test == 1 } {
26		puts "Skipping replication test on Win 9x platform."
27		return
28	}
29
30	# Valid for all access methods.
31	if { $checking_valid_methods } {
32		return "ALL"
33	}
34
35	set args [convert_args $method $args]
36	set logsets [create_logsets 5]
37
38	# Set up for on-disk or in-memory databases.
39	set msg "using on-disk databases"
40	if { $databases_in_memory } {
41		set msg "using named in-memory databases"
42		if { [is_queueext $method] } {
43			puts -nonewline "Skipping rep$tnum for method "
44			puts "$method with named in-memory databases."
45			return
46		}
47	}
48
49	set msg2 "and on-disk replication files"
50	if { $repfiles_in_memory } {
51		set msg2 "and in-memory replication files"
52	}
53
54	# Run the body of the test with and without recovery.
55	foreach r $test_recopts {
56		foreach l $logsets {
57			set logindex [lsearch -exact $l "in-memory"]
58			if { $r == "-recover" && $logindex != -1 } {
59				puts "Rep$tnum: Skipping\
60				    for in-memory logs with -recover."
61				continue
62			}
63			puts "Rep$tnum ($r): Replication\
64			    and ($method) delayed sync-up $msg $msg2."
65			puts "Rep$tnum: Master logs are [lindex $l 0]"
66			puts "Rep$tnum: Client 0 logs are [lindex $l 1]"
67			puts "Rep$tnum: Delay Client 1 logs are [lindex $l 2]"
68			puts "Rep$tnum: Delay Client 2 logs are [lindex $l 3]"
69			puts "Rep$tnum: Delay Client 3 logs are [lindex $l 4]"
70			rep050_sub $method $niter $tnum $l $r $args
71		}
72	}
73}
74
75proc rep050_sub { method niter tnum logset recargs largs } {
76	global testdir
77	global util_path
78	global databases_in_memory
79	global repfiles_in_memory
80	global rep_verbose
81	global verbose_type
82
83	set verbargs ""
84	if { $rep_verbose == 1 } {
85		set verbargs " -verbose {$verbose_type on} "
86	}
87
88	set repmemargs ""
89	if { $repfiles_in_memory } {
90		set repmemargs "-rep_inmem_files "
91	}
92
93	env_cleanup $testdir
94	set orig_tdir $testdir
95
96	replsetup $testdir/MSGQUEUEDIR
97
98	set env1dir $testdir/MASTERDIR
99	set env2dir $testdir/CLIENTDIR
100	set delaycldir1 $testdir/DELAYCLDIR.1
101	set delaycldir2 $testdir/DELAYCLDIR.2
102	set delaycldir3 $testdir/DELAYCLDIR.3
103	file mkdir $env1dir
104	file mkdir $env2dir
105	file mkdir $delaycldir1
106	file mkdir $delaycldir2
107	file mkdir $delaycldir3
108
109	set m_logtype [lindex $logset 0]
110	set c_logtype [lindex $logset 1]
111	set dc1_logtype [lindex $logset 2]
112	set dc2_logtype [lindex $logset 3]
113	set dc3_logtype [lindex $logset 4]
114
115	# In-memory logs require a large log buffer, and cannot
116	# be used with -txn nosync.
117	set m_logargs [adjust_logargs $m_logtype]
118	set c_logargs [adjust_logargs $c_logtype]
119	set dc1_logargs [adjust_logargs $dc1_logtype]
120	set dc2_logargs [adjust_logargs $dc2_logtype]
121	set dc3_logargs [adjust_logargs $dc3_logtype]
122	set m_txnargs [adjust_txnargs $m_logtype]
123	set c_txnargs [adjust_txnargs $c_logtype]
124	set dc1_txnargs [adjust_txnargs $dc1_logtype]
125	set dc2_txnargs [adjust_txnargs $dc2_logtype]
126	set dc3_txnargs [adjust_txnargs $dc3_logtype]
127
128	#
129	# XXX rep050 delayed sync-up but change master:
130	# while client is delayed.
131	# while client is in the middle of delayed sync.
132
133	# Open a master.
134	repladd 1
135	set ma_envcmd "berkdb_env_noerr -create $m_txnargs \
136	    $m_logargs -errpfx ENV1 $verbargs $repmemargs \
137	    -home $env1dir -rep_transport \[list 1 replsend\]"
138	set env1 [eval $ma_envcmd $recargs -rep_master]
139	$env1 rep_limit 0 0
140
141	# Open two clients
142	repladd 2
143	set cl_envcmd "berkdb_env_noerr -create $c_txnargs \
144	    $c_logargs -errpfx ENV2 $verbargs $repmemargs \
145	    -cachesize {0 2097152 2} \
146	    -home $env2dir -rep_transport \[list 2 replsend\]"
147	set env2 [eval $cl_envcmd $recargs -rep_client]
148	$env2 rep_limit 0 0
149
150	repladd 3
151	set dc1_envcmd "berkdb_env_noerr -create $dc1_txnargs \
152	    $dc1_logargs -errpfx ENV3 $verbargs $repmemargs \
153	    -home $delaycldir1 -rep_transport \[list 3 replsend\]"
154	set dc1env [eval $dc1_envcmd $recargs -rep_client]
155	$dc1env rep_limit 0 0
156
157	repladd 4
158	set dc2_envcmd "berkdb_env_noerr -create $dc2_txnargs \
159	    $dc2_logargs -errpfx ENV4 $verbargs $repmemargs \
160	    -home $delaycldir2 -rep_transport \[list 4 replsend\]"
161	set dc2env [eval $dc2_envcmd $recargs -rep_client]
162	$dc2env rep_limit 0 0
163
164	repladd 5
165	set dc3_envcmd "berkdb_env_noerr -create $dc3_txnargs \
166	    $dc3_logargs -errpfx ENV5 $verbargs $repmemargs \
167	    -home $delaycldir3 -rep_transport \[list 5 replsend\]"
168
169	# Bring the clients online by processing the startup messages.
170	# !!!
171	# NOTE: We set up dc3_envcmd but we do not open the env now.
172	# Therefore dc3env is not part of the envlist.  However, since
173	# we did the repladd broadcast messages will be sent to it,
174	# but we will replclear before we start the env.
175	#
176	set envlist "{$env1 1} {$env2 2} {$dc1env 3} {$dc2env 4}"
177	process_msgs $envlist
178
179	puts "\tRep$tnum.a: Run rep_test in master env."
180	set start 0
181	eval rep_test $method $env1 NULL $niter $start $start 0 $largs
182
183	process_msgs $envlist
184
185	puts "\tRep$tnum.b: Set delayed sync on clients 2 and 3"
186	error_check_good set_delay [$dc1env rep_config {delayclient on}] 0
187	error_check_good set_delay [$dc2env rep_config {delayclient on}] 0
188
189	set oplist { "delayed" "syncing" }
190
191	set masterenv $env1
192	set mid 1
193	set mdir $env1dir
194	set clientenv $env2
195	set cid 2
196	set cdir $env2dir
197	foreach op $oplist {
198		# Swap all the info we need.
199		set tmp $masterenv
200		set masterenv $clientenv
201		set clientenv $tmp
202
203		set tmp $mdir
204		set mdir $cdir
205		set cdir $mdir
206
207		set tmp $mid
208		set mid $cid
209		set cid $tmp
210
211		puts "\tRep$tnum.c: Swap master/client ($op)"
212		error_check_good downgrade [$clientenv rep_start -client] 0
213		error_check_good upgrade [$masterenv rep_start -master] 0
214		process_msgs $envlist
215
216		#
217		# !!!
218		# At this point, clients 2 and 3 should have DELAY set.
219		# We should # probably add a field to rep_stat
220		# to indicate that and test that here..
221		#
222		puts "\tRep$tnum.d: Run rep_test in new master env"
223		set start [expr $start + $niter]
224		eval rep_test $method $env2 NULL $niter $start $start 0 $largs
225		process_msgs $envlist
226
227		#
228		# Delayed clients should be different.
229		# Former master should by synced.
230		#
231		rep_verify $mdir $masterenv $cdir $clientenv 0 1 1
232		rep_verify $mdir $masterenv $delaycldir1 $dc1env 0 0 0
233		rep_verify $mdir $masterenv $delaycldir2 $dc2env 0 0 0
234
235		#
236		# Run rep_test again, but don't process on former master.
237		# This makes the master/client different from each other.
238		#
239		puts "\tRep$tnum.e: Run rep_test in new master env only"
240		set start [expr $start + $niter]
241		eval rep_test \
242		    $method $masterenv NULL $niter $start $start 0 $largs
243		replclear $cid
244		replclear 3
245		replclear 4
246		replclear 5
247
248		puts "\tRep$tnum.f: Start 4th, clean delayed client."
249		set dc3env [eval $dc3_envcmd $recargs -rep_client]
250		error_check_good client4_env [is_valid_env $dc3env] TRUE
251		$dc3env rep_limit 0 0
252		error_check_good set_delay [$dc3env rep_config \
253		    {delayclient on}] 0
254		set envlist "{$env1 1} {$env2 2} {$dc1env 3} \
255		    {$dc2env 4} {$dc3env 5}"
256		process_msgs $envlist
257
258		#
259		# Now we have a master at point 1, a former master,
260		# now client at point 2, and two delayed clients at point 3.
261		# If 'delayed' swap masters now, while the clients are
262		# in the delayed state but not syncing yet.
263		# If 'syncing', first call rep_sync, and begin syncing the
264		# clients, then swap masters in the middle of that process.
265		#
266		set nextlet "g"
267		if { $op == "delayed" } {
268			# Swap all the info we need.
269			set tmp $masterenv
270			set masterenv $clientenv
271			set clientenv $tmp
272
273			set tmp $mdir
274			set mdir $cdir
275			set cdir $mdir
276
277			set tmp $mid
278			set mid $cid
279			set cid $tmp
280
281			puts "\tRep$tnum.g: Swap master/client while delayed"
282			set nextlet "h"
283			error_check_good downgrade \
284			    [$clientenv rep_start -client] 0
285			error_check_good upgrade \
286			    [$masterenv rep_start -master] 0
287			process_msgs $envlist
288		}
289		puts "\tRep$tnum.$nextlet: Run rep_test and sync delayed client"
290		set start [expr $start + $niter]
291		eval rep_test $method $masterenv NULL $niter $start $start 0 $largs
292		process_msgs $envlist
293		error_check_good rep_sync [$dc1env rep_sync] 0
294		error_check_good rep_sync [$dc3env rep_sync] 0
295		if { $op == "syncing" } {
296			#
297			# Process messages twice to get us into syncing,
298			# but not enough to complete it.  Then swap.
299			#
300			set nproced [proc_msgs_once $envlist NONE err]
301			set nproced [proc_msgs_once $envlist NONE err]
302
303			# Swap all the info we need.
304			set tmp $masterenv
305			set masterenv $clientenv
306			set clientenv $tmp
307
308			set tmp $mdir
309			set mdir $cdir
310			set cdir $mdir
311
312			set tmp $mid
313			set mid $cid
314			set cid $tmp
315
316			puts "\tRep$tnum.h: Swap master/client while syncing"
317			error_check_good downgrade \
318			    [$clientenv rep_start -client] 0
319			error_check_good upgrade \
320			    [$masterenv rep_start -master] 0
321		}
322		#
323		# Now process all messages and verify.
324		#
325		puts "\tRep$tnum.i: Process all messages and verify."
326		process_msgs $envlist
327
328		#
329		# If we swapped during the last syncing, we need to call
330		# rep_sync again because the master changed again.
331		#
332		if { $op == "syncing" } {
333			error_check_good rep_sync [$dc1env rep_sync] 0
334			error_check_good rep_sync [$dc3env rep_sync] 0
335			process_msgs $envlist
336		}
337
338		#
339		# Delayed client should be the same now.
340		#
341		rep_verify $mdir $masterenv $delaycldir1 $dc1env 0 1 1
342		rep_verify $mdir $masterenv $delaycldir3 $dc3env 0 1 1
343		rep_verify $mdir $masterenv $delaycldir2 $dc2env 0 0 0
344		error_check_good dc3_close [$dc3env close] 0
345		env_cleanup $delaycldir3
346		set envlist "{$env1 1} {$env2 2} {$dc1env 3} {$dc2env 4}"
347
348	}
349	puts "\tRep$tnum.j: Sync up 2nd delayed client and verify."
350	error_check_good rep_sync [$dc2env rep_sync] 0
351	process_msgs $envlist
352	rep_verify $mdir $masterenv $delaycldir2 $dc2env 0 1 1
353
354	puts "\tRep$tnum.k: Closing"
355	error_check_good env1_close [$env1 close] 0
356	error_check_good env2_close [$env2 close] 0
357	error_check_good dc1_close [$dc1env close] 0
358	error_check_good dc2_close [$dc2env close] 0
359	replclose $testdir/MSGQUEUEDIR
360	set testdir $orig_tdir
361	return
362}
363