1 # See the file LICENSE for redistribution information.
3 # Copyright (c) 2002, 2012 Oracle and/or its affiliates. All rights reserved.
8 # TEST Replication election test with varying required nvotes.
10 # TEST Run a modified version of test001 in a replicated master environment;
11 # TEST hold an election among a group of clients to make sure they select
12 # TEST the master with varying required participants.
14 proc rep016 { method args } {
16 global databases_in_memory
17 global repfiles_in_memory
22 # Skip for all methods except btree.
23 if { $checking_valid_methods } {
24 set test_methods { btree }
27 if { [is_btree $method] == 0 } {
28 puts "Rep$tnum: Skipping for method $method."
33 set logsets [create_logsets [expr $nclients + 1]]
35 # Set up for on-disk or in-memory databases.
36 set msg "using on-disk databases"
37 if { $databases_in_memory } {
38 set msg "using named in-memory databases"
39 if { [is_queueext $method] } {
40 puts -nonewline "Skipping rep$tnum for method "
41 puts "$method with named in-memory databases"
46 set msg2 "and on-disk replication files"
47 if { $repfiles_in_memory } {
48 set msg2 "and in-memory replication files"
51 # Run the body of the test with and without recovery.
52 foreach r $test_recopts {
54 set logindex [lsearch -exact $l "in-memory"]
55 if { $r == "-recover" && $logindex != -1 } {
56 puts "Rep$tnum: Skipping\
57 for in-memory logs with -recover."
60 puts "Rep$tnum ($method $r): Replication\
61 elections with varying nvotes $msg $msg2."
62 puts "Rep$tnum: Master logs are [lindex $l 0]"
63 for { set i 0 } { $i < $nclients } { incr i } {
64 puts "Rep$tnum: Client $i logs are\
65 [lindex $l [expr $i + 1]]"
67 rep016_sub $method $nclients $tnum $l $r $args
72 proc rep016_sub { method nclients tnum logset recargs largs } {
74 global databases_in_memory
75 global repfiles_in_memory
80 if { $rep_verbose == 1 } {
81 set verbargs " -verbose {$verbose_type on} "
85 if { $repfiles_in_memory } {
86 set repmemargs "-rep_inmem_files "
92 set qdir $testdir/MSGQUEUEDIR
95 set masterdir $testdir/MASTERDIR
98 set m_logtype [lindex $logset 0]
99 set m_logargs [adjust_logargs $m_logtype]
100 set m_txnargs [adjust_txnargs $m_logtype]
102 for { set i 0 } { $i < $nclients } { incr i } {
103 set clientdir($i) $testdir/CLIENTDIR.$i
104 file mkdir $clientdir($i)
105 set c_logtype($i) [lindex $logset [expr $i + 1]]
106 set c_logargs($i) [adjust_logargs $c_logtype($i)]
107 set c_txnargs($i) [adjust_txnargs $c_logtype($i)]
113 set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 \
115 -home $masterdir $m_txnargs $m_logargs -rep_master $verbargs \
116 -errpfx MASTER -rep_transport \[list 1 replsend\]"
117 set masterenv [eval $env_cmd(M) $recargs]
118 lappend envlist "$masterenv 1"
121 # Don't set -errfile now -- wait until the error catching
122 # portion of the test is complete.
123 for { set i 0 } { $i < $nclients } { incr i } {
124 set envid [expr $i + 2]
126 set env_cmd($i) "berkdb_env_noerr -create -home $clientdir($i) \
128 $c_txnargs($i) $c_logargs($i) -rep_client $verbargs \
129 -rep_transport \[list $envid replsend\]"
130 set clientenv($i) [eval $env_cmd($i) $recargs]
131 lappend envlist "$clientenv($i) $envid"
133 # Bring the clients online by processing the startup messages.
134 process_msgs $envlist
136 # Run a modified test001 in the master.
137 puts "\tRep$tnum.a: Running rep_test in replicated env."
138 eval rep_test $method $masterenv NULL $niter 0 0 0 $largs
139 process_msgs $envlist
141 # Check that databases are in-memory or on-disk as expected.
142 if { $databases_in_memory } {
143 set dbname { "" "test.db" }
147 check_db_location $masterenv
148 for { set i 0 } { $i < $nclients } { incr i } {
149 check_db_location $clientenv($i)
152 error_check_good masterenv_close [$masterenv close] 0
153 set envlist [lreplace $envlist 0 0]
155 puts "\tRep$tnum.b: Error values for rep_elect"
157 # Do all the error catching in client0. We do not need to call
158 # start_election here to fork a process because we never get
159 # far enough to send/receive any messages. We just want to
160 # check the error message.
163 # We cannot set -errpfx or -errfile or anything in the
164 # env_cmd above. Otherwise the correct output won't be set
165 # in 'ret' below and the test will fail.
167 # First check negative nvotes.
169 set nsites [expr $nclients + 1]
173 # Setting nsites to 0 acts as a signal for rep_elect to use
174 # the configured nsites, but since we haven't set that yet,
175 # this should still fail. TODO: need another test verifying
176 # the proper operation when we *have* configured nsites.
180 set res [catch {$clientenv(0) rep_elect $nsites $nvotes $priority \
182 error_check_bad catch $res 0
183 error_check_good ret [is_substr $ret "is larger than nsites"] 1
186 # Check nvotes > nsites.
189 set nvotes [expr $nsites + 1]
190 set res [catch {$clientenv(0) rep_elect $nsites $nvotes $priority \
192 error_check_bad catch $res 0
193 error_check_good ret [is_substr $ret "is larger than nsites"] 1
195 for { set i 0 } { $i < $nclients } { incr i } {
196 replclear [expr $i + 2]
198 # This test doesn't use the testing hooks, so
199 # initialize err_cmd and crash appropriately.
201 set err_cmd($i) "none"
204 # Initialize the array pri. We'll set it to
205 # appropriate values when the winner is determined.
209 if { $rep_verbose == 1 } {
210 $clientenv($i) errpfx CLIENT.$i
211 $clientenv($i) verbose $verbose_type on
212 $clientenv($i) errfile /dev/stderr
213 set env_cmd($i) [concat $env_cmd($i) \
214 "-errpfx CLIENT.$i -errfile /dev/stderr "]
218 puts "\t$m: Check single master/client can elect itself"
220 # 2 sites: 1 master, 1 client. Allow lone client to elect itself.
221 # Adjust client env list to reflect the single client.
223 set oldenvlist $envlist
224 set envlist [lreplace $envlist 1 end]
227 set orig_ncl $nclients
231 setpriority pri $nclients $winner
232 run_election envlist err_cmd pri crash\
233 $qdir $m $elector $nsites $nvotes $nclients $winner 1 $dbname
236 # Now run with all clients. Client0 should always get elected
237 # because it became master and should have a bigger LSN.
239 set nclients $orig_ncl
240 set envlist [lreplace $oldenvlist 0 0 [lindex $envlist 0]]
243 puts "\t$m: Elect with 100% client participation"
246 set winner [rep016_selectwinner $nsites $nvotes $nclients]
247 setpriority pri $nclients $winner
248 run_election envlist err_cmd pri crash\
249 $qdir $m $elector $nsites $nvotes $nclients $winner 1 $dbname
252 # Elect with varying levels of participation. Start with nsites
253 # as nclients+1 (simulating a down master) and require nclients,
254 # and fewer (by 1) until we get down to 2 clients.
257 puts "\t$m: Elect with varying participation"
258 set nsites [expr $nclients + 1]
260 for {set n $nclients} {$n > 1} {incr n -1} {
261 set m "Rep$tnum.e.$count"
262 set winner [rep016_selectwinner $nsites $n $n]
263 setpriority pri $nclients $winner
264 run_election envlist err_cmd pri crash\
265 $qdir $m $elector $nsites $n $n $winner 1 $dbname
269 foreach pair $envlist {
270 set cenv [lindex $pair 0]
271 error_check_good cenv_close [$cenv close] 0
273 replclose $testdir/MSGQUEUEDIR
276 proc rep016_selectwinner { nsites nvotes nclients } {
278 # Special case: When we test with 100% participation, we expect
279 # client 0 to always win because it has a bigger LSN than the
280 # rest due to earlier part of the test. This special case is
283 if { $nsites != $nvotes } {
284 set win [berkdb random_int 0 [expr $nclients - 1]]