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