proc rep002 { method { niter 10 } { nclients 3 } { tnum "002" } args } {
source ./include.tcl
global elect_timeout elect_serial
set elect_timeout 5000000
if { [is_record_based $method] == 1 } {
puts "Rep002: Skipping for method $method."
return
}
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 "Rep$tnum: Replication election test with $nclients clients."
repladd 1
set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 \
-home $masterdir -errpfx MASTER \
-txn nosync -rep_master -rep_transport \[list 1 replsend\]"
set masterenv [eval $env_cmd(M)]
error_check_good master_env [is_valid_env $masterenv] TRUE
for { set i 0 } { $i < $nclients } { incr i } {
set envid [expr $i + 2]
repladd $envid
set env_cmd($i) "berkdb_env_noerr -create -home $clientdir($i) \
-txn nosync -rep_client -errpfx CLIENT$i \
-rep_transport \[list $envid replsend\]"
set clientenv($i) [eval $env_cmd($i)]
error_check_good \
client_env($i) [is_valid_env $clientenv($i)] TRUE
}
puts "\tRep$tnum.a: Running test001 in replicated env."
eval test001 $method $niter 0 0 $tnum -env $masterenv $args
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
}
}
for { set i 0 } { $i < $nclients } { incr i } {
puts "\tRep$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 test$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) "\tRep$tnum.c: " 0 0 1
}
puts "\tRep$tnum.d: Starting election with existing master."
set got_hold_elect(M) 0
for { set i 0 } { $i < $nclients } { incr i } {
set got_hold_elect($i) 0
set elect_pipe($i) INVALID
}
set elect_pipe(0) [start_election C0 \
$qdir $env_cmd(0) [expr $nclients + 1] 20 $elect_timeout]
tclsleep 2
set got_master 0
while { 1 } {
set nproced 0
set he 0
set nm 0
set nm2 0
incr nproced [replprocessqueue $masterenv 1 0 he nm]
if { $he == 1 } {
incr elect_serial
set elect_pipe(M) [start_election CM $qdir \
$env_cmd(M) [expr $nclients + 1] 0 $elect_timeout]
set got_hold_elect(M) 1
}
if { $nm != 0 } {
error_check_good newmaster_is_master $nm 1
set got_master $nm
}
if { $nm2 != 0 } {
error_check_good newmaster_is_master $nm2 1
set got_master $nm2
}
for { set i 0 } { $i < $nclients } { incr i } {
set he 0
set envid [expr $i + 2]
incr nproced \
[replprocessqueue $clientenv($i) $envid 0 he nm]
set child_done [check_election $elect_pipe($i) nm2]
if { $he == 1 } {
if { $elect_pipe($i) != "INVALID" } {
close_election $elect_pipe($i)
}
incr elect_serial
set pfx CHILD$i.$elect_serial
set elect_pipe($i) [start_election $pfx $qdir \
$env_cmd($i) [expr $nclients + 1] 0 \
$elect_timeout]
set got_hold_elect($i) 1
}
if { $nm != 0 } {
error_check_good newmaster_is_master $nm 1
set got_master $nm
}
if { $nm2 != 0 } {
error_check_good newmaster_is_master $nm2 1
set got_master $nm2
}
}
if { $nproced == 0 } {
break
}
}
error_check_good got_master $got_master 1
cleanup_elections
if { $nclients < 2 } {
puts "\tRep$tnum: Skipping for less than two clients."
error_check_good masterenv_close [$masterenv close] 0
for { set i 0 } { $i < $nclients } { incr i } {
error_check_good clientenv_close($i) \
[$clientenv($i) close] 0
}
return
}
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
}
}
puts "\tRep$tnum.e: Starting election with dead master."
error_check_good masterenv_close [$masterenv close] 0
for { set i 0 } { $i < $nclients } { incr i } {
replclear [expr $i + 2]
}
incr elect_serial
set elect_pipe(0) [start_election C0 \
$qdir $env_cmd(0) $nclients 20 $elect_timeout]
tclsleep 2
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]
set child_done [check_election $elect_pipe($i) nm2]
if { $got_newmaster == 0 && $nm2 != 0} {
error_check_good newmaster_is_master $nm2 \
[expr 1 + 2]
set got_newmaster $nm2
if { $nm2 == $envid } {
error_check_good make_master($i) \
[$clientenv($i) rep_start -master] \
0
}
}
incr nproced \
[replprocessqueue $clientenv($i) $envid 0 he nm]
if { $he == 1 } {
if { $i == 1 } {
set pri 100
} else {
set pri 10
}
incr elect_serial
set pfx CHILD$i.$elect_serial
set elect_pipe($i) [start_election $pfx \
$qdir $env_cmd($i) $nclients \
$pri $elect_timeout]
set got_hold_elect($i) 1
}
if { $nm != 0 } {
error_check_good newmaster_is_master $nm \
[expr 1 + 2]
set got_newmaster $nm
if { $nm == $envid } {
error_check_good make_master($i) \
[$clientenv($i) rep_start -master] \
0
}
}
}
if { $nproced == 0 } {
incr tries -1
if { $tries == 0 } {
break
} else {
tclsleep 1
}
} else {
set tries 10
}
}
error_check_good "client 1 wins" $got_newmaster [expr 1 + 2]
cleanup_elections
for { set i 0 } { $i < $nclients } { incr i } {
error_check_good clientenv_close($i) [$clientenv($i) close] 0
}
replclose $testdir/MSGQUEUEDIR
}