1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2001,2008 Oracle.  All rights reserved.
4#
5# $Id: rep053.tcl,v 12.22 2008/04/03 17:27:51 carol Exp $
6#
7# TEST	rep053
8# TEST	Replication and basic client-to-client synchronization.
9# TEST
10# TEST	Open and start up master and 1 client.
11# TEST	Start up a second client later and verify it sync'ed from
12# TEST	the original client, not the master.
13#
14proc rep053 { method { niter 200 } { tnum "053" } args } {
15	source ./include.tcl
16
17	if { $is_windows9x_test == 1 } {
18		puts "Skipping replication test on Win 9x platform."
19		return
20	}
21
22	# Valid for all access methods.
23	if { $checking_valid_methods } {
24		return "ALL"
25	}
26
27	set args [convert_args $method $args]
28	set logsets [create_logsets 3]
29
30	# Run the body of the test with and without recovery,
31	# and with and without cleaning.  Skip recovery with in-memory
32	# logging - it doesn't make sense.
33	set throttle { "throttle" "" }
34	foreach r $test_recopts {
35		foreach t $throttle {
36			foreach l $logsets {
37				set logindex [lsearch -exact $l "in-memory"]
38				if { $r == "-recover" && $logindex != -1 } {
39					puts "Skipping rep$tnum for -recover\
40					    with in-memory logs."
41					continue
42				}
43				puts "Rep$tnum ($method $r $t):\
44				    Replication and client-to-client sync up."
45				puts "Rep$tnum: Master logs are [lindex $l 0]"
46				puts "Rep$tnum: Client logs are [lindex $l 1]"
47				puts "Rep$tnum: Client2 logs are [lindex $l 2]"
48				rep053_sub $method $niter $tnum $l $r $t $args
49			}
50		}
51	}
52}
53
54proc rep053_sub { method niter tnum logset recargs throttle largs } {
55	global anywhere
56	global testdir
57	global util_path
58	global rep_verbose
59	global verbose_type
60
61	set verbargs ""
62	if { $rep_verbose == 1 } {
63		set verbargs " -verbose {$verbose_type on} "
64	}
65
66	env_cleanup $testdir
67	set orig_tdir $testdir
68
69	replsetup $testdir/MSGQUEUEDIR
70
71	set masterdir $testdir/MASTERDIR
72	set clientdir $testdir/CLIENTDIR
73	set delaycldir1 $testdir/DELAYCLDIR.1
74	file mkdir $masterdir
75	file mkdir $clientdir
76	file mkdir $delaycldir1
77
78	set m_logtype [lindex $logset 0]
79	set c_logtype [lindex $logset 1]
80	set c2_logtype [lindex $logset 2]
81
82	# In-memory logs cannot be used with -txn nosync.
83	set m_logargs [adjust_logargs $m_logtype]
84	set c_logargs [adjust_logargs $c_logtype]
85	set c2_logargs [adjust_logargs $c2_logtype]
86	set m_txnargs [adjust_txnargs $m_logtype]
87	set c_txnargs [adjust_txnargs $c_logtype]
88	set c2_txnargs [adjust_txnargs $c2_logtype]
89
90	# Open a master.
91	repladd 1
92	set ma_envcmd "berkdb_env_noerr -create $m_txnargs \
93	    $m_logargs -errpfx MASTER $verbargs \
94	    -home $masterdir -rep_transport \[list 1 replsend\]"
95	set masterenv [eval $ma_envcmd $recargs -rep_master]
96
97	# Open two clients
98	repladd 2
99	set cl_envcmd "berkdb_env_noerr -create $c_txnargs \
100	    $c_logargs -errpfx CLIENT $verbargs \
101	    -home $clientdir -rep_transport \[list 2 replsend\]"
102	set clientenv [eval $cl_envcmd $recargs -rep_client]
103
104	# If throttling is specified, turn it on here.  Throttle the
105	# client, since this is a test of client-to-client sync-up.
106	if { $throttle == "throttle" } {
107		error_check_good \
108		    throttle [$clientenv rep_limit 0 [expr 8 * 1024]] 0
109	}
110
111	#
112	# Set up delayed client command, but don't eval until later.
113	# !!! Do NOT put the 'repladd' call here because we don't
114	# want this client to already have the backlog of records
115	# when it starts.
116	#
117	set dc1_envcmd "berkdb_env_noerr -create $c2_txnargs \
118	    $c2_logargs -errpfx DELAYCL $verbargs \
119	    -home $delaycldir1 -rep_transport \[list 3 replsend\]"
120
121	# Bring the client online by processing the startup messages.
122	set envlist "{$masterenv 1} {$clientenv 2}"
123	process_msgs $envlist
124
125	puts "\tRep$tnum.a: Run rep_test in master env."
126	set start 0
127	eval rep_test $method $masterenv NULL $niter $start $start 0 0 $largs
128	incr start $niter
129	process_msgs $envlist
130
131	puts "\tRep$tnum.b: Start new client."
132	set anywhere 1
133	repladd 3
134	set newclient [eval $dc1_envcmd $recargs -rep_client]
135	error_check_good client2_env [is_valid_env $newclient] TRUE
136
137	set envlist "{$masterenv 1} {$clientenv 2} {$newclient 3}"
138	process_msgs $envlist
139
140	puts "\tRep$tnum.c: Verify sync-up from client."
141	set req [stat_field $clientenv rep_stat "Client service requests"]
142	set miss [stat_field $clientenv rep_stat "Client service req misses"]
143	set rereq [stat_field $newclient rep_stat "Client rerequests"]
144
145	# To complete the internal init, we need a PAGE_REQ and a LOG_REQ.  These
146	# requests get served by $clientenv.  Since the end-of-range specified
147	# in the LOG_REQ points to the very end of the log (i.e., the LSN given
148	# in the NEWMASTER message), the serving client gets NOTFOUND in its log
149	# cursor reading loop, and can't tell whether it simply hit the end, or
150	# is really missing sufficient log records to fulfill the request.  So
151	# it counts a "miss" and generates a rerequest.  When internal init
152	# finishes recovery, it sends an ALL_REQ, for a total of 3 requests in
153	# the simple case, and more than 3 in the "throttle" case.
154	#
155
156	set expected_msgs 3
157	if { [is_queue $method] } {
158		# Queue database require an extra request
159		# to retrieve the meta page.
160		incr expected_msgs
161	}
162
163	if { $throttle == "throttle" } {
164		error_check_good req [expr $req > $expected_msgs] 1
165	} else {
166		error_check_good min_req [expr $req >= $expected_msgs] 1
167		set max_expected_msgs [expr $expected_msgs * 2]
168		error_check_good max_req [expr $req <= $max_expected_msgs] 1
169	}
170	error_check_good miss=rereq $miss $rereq
171
172	# Check for throttling.
173	if { $throttle == "throttle" } {
174		set num_throttles \
175		    [stat_field $clientenv rep_stat "Transmission limited"]
176		error_check_bad client_throttling $num_throttles 0
177	}
178
179	rep_verify $masterdir $masterenv $clientdir $clientenv
180	# Process messages again in case we are running with debug_rop.
181	process_msgs $envlist
182	rep_verify $masterdir $masterenv $delaycldir1 $newclient
183
184	puts "\tRep$tnum.d: Run rep_test more in master env and verify."
185	set niter 10
186	eval rep_test $method $masterenv NULL $niter $start $start 0 0 $largs
187	incr start $niter
188	process_msgs $envlist
189	rep_verify $masterdir $masterenv $clientdir $clientenv
190	process_msgs $envlist
191	rep_verify $masterdir $masterenv $delaycldir1 $newclient
192
193	puts "\tRep$tnum.e: Closing"
194	error_check_good master_close [$masterenv close] 0
195	error_check_good client_close [$clientenv close] 0
196	error_check_good dc1_close [$newclient close] 0
197	replclose $testdir/MSGQUEUEDIR
198	set testdir $orig_tdir
199	set anywhere 0
200	return
201}
202