summaryrefslogtreecommitdiff
path: root/db/test/rep053.tcl
blob: 578e445e007792942fc8f2e2e9c1ff2dd3172af2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2001,2007 Oracle.  All rights reserved.
#
# $Id: rep053.tcl,v 12.19 2007/05/17 19:33:06 bostic Exp $
#
# TEST	rep053
# TEST	Replication and basic client-to-client synchronization.
# TEST
# TEST	Open and start up master and 1 client.
# TEST	Start up a second client later and verify it sync'ed from
# TEST	the original client, not the master.
#
proc rep053 { method { niter 200 } { tnum "053" } args } {
	source ./include.tcl

	if { $is_windows9x_test == 1 } {
		puts "Skipping replication test on Win 9x platform."
		return
	}

	# Valid for all access methods.
	if { $checking_valid_methods } {
		return "ALL"
	}

	set args [convert_args $method $args]
	set logsets [create_logsets 3]

	# Run the body of the test with and without recovery,
	# and with and without cleaning.  Skip recovery with in-memory
	# logging - it doesn't make sense.
	set throttle { "throttle" "" }
	foreach r $test_recopts {
		foreach t $throttle {
			foreach l $logsets {
				set logindex [lsearch -exact $l "in-memory"]
				if { $r == "-recover" && $logindex != -1 } {
					puts "Skipping rep$tnum for -recover\
					    with in-memory logs."
					continue
				}
				puts "Rep$tnum ($method $r $t):\
				    Replication and client-to-client sync up."
				puts "Rep$tnum: Master logs are [lindex $l 0]"
				puts "Rep$tnum: Client logs are [lindex $l 1]"
				puts "Rep$tnum: Client2 logs are [lindex $l 2]"
				rep053_sub $method $niter $tnum $l $r $t $args
			}
		}
	}
}

proc rep053_sub { method niter tnum logset recargs throttle largs } {
	global anywhere
	global testdir
	global util_path
	global rep_verbose

	set verbargs ""
	if { $rep_verbose == 1 } {
		set verbargs " -verbose {rep on} "
	}

	env_cleanup $testdir
	set orig_tdir $testdir

	replsetup $testdir/MSGQUEUEDIR

	set masterdir $testdir/MASTERDIR
	set clientdir $testdir/CLIENTDIR
	set delaycldir1 $testdir/DELAYCLDIR.1
	file mkdir $masterdir
	file mkdir $clientdir
	file mkdir $delaycldir1

	set m_logtype [lindex $logset 0]
	set c_logtype [lindex $logset 1]
	set c2_logtype [lindex $logset 2]

	# In-memory logs cannot be used with -txn nosync.
	set m_logargs [adjust_logargs $m_logtype]
	set c_logargs [adjust_logargs $c_logtype]
	set c2_logargs [adjust_logargs $c2_logtype]
	set m_txnargs [adjust_txnargs $m_logtype]
	set c_txnargs [adjust_txnargs $c_logtype]
	set c2_txnargs [adjust_txnargs $c2_logtype]

	# Open a master.
	repladd 1
	set ma_envcmd "berkdb_env_noerr -create $m_txnargs \
	    $m_logargs -errpfx MASTER $verbargs \
	    -home $masterdir -rep_transport \[list 1 replsend\]"
	set masterenv [eval $ma_envcmd $recargs -rep_master]

	# Open two clients
	repladd 2
	set cl_envcmd "berkdb_env_noerr -create $c_txnargs \
	    $c_logargs -errpfx CLIENT $verbargs \
	    -home $clientdir -rep_transport \[list 2 replsend\]"
	set clientenv [eval $cl_envcmd $recargs -rep_client]

	# If throttling is specified, turn it on here.  Throttle the
	# client, since this is a test of client-to-client sync-up.
	if { $throttle == "throttle" } {
		error_check_good \
		    throttle [$clientenv rep_limit 0 [expr 8 * 1024]] 0
	}

	#
	# Set up delayed client command, but don't eval until later.
	# !!! Do NOT put the 'repladd' call here because we don't
	# want this client to already have the backlog of records
	# when it starts.
	#
	set dc1_envcmd "berkdb_env_noerr -create $c2_txnargs \
	    $c2_logargs -errpfx DELAYCL $verbargs \
	    -home $delaycldir1 -rep_transport \[list 3 replsend\]"

	# Bring the client online by processing the startup messages.
	set envlist "{$masterenv 1} {$clientenv 2}"
	process_msgs $envlist

	puts "\tRep$tnum.a: Run rep_test in master env."
	set start 0
	eval rep_test $method $masterenv NULL $niter $start $start 0 0 $largs
	incr start $niter
	process_msgs $envlist

	puts "\tRep$tnum.b: Start new client."
	set anywhere 1
	repladd 3
	set newclient [eval $dc1_envcmd $recargs -rep_client]
	error_check_good client2_env [is_valid_env $newclient] TRUE

	set envlist "{$masterenv 1} {$clientenv 2} {$newclient 3}"
	process_msgs $envlist

	puts "\tRep$tnum.c: Verify sync-up from client."
	set req [stat_field $clientenv rep_stat "Client service requests"]
	set miss [stat_field $clientenv rep_stat "Client service req misses"]
	set rereq [stat_field $newclient rep_stat "Client rerequests"]

	# To complete the internal init, we need a PAGE_REQ and a LOG_REQ.  These
	# requests get served by $clientenv.  Since the end-of-range specified
	# in the LOG_REQ points to the very end of the log (i.e., the LSN given
	# in the NEWMASTER message), the serving client gets NOTFOUND in its log
	# cursor reading loop, and can't tell whether it simply hit the end, or
	# is really missing sufficient log records to fulfill the request.  So
	# it counts a "miss" and generates a rerequest.  When internal init
	# finishes recovery, it sends an ALL_REQ, for a total of 3 requests in
	# the simple case, and more than 3 in the "throttle" case.
	#

	set expected_msgs 3
	if { [is_queue $method] } {
		# Queue database require an extra request
		# to retrieve the meta page.
		incr expected_msgs
	}

	if { $throttle == "throttle" } {
		error_check_good req [expr $req > $expected_msgs] 1
	} else {
		error_check_good req $req $expected_msgs
	}
	error_check_good miss $miss 1
	error_check_good rereq $rereq 1

	# Check for throttling.
	if { $throttle == "throttle" } {
		set num_throttles \
		    [stat_field $clientenv rep_stat "Transmission limited"]
		error_check_bad client_throttling $num_throttles 0
	}

	rep_verify $masterdir $masterenv $clientdir $clientenv
	# Process messages again in case we are running with debug_rop.
	process_msgs $envlist
	rep_verify $masterdir $masterenv $delaycldir1 $newclient

	puts "\tRep$tnum.d: Run rep_test more in master env and verify."
	set niter 10
	eval rep_test $method $masterenv NULL $niter $start $start 0 0 $largs
	incr start $niter
	process_msgs $envlist
	rep_verify $masterdir $masterenv $clientdir $clientenv
	process_msgs $envlist
	rep_verify $masterdir $masterenv $delaycldir1 $newclient

	puts "\tRep$tnum.e: Closing"
	error_check_good master_close [$masterenv close] 0
	error_check_good client_close [$clientenv close] 0
	error_check_good dc1_close [$newclient close] 0
	replclose $testdir/MSGQUEUEDIR
	set testdir $orig_tdir
	set anywhere 0
	return
}