1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2004-2009 Oracle. All rights reserved. 4# 5# $Id$ 6# 7# TEST rep069 8# TEST Test of internal initialization and elections. 9# TEST 10# TEST If a client is in a recovery mode of any kind, it 11# TEST participates in elections at priority 0 so it can 12# TEST never be elected master. 13# 14proc rep069 { method { niter 200 } { tnum "069" } args } { 15 16 source ./include.tcl 17 global databases_in_memory 18 global repfiles_in_memory 19 20 if { $is_windows9x_test == 1 } { 21 puts "Skipping replication test on Win 9x platform." 22 return 23 } 24 if { $checking_valid_methods } { 25 set test_methods { btree } 26 return $test_methods 27 } 28 if { [is_btree $method] == 0 } { 29 puts "Rep$tnum: Skipping for method $method." 30 return 31 } 32 33 set args [convert_args $method $args] 34 set saved_args $args 35 36 set logsets [create_logsets 2] 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 foreach l $logsets { 55 set args $saved_args 56 puts "Rep$tnum ($method $args): Test internal\ 57 initialization and elections $msg $msg2." 58 puts "Rep$tnum: Master logs are [lindex $l 0]" 59 puts "Rep$tnum: Client logs are [lindex $l 1]" 60 rep069_sub $method $niter $tnum $l $args 61 } 62} 63 64proc rep069_sub { method niter tnum logset largs } { 65 global testdir 66 global util_path 67 global databases_in_memory 68 global repfiles_in_memory 69 global rep_verbose 70 global verbose_type 71 global timeout_ok 72 73 env_cleanup $testdir 74 75 set qdir $testdir/MSGQUEUEDIR 76 replsetup $qdir 77 78 set verbargs "" 79 if { $rep_verbose == 1 } { 80 set verbargs " -verbose {$verbose_type on} " 81 } 82 83 set repmemargs "" 84 if { $repfiles_in_memory } { 85 set repmemargs "-rep_inmem_files " 86 } 87 88 set masterdir $testdir/MASTERDIR 89 file mkdir $masterdir 90 91 set nclients 2 92 for { set i 0 } { $i < $nclients } { incr i } { 93 set clientdir($i) $testdir/CLIENTDIR.$i 94 file mkdir $clientdir($i) 95 } 96 97 # Log size is small so we quickly create more than one, and 98 # can easily force internal initialization. 99 set pagesize 4096 100 append largs " -pagesize $pagesize " 101 set log_max [expr $pagesize * 8] 102 103 set m_logtype [lindex $logset 0] 104 set c_logtype [lindex $logset 1] 105 106 # In-memory logs cannot be used with -txn nosync. 107 set m_logargs [adjust_logargs $m_logtype] 108 set c_logargs [adjust_logargs $c_logtype] 109 set m_txnargs [adjust_txnargs $m_logtype] 110 set c_txnargs [adjust_txnargs $c_logtype] 111 112 # Open a master. 113 set envlist {} 114 repladd 1 115 set ma_envcmd "berkdb_env_noerr -create $m_txnargs \ 116 $repmemargs \ 117 $m_logargs -log_max $log_max -event rep_event $verbargs \ 118 -home $masterdir -rep_transport \[list 1 replsend\]" 119 set masterenv [eval $ma_envcmd -recover -rep_master] 120 lappend envlist "$masterenv 1" 121 122 # Open clients. 123 for { set i 0 } { $i < $nclients } { incr i } { 124 set envid [expr $i + 2] 125 repladd $envid 126 set envcmd($i) "berkdb_env_noerr -create \ 127 $repmemargs \ 128 $c_txnargs $c_logargs -log_max $log_max \ 129 -home $clientdir($i) -event rep_event $verbargs \ 130 -rep_transport \[list $envid replsend\]" 131 set clientenv($i) [eval $envcmd($i) -recover -rep_client] 132 lappend envlist "$clientenv($i) $envid" 133 } 134 135 # Bring the clients online by processing the startup messages. 136 process_msgs $envlist 137 138 # Clobber replication's 30-second anti-archive timer, which will have 139 # been started by client sync-up internal init, so that we can do a 140 # db_archive in a moment. 141 # 142 $masterenv test force noarchive_timeout 143 144 # Run rep_test in the master and update clients. 145 puts "\tRep$tnum.a: Running rep_test in replicated env." 146 set start 0 147 eval rep_test \ 148 $method $masterenv NULL $niter $start $start 0 $largs 149 incr start $niter 150 process_msgs $envlist 0 NONE err 151 error_check_good process_msgs $err 0 152 153 # Find out what exists on the client. We need to loop until 154 # the first master log file > last client log file. The two 155 # clients should be the same, so just inspect one. 156 puts "\tRep$tnum.b: Close clients." 157 if { $c_logtype != "in-memory" } { 158 set res [eval exec $util_path/db_archive -l -h $clientdir(0)] 159 set res [eval exec $util_path/db_archive -l -h $clientdir(1)] 160 } 161 set last_client_log [get_logfile $clientenv(1) last] 162 for { set i 0 } { $i < $nclients } { incr i } { 163 error_check_good client_close [$clientenv($i) close] 0 164 } 165 set envlist [lreplace $envlist 1 2] 166 167 # Run the master forward. 168 set stop 0 169 while { $stop == 0 } { 170 puts "\tRep$tnum.c: Running rep_test in replicated env." 171 eval rep_test \ 172 $method $masterenv NULL $niter $start $start 0 $largs 173 incr start $niter 174 175 puts "\tRep$tnum.d: Run db_archive on master." 176 if { $m_logtype != "in-memory"} { 177 set res [eval \ 178 exec $util_path/db_archive -d -h $masterdir] 179 } 180 set first_master_log [get_logfile $masterenv first] 181 if { $first_master_log > $last_client_log } { 182 set stop 1 183 } 184 } 185 186 for { set i 0 } { $i < $nclients } { incr i } { 187 set envid [expr $i + 2] 188 replclear $envid 189 } 190 191 # Reopen clients. 192 puts "\tRep$tnum.e: Reopen clients." 193 for { set i 0 } { $i < $nclients } { incr i } { 194 env_cleanup $clientdir($i) 195 set clientenv($i) [eval $envcmd($i) -recover -rep_client] 196 set envid [expr $i + 2] 197 lappend envlist "$clientenv($i) $envid" 198 } 199 200 # Run proc_msgs_once until both clients are in internal 201 # initialization. 202 # 203 # We figure out whether each client is in initialization 204 # by searching for any of the flags REP_F_RECOVER_UPDATE, 205 # REP_F_RECOVER_PAGE, and REP_F_RECOVER_LOG. As soon as 206 # a client produces one of these, it's marked as being 207 # in initialization, and stays that way even if it proceeds 208 # further, but we don't exit the loop until all clients 209 # have gotten into initialization. 210 # 211 puts "\tRep$tnum.f:\ 212 Run proc_msgs_once until all clients enter internal init." 213 set in_init 0 214 for { set i 0 } { $i < $nclients } { incr i } { 215 set initializing($i) 0 216 } 217 218 while { $in_init != 1 } { 219 set nproced [proc_msgs_once $envlist NONE err] 220 for { set i 0 } { $i < $nclients } { incr i } { 221 set stat($i) \ 222 [exec $util_path/db_stat -r -R A -h $clientdir(1)] 223 if {[is_substr $stat($i) "REP_F_RECOVER_UPDATE"] } { 224 set initializing($i) 1 225 } 226 if {[is_substr $stat($i) "REP_F_RECOVER_PAGE"] } { 227 set initializing($i) 1 228 } 229 if {[is_substr $stat($i) "REP_F_RECOVER_LOG"] } { 230 set initializing($i) 1 231 } 232 } 233 set in_init 1 234 for { set i 0 } { $i < $nclients } { incr i } { 235 if { $initializing($i) == 0 } { 236 set in_init 0 237 } 238 } 239 } 240 241 # Call an election. It should fail, because both clients 242 # are in internal initialization and therefore not electable. 243 # Indicate failure with winner = -2. 244 # First, close the master. 245 error_check_good masterenv_close [$masterenv close] 0 246 set envlist [lreplace $envlist 0 0] 247 248 puts "\tRep$tnum.g: Run election; no one will get elected." 249 set m "Rep$tnum.g" 250 set nsites $nclients 251 set nvotes $nclients 252 set winner -2 253 set elector 0 254 for { set i 0 } { $i < $nclients } { incr i } { 255 set err_cmd($i) "none" 256 set crash($i) 0 257 set pri($i) 10 258 } 259 260 # This election will time out instead of succeeding. 261 set timeout_ok 1 262 if { $databases_in_memory } { 263 set dbname { "" "test.db" } 264 } else { 265 set dbname "test.db" 266 } 267 run_election envcmd envlist err_cmd pri crash \ 268 $qdir $m $elector $nsites $nvotes $nclients $winner \ 269 0 $dbname 0 $timeout_ok 270 271 # Verify that each client saw the message that no 272 # electable site was found. 273 puts "\tRep$tnum.h: Check for right error message." 274 for { set i 0 } { $i < $nclients } { incr i } { 275 set none_electable 0 276 set id [expr $i + 1] 277 set fd [open $testdir/ELECTION_RESULT.$id r] 278 while { [gets $fd str] != -1 } { 279 if { [is_substr $str "Unable to elect a master"] == 1 } { 280 set none_electable 1 281 break 282 } 283 } 284 close $fd 285 error_check_good none_electable $none_electable 1 286 } 287 288 # Clean up for the next pass. 289 for { set i 0 } { $i < $nclients } { incr i } { 290 $clientenv($i) close 291 } 292 293 replclose $testdir/MSGQUEUEDIR 294} 295 296