1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2004-2009 Oracle. All rights reserved. 4# 5# $Id$ 6# 7# TEST rep020 8# TEST Replication elections - test election generation numbers. 9# TEST 10 11proc rep020 { method args } { 12 global rand_init 13 global databases_in_memory 14 global repfiles_in_memory 15 16 source ./include.tcl 17 if { $is_windows9x_test == 1 } { 18 puts "Skipping replication test on Win 9x platform." 19 return 20 } 21 set tnum "020" 22 23 # Run for btree only. 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 error_check_good set_random_seed [berkdb srand $rand_init] 0 34 set nclients 5 35 set logsets [create_logsets [expr $nclients + 1]] 36 37 # Set up for on-disk or in-memory databases. 38 set msg "using on-disk databases" 39 if { $databases_in_memory } { 40 set msg "using named in-memory databases" 41 if { [is_queueext $method] } { 42 puts -nonewline "Skipping rep$tnum for method " 43 puts "$method with named in-memory databases" 44 return 45 } 46 } 47 48 set msg2 "and on-disk replication files" 49 if { $repfiles_in_memory } { 50 set msg2 "and in-memory replication files" 51 } 52 53 foreach l $logsets { 54 puts "Rep$tnum ($method): Election generation test $msg $msg2." 55 puts "Rep$tnum: Master logs are [lindex $l 0]" 56 for { set i 0 } { $i < $nclients } { incr i } { 57 puts "Rep$tnum: Client $i logs are\ 58 [lindex $l [expr $i + 1]]" 59 } 60 rep020_sub $method $nclients $tnum $l $args 61 } 62} 63 64proc rep020_sub { method nclients tnum logset largs } { 65 source ./include.tcl 66 global errorInfo 67 global databases_in_memory 68 global mixed_mode_logging 69 global repfiles_in_memory 70 global rep_verbose 71 global verbose_type 72 73 set verbargs "" 74 if { $rep_verbose == 1 } { 75 set verbargs " -verbose {$verbose_type on} " 76 } 77 78 set repmemargs "" 79 if { $repfiles_in_memory } { 80 set repmemargs "-rep_inmem_files " 81 } 82 83 env_cleanup $testdir 84 85 set qdir $testdir/MSGQUEUEDIR 86 replsetup $qdir 87 88 set masterdir $testdir/MASTERDIR 89 file mkdir $masterdir 90 set m_logtype [lindex $logset 0] 91 set m_logargs [adjust_logargs $m_logtype] 92 set m_txnargs [adjust_txnargs $m_logtype] 93 94 for { set i 0 } { $i < $nclients } { incr i } { 95 set clientdir($i) $testdir/CLIENTDIR.$i 96 file mkdir $clientdir($i) 97 set c_logtype($i) [lindex $logset [expr $i + 1]] 98 set c_logargs($i) [adjust_logargs $c_logtype($i)] 99 set c_txnargs($i) [adjust_txnargs $c_logtype($i)] 100 } 101 102 # Open a master. 103 set envlist {} 104 repladd 1 105 set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 $verbargs \ 106 -event rep_event $repmemargs \ 107 -home $masterdir $m_txnargs $m_logargs -rep_master \ 108 -errpfx MASTER -rep_transport \[list 1 replsend\]" 109 set masterenv [eval $env_cmd(M)] 110 lappend envlist "$masterenv 1" 111 112 # Open the clients. 113 for { set i 0 } { $i < $nclients } { incr i } { 114 set envid [expr $i + 2] 115 repladd $envid 116 set env_cmd($i) "berkdb_env_noerr -create -event rep_event \ 117 $verbargs -home $clientdir($i) $repmemargs \ 118 $c_txnargs($i) $c_logargs($i) \ 119 -rep_client -rep_transport \[list $envid replsend\]" 120 set clientenv($i) [eval $env_cmd($i)] 121 lappend envlist "$clientenv($i) $envid" 122 } 123 124 # Run a modified test001 in the master. 125 process_msgs $envlist 126 puts "\tRep$tnum.a: Running rep_test in replicated env." 127 set niter 10 128 eval rep_test $method $masterenv NULL $niter 0 0 0 $largs 129 process_msgs $envlist 130 131 # Check that databases are in-memory or on-disk as expected. 132 if { $databases_in_memory } { 133 set dbname { "" "test.db" } 134 } else { 135 set dbname "test.db" 136 } 137 check_db_location $masterenv 138 for { set i 0 } { $i < $nclients } { incr i } { 139 check_db_location $clientenv($i) 140 } 141 142 # Close master. 143 error_check_good masterenv_close [$masterenv close] 0 144 set envlist [lreplace $envlist 0 0] 145 146 foreach pair $envlist { 147 set i [expr [lindex $pair 1] - 2] 148 replclear [expr $i + 2] 149 set err_cmd($i) "none" 150 set pri($i) 10 151 set crash($i) 0 152 if { $rep_verbose == 1 } { 153 $clientenv($i) errpfx CLIENT$i 154 $clientenv($i) verbose $verbose_type on 155 $clientenv($i) errfile /dev/stderr 156 set env_cmd($i) [concat $env_cmd($i) \ 157 "-errpfx CLIENT$i -errfile /dev/stderr"] 158 } 159 } 160 161 set msg "Rep$tnum.b" 162 puts "\t$msg: Run elections to increment egen." 163 164 set nelect 2 165 set nsites $nclients 166 set nvotes $nclients 167 for { set j 0 } { $j < $nelect } { incr j } { 168 # Pick winner and elector randomly. 169 set winner [berkdb random_int 0 [expr $nclients - 1]] 170 setpriority pri $nclients $winner 171 set elector [berkdb random_int 0 [expr $nclients - 1]] 172 run_election env_cmd envlist err_cmd pri crash $qdir \ 173 $msg $elector $nsites $nvotes $nclients $winner 1 $dbname 174 } 175 process_msgs $envlist 176 177 set msg "Rep$tnum.c" 178 puts "\t$msg: Updating egen when getting an old vote." 179 180 # 181 # Find the last client and save the election generation number. 182 # Close the last client and adjust the list of envs to process. 183 # 184 set i [expr $nclients - 1] 185 set last [lindex $envlist end] 186 set clientenv($i) [lindex $last 0] 187 set egen($i) \ 188 [stat_field $clientenv($i) rep_stat "Election generation number"] 189 error_check_good clientenv_close($i) [$clientenv($i) close] 0 190 set envlist [lreplace $envlist end end] 191 192 # Run a few more elections while the last client is closed. 193 # Make sure we don't pick the closed client as the winner, 194 # and require votes from one fewer site. 195 # 196 set orig_nvotes $nvotes 197 set orig_nclients $nclients 198 set nvotes [expr $orig_nvotes - 1] 199 set nclients [expr $orig_nclients - 1] 200 for { set j 0 } { $j < $nelect } { incr j } { 201 set winner [berkdb random_int 0 [expr $nclients - 1]] 202 setpriority pri $nclients $winner 203 set elector [berkdb random_int 0 [expr $nclients - 1]] 204 run_election env_cmd envlist err_cmd pri crash $qdir \ 205 $msg $elector $nsites $nvotes $nclients $winner 1 $dbname 206 } 207 process_msgs $envlist 208 # 209 # Verify that the last client's election generation number has 210 # changed, and that it matches the other clients. 211 # 212 set pair [lindex $envlist 0] 213 set clenv [lindex $pair 0] 214 set clegen [stat_field \ 215 $clenv rep_stat "Election generation number"] 216 217 # Reopen last client's env. Do not run recovery, but do 218 # process messages to get the egen updated. 219 replclear $envid 220 set clientenv($i) [eval $env_cmd($i)] 221 lappend envlist "$clientenv($i) $envid" 222 error_check_good client_reopen [is_valid_env $clientenv($i)] TRUE 223 process_msgs $envlist 224 225 set newegen($i) \ 226 [stat_field $clientenv($i) rep_stat "Election generation number"] 227 error_check_bad egen_changed $newegen($i) $egen($i) 228 error_check_good egen_changed1 $newegen($i) $clegen 229 230 set msg "Rep$tnum.d" 231 puts "\t$msg: New client starts election." 232 # 233 # Run another election, this time called by the last client. 234 # This should succeed because the last client has already 235 # caught up to the others for egen. 236 # 237 set winner 2 238 set nvotes $orig_nvotes 239 set nclients $orig_nclients 240 set elector [expr $nclients - 1] 241 setpriority pri $nclients $winner 242 run_election env_cmd envlist err_cmd pri crash $qdir \ 243 $msg $elector $nsites $nvotes $nclients $winner 0 $dbname 244 245 set newegen($i) \ 246 [stat_field $clientenv($i) rep_stat "Election generation number"] 247 foreach pair $envlist { 248 set i [expr [lindex $pair 1] - 2] 249 set clientenv($i) [lindex $pair 0] 250 set egen($i) [stat_field \ 251 $clientenv($i) rep_stat "Election generation number"] 252 } 253 error_check_good egen_catchup $egen(4) $egen(3) 254 255 # Skip this part of the test for mixed-mode logging, 256 # since we can't recover with in-memory logs. 257 if { $mixed_mode_logging == 0 } { 258 set msg "Rep$tnum.e" 259 puts "\t$msg: Election generation set as expected after recovery." 260 # Note all client egens. Close, recover, process messages, 261 # and check that egens are unchanged. 262 set big_e [big_endian] 263 foreach pair $envlist { 264 set i [expr [lindex $pair 1] - 2] 265 set clientenv($i) [lindex $pair 0] 266 # Can only get egen file if repfiles on-disk. 267 if { $repfiles_in_memory == 0 } { 268 set fid [open $clientdir($i)/__db.rep.egen r] 269 fconfigure $fid -translation binary 270 set data [read $fid 4] 271 if { $big_e } { 272 binary scan $data I egen($i) 273 } else { 274 binary scan $data i egen($i) 275 } 276 binary scan $data c val 277 close $fid 278 } 279 $clientenv($i) log_flush 280 error_check_good \ 281 clientenv_close($i) [$clientenv($i) close] 0 282 set clientenv($i) [eval $env_cmd($i) -recover] 283 set envlist [lreplace \ 284 $envlist $i $i "$clientenv($i) [expr $i + 2]"] 285 } 286 process_msgs $envlist 287 foreach pair $envlist { 288 set i [expr [lindex $pair 1] - 2] 289 set newegen($i) [stat_field $clientenv($i) \ 290 rep_stat "Election generation number"] 291 if { $repfiles_in_memory == 0 } { 292 error_check_good egen_recovery $egen($i) \ 293 $newegen($i) 294 } else { 295 # For rep in-memory, egen expected to start 296 # over at 1 after close/reopen environment. 297 error_check_good egen_recovery $newegen($i) 1 298 } 299 } 300 301 # Run an election. Now the egens should go forward. 302 set winner [berkdb random_int 0 [expr $nclients - 1]] 303 setpriority pri $nclients $winner 304 set elector [berkdb random_int 0 [expr $nclients - 1]] 305 run_election env_cmd envlist err_cmd pri crash $qdir \ 306 $msg $elector $nsites $nvotes $nclients $winner 1 $dbname 307 308 foreach pair $envlist { 309 set i [expr [lindex $pair 1] - 2] 310 set clientenv($i) [lindex $pair 0] 311 set newegen($i) [stat_field $clientenv($i) \ 312 rep_stat "Election generation number"] 313 if { $repfiles_in_memory == 0 } { 314 error_check_good egen_forward \ 315 [expr $newegen($i) > $egen($i)] 1 316 } else { 317 # For rep in-memory, egen expected to 318 # increment to 2 after election. 319 error_check_good egen_recovery $newegen($i) 2 320 } 321 } 322 } 323 324 foreach pair $envlist { 325 set cenv [lindex $pair 0] 326 error_check_good cenv_close [$cenv close] 0 327 } 328 329 replclose $testdir/MSGQUEUEDIR 330} 331 332