# See the file LICENSE for redistribution information. # # Copyright (c) 2002 # Sleepycat Software. All rights reserved. # # $Id: rep005.tcl,v 1.1.1.1 2003/02/15 04:56:16 zarzycki Exp $ # # TEST rep005 # TEST Replication election test with error handling. # TEST # TEST Run a modified version of test001 in a replicated master environment; # TEST hold an election among a group of clients to make sure they select # TEST a proper master from amongst themselves, forcing errors at various # TEST locations in the election path. proc rep005 { method { niter 10 } { tnum "05" } args } { source ./include.tcl if { [is_record_based $method] == 1 } { puts "Rep005: Skipping for method $method." return } set nclients 3 env_cleanup $testdir set qdir $testdir/MSGQUEUEDIR replsetup $qdir set masterdir $testdir/MASTERDIR file mkdir $masterdir for { set i 0 } { $i < $nclients } { incr i } { set clientdir($i) $testdir/CLIENTDIR.$i file mkdir $clientdir($i) } puts "Rep0$tnum: Replication election test with $nclients clients." # Open a master. repladd 1 set env_cmd(M) "berkdb_env -create -log_max 1000000 -home \ $masterdir -txn -rep_master -rep_transport \[list 1 replsend\]" set masterenv [eval $env_cmd(M)] error_check_good master_env [is_valid_env $masterenv] TRUE # Open the clients. for { set i 0 } { $i < $nclients } { incr i } { set envid [expr $i + 2] repladd $envid set env_cmd($i) "berkdb_env -create -home $clientdir($i) \ -txn -rep_client -rep_transport \[list $envid replsend\]" set clientenv($i) [eval $env_cmd($i)] error_check_good \ client_env($i) [is_valid_env $clientenv($i)] TRUE } # Run a modified test001 in the master. puts "\tRep0$tnum.a: Running test001 in replicated env." eval test001 $method $niter 0 $tnum 0 -env $masterenv $args # Loop, processing first the master's messages, then the client's, # until both queues are empty. while { 1 } { set nproced 0 incr nproced [replprocessqueue $masterenv 1] for { set i 0 } { $i < $nclients } { incr i } { set envid [expr $i + 2] incr nproced [replprocessqueue $clientenv($i) $envid] } if { $nproced == 0 } { break } } # Verify the database in the client dir. for { set i 0 } { $i < $nclients } { incr i } { puts "\tRep0$tnum.b: Verifying contents of client database $i." set testdir [get_home $masterenv] set t1 $testdir/t1 set t2 $testdir/t2 set t3 $testdir/t3 open_and_dump_file test0$tnum.db $clientenv($i) $testdir/t1 \ test001.check dump_file_direction "-first" "-next" if { [string compare [convert_method $method] -recno] != 0 } { filesort $t1 $t3 } error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0 verify_dir $clientdir($i) "\tRep0$tnum.c: " 0 0 1 } # Make sure all the clients are synced up and ready to be good # voting citizens. error_check_good master_flush [$masterenv rep_flush] 0 while { 1 } { set nproced 0 incr nproced [replprocessqueue $masterenv 1 0] for { set i 0 } { $i < $nclients } { incr i } { incr nproced [replprocessqueue $clientenv($i) \ [expr $i + 2] 0] } if { $nproced == 0 } { break } } error_check_good masterenv_close [$masterenv close] 0 for { set i 0 } { $i < $nclients } { incr i } { replclear [expr $i + 2] } # # We set up the error list for each client. We know that the # first client is the one calling the election, therefore, add # the error location on sending the message (electsend) for that one. set m "Rep0$tnum" set count 0 foreach c0 { electinit electsend electvote1 electwait1 electvote2 \ electwait2 } { foreach c1 { electinit electvote1 electwait1 electvote2 \ electwait2 } { foreach c2 { electinit electvote1 electwait1 \ electvote2 electwait2 } { set elist [list $c0 $c1 $c2] rep005_elect env_cmd clientenv $qdir $m \ $count $elist incr count } } } for { set i 0 } { $i < $nclients } { incr i } { error_check_good clientenv_close($i) [$clientenv($i) close] 0 } replclose $testdir/MSGQUEUEDIR } proc rep005_elect { ecmd cenv qdir msg count elist } { global elect_timeout upvar $ecmd env_cmd upvar $cenv clientenv set elect_timeout 1000000 set nclients [llength $elist] for { set i 0 } { $i < $nclients } { incr i } { set err_cmd($i) [lindex $elist $i] } puts "\t$msg.d.$count: Starting election with errors $elist" set elect_pipe(0) [start_election $qdir $env_cmd(0) \ [expr $nclients + 1] 20 $elect_timeout $err_cmd(0)] tclsleep 1 # Process messages, and verify that the client with the highest # priority--client #1--wins. set got_newmaster 0 set tries 10 while { 1 } { set nproced 0 set he 0 set nm 0 for { set i 0 } { $i < $nclients } { incr i } { set he 0 set envid [expr $i + 2] # puts "Processing queue for client $i" incr nproced \ [replprocessqueue $clientenv($i) $envid 0 he nm] if { $he == 1 } { # Client #1 has priority 100; everyone else if { $i == 1 } { set pri 100 } else { set pri 10 } # error_check_bad client(0)_in_elect $i 0 # puts "Starting election on client $i" set elect_pipe($i) [start_election $qdir \ $env_cmd($i) [expr $nclients + 1] $pri \ $elect_timeout $err_cmd($i)] set got_hold_elect($i) 1 } if { $nm != 0 } { error_check_good newmaster_is_master $nm \ [expr 1 + 2] set got_newmaster $nm # If this env is the new master, it needs to # configure itself as such--this is a different # env handle from the one that performed the # election. if { $nm == $envid } { error_check_good make_master($i) \ [$clientenv($i) rep_start -master] \ 0 } } } # We need to wait around to make doubly sure that the # election has finished... if { $nproced == 0 } { incr tries -1 if { $tries == 0 } { break } else { tclsleep 1 } } } # Verify that client #1 is actually the winner. error_check_good "client 1 wins" $got_newmaster [expr 1 + 2] cleanup_elections }