# See the file LICENSE for redistribution information. # # Copyright (c) 2006,2008 Oracle. All rights reserved. # # $Id: rep065script.tcl,v 12.19 2008/04/14 14:29:39 sue Exp $ # # rep065script - procs to use at each replication site in the # replication upgrade test. # # type: START, PROCMSGS, VERIFY # START starts up a replication site and performs an operation. # the operations are: # REPTEST runs the rep_test_upg procedure on the master. # REPTEST_GET run a read-only test on a client. # REPTEST_ELECT runs an election on the site. # PROCMSGS processes messages until none are left. # VERIFY dumps the log and database contents. # role: master or client # op: operation to perform # envid: environment id number for use in replsend # allids: all env ids we need for sending # ctldir: controlling directory # mydir: directory where this participant runs # reputils_path: location of reputils.tcl proc rep065scr_elect { repenv oplist } { set ver [lindex $oplist 1] set pri [lindex $oplist 2] } proc rep065scr_reptest { repenv oplist markerdb } { set method [lindex $oplist 1] set niter [lindex $oplist 2] set loop [lindex $oplist 3] set start 0 puts "REPTEST: method $method, niter $niter, loop $loop" for {set n 0} {$n < $loop} {incr n} { puts "REPTEST: call rep_test_upg $n" eval rep_test_upg $method $repenv NULL $niter $start $start 0 0 incr start $niter tclsleep 3 } # # Sleep a bunch to help get the messages worked through. # tclsleep 10 puts "put DONE to marker" error_check_good marker_done [$markerdb put DONE DONE] 0 error_check_good marker_sync [$markerdb sync] 0 } proc rep065scr_repget { repenv oplist mydir markerfile } { set dbname "$mydir/test.db" set i 0 while { [file exists $dbname] == 0 } { tclsleep 2 incr i if { $i >= 15 && $i % 5 == 0 } { puts "After $i seconds, no database exists." } if { $i > 180 } { error "Database never created." } } set loop 1 while { 1 } { set markerdb [berkdb_open $markerfile] error_check_good marker [is_valid_db $markerdb] TRUE set kd [$markerdb get DONE] error_check_good marker_close [$markerdb close] 0 if { [llength $kd] != 0 } { break } set db [berkdb_open -env $repenv $dbname] error_check_good dbopen [is_valid_db $db] TRUE set dbc [$db cursor] set i 0 error_check_good curs [is_valid_cursor $dbc $db] TRUE for { set dbt [$dbc get -first ] } \ { [llength $dbt] > 0 } \ { set dbt [$dbc get -next] } { incr i } error_check_good dbc_close [$dbc close] 0 error_check_good db_close [$db close] 0 puts "REPTEST_GET: after $loop loops: key count $i" incr loop tclsleep 2 } } proc rep065scr_starttest { role oplist envid msgdir mydir allids markerfile } { global qtestdir global util_path puts "repladd_noenv $allids" set qtestdir $msgdir foreach id $allids { repladd_noenv $id } set markerdb [berkdb_open -create -btree $markerfile] error_check_good marker [is_valid_db $markerdb] TRUE puts "set up env cmd" set lockmax 40000 set logbuf [expr 16 * 1024] set logmax [expr $logbuf * 4] if { $role == "MASTER" } { set rep_env_cmd "berkdb_env_noerr -create -home $mydir \ -log_max $logmax -log_buffer $logbuf \ -lock_max_objects $lockmax -lock_max_locks $lockmax \ -errpfx MASTER -txn -rep_master \ -rep_transport \[list $envid replsend_noenv\]" # set rep_env_cmd "berkdb_env_noerr -create -home $mydir \ # -log_max $logmax -log_buffer $logbuf \ # -lock_max_objects $lockmax -lock_max_locks $lockmax \ # -errpfx MASTER -txn -rep_master \ # -verbose {rep on} -errfile /dev/stderr \ # -rep_transport \[list $envid replsend_noenv\]" } elseif { $role == "CLIENT" } { set rep_env_cmd "berkdb_env_noerr -create -home $mydir \ -log_max $logmax -log_buffer $logbuf \ -lock_max_objects $lockmax -lock_max_locks $lockmax \ -errpfx CLIENT -txn -rep_client \ -rep_transport \[list $envid replsend_noenv\]" # set rep_env_cmd "berkdb_env_noerr -create -home $mydir \ # -log_max $logmax -log_buffer $logbuf \ # -lock_max_objects $lockmax -lock_max_locks $lockmax \ # -errpfx CLIENT -txn -rep_client \ # -verbose {rep on} -errfile /dev/stderr \ # -rep_transport \[list $envid replsend_noenv\]" } else { puts "FAIL: unrecognized replication role $role" return } # Change directories to where this will run. # !!! # mydir is an absolute path of the form # /build_unix/TESTDIR/MASTERDIR or # /build_unix/TESTDIR/CLIENTDIR.0 # # So we want to run relative to the build_unix directory cd $mydir/../.. puts "open repenv $rep_env_cmd" set repenv [eval $rep_env_cmd] error_check_good repenv_open [is_valid_env $repenv] TRUE puts "repenv is $repenv" # # Indicate that we're done starting up. Sleep to let # others do the same. # puts "put START$envid to marker" error_check_good marker_done [$markerdb put START$envid START$envid] 0 error_check_good marker_sync [$markerdb sync] 0 puts "sleeping after marker" tclsleep 3 # Here is where the real test starts. # # Different operations may have different args in their list. # REPTEST: Args are method, niter, nloops set op [lindex $oplist 0] if { $op == "REPTEST" } { # # This test writes the marker, so close after it runs. # rep065scr_reptest $repenv $oplist $markerdb error_check_good marker_close [$markerdb close] 0 } if { $op == "REPTEST_GET" } { # # This test needs to poll the marker. So close it now. # error_check_good marker_close [$markerdb close] 0 rep065scr_repget $repenv $oplist $mydir $markerfile } if { $op == "REP_ELECT" } { # # This test writes the marker, so close after it runs. # rep065scr_elect $repenv $oplist $markerdb } puts "Closing env" $repenv mpool_sync error_check_good envclose [$repenv close] 0 } proc rep065scr_msgs { role envid msgdir mydir allids markerfile } { global qtestdir # # The main test process will write the marker file when it # has started and when it has completed. We need to # open/close the marker file because we are in a separate # process from the writer and we cannot share an env because # we might be a different BDB release version. # set markerdb [berkdb_open -create -btree $markerfile] error_check_good marker [is_valid_db $markerdb] TRUE set s [$markerdb get START$envid] while { [llength $s] == 0 } { error_check_good marker_close [$markerdb close] 0 tclsleep 1 set markerdb [berkdb_open $markerfile] error_check_good marker [is_valid_db $markerdb] TRUE set s [$markerdb get START$envid] } puts "repladd_noenv $allids" set qtestdir $msgdir foreach id $allids { repladd_noenv $id } puts "set up env cmd" if { $role == "MASTER" } { set rep_env_cmd "berkdb_env_noerr -home $mydir \ -errpfx MASTER -txn -rep_master \ -rep_transport \[list $envid replsend_noenv\]" # set rep_env_cmd "berkdb_env_noerr -home $mydir \ # -errpfx MASTER -txn -rep_master \ # -verbose {rep on} -errfile /dev/stderr \ # -rep_transport \[list $envid replsend_noenv\]" } elseif { $role == "CLIENT" } { set rep_env_cmd "berkdb_env_noerr -home $mydir \ -errpfx CLIENT -txn -rep_client \ -rep_transport \[list $envid replsend_noenv\]" # set rep_env_cmd "berkdb_env_noerr -home $mydir \ # -errpfx CLIENT -txn -rep_client \ # -verbose {rep on} -errfile /dev/stderr \ # -rep_transport \[list $envid replsend_noenv\]" } else { puts "FAIL: unrecognized replication role $role" return } # Change directories to where this will run. cd $mydir puts "open repenv $rep_env_cmd" set repenv [eval $rep_env_cmd] error_check_good repenv_open [is_valid_env $repenv] TRUE set envlist "{$repenv $envid}" puts "repenv is $repenv" while { 1 } { if { [llength [$markerdb get DONE]] != 0 } { break } process_msgs $envlist 0 NONE NONE 1 error_check_good marker_close [$markerdb close] 0 set markerdb [berkdb_open $markerfile] error_check_good marker [is_valid_db $markerdb] TRUE tclsleep 1 } # # Process messages in case there are a few more stragglers. # Just because the main test is done doesn't mean that all # the messaging is done. Loop for messages as long as # progress is being made. # set nummsg 1 while { $nummsg != 0 } { process_msgs $envlist 0 NONE NONE 1 tclsleep 1 # First look at messages from us set nummsg [replmsglen_noenv $envid from] puts "Still have $nummsg not yet processed by others" } error_check_good marker_close [$markerdb close] 0 replclear_noenv $envid from tclsleep 1 replclear_noenv $envid $repenv mpool_sync error_check_good envclose [$repenv close] 0 } proc rep065scr_verify { oplist mydir id } { global util_path set rep_env_cmd "berkdb_env_noerr -home $mydir -txn \ -rep_transport \[list $id replnoop\]" # Change directories to where this will run. # !!! # mydir is an absolute path of the form # /build_unix/TESTDIR/MASTERDIR or # /build_unix/TESTDIR/CLIENTDIR.0 # # So we want to run relative to the build_unix directory cd $mydir/../.. foreach op $oplist { set repenv [eval $rep_env_cmd] error_check_good env_open [is_valid_env $repenv] TRUE if { $op == "DB" } { set dbname "$mydir/test.db" set db [berkdb_open -env $repenv -rdonly $dbname] error_check_good dbopen [is_valid_db $db] TRUE set txn "" set method [$db get_type] if { [is_record_based $method] == 1 } { dump_file $db $txn $mydir/VERIFY/dbdump \ rep_test_upg.recno.check } else { dump_file $db $txn $mydir/VERIFY/dbdump \ rep_test_upg.check } error_check_good dbclose [$db close] 0 } if { $op == "LOG" } { set lgstat [$repenv log_stat] set lgfile [stat_field $repenv log_stat "Current log file number"] set lgoff [stat_field $repenv log_stat "Current log file offset"] puts "Current LSN: $lgfile $lgoff" set f [open $mydir/VERIFY/loglsn w] puts $f $lgfile puts $f $lgoff close $f set stat [catch {eval exec $util_path/db_printlog \ -h $mydir > $mydir/VERIFY/prlog} result] if { $stat != 0 } { puts "PRINTLOG: $result" } error_check_good stat_prlog $stat 0 } error_check_good envclose [$repenv close] 0 } # # Run recovery locally so that any later upgrades are ready # to be upgraded. # set stat [catch {eval exec $util_path/db_recover -h $mydir} result] if { $stat != 0 } { puts "RECOVERY: $result" } error_check_good stat_rec $stat 0 } set usage "upgradescript type role op envid allids ctldir mydir reputils_path" # Verify usage if { $argc != 8 } { puts stderr "Argc $argc, argv $argv" puts stderr "FAIL:[timestamp] Usage: $usage" exit } # Initialize arguments set type [ lindex $argv 0 ] set role [ lindex $argv 1 ] set op [ lindex $argv 2 ] set envid [ lindex $argv 3 ] set allids [ lindex $argv 4 ] set ctldir [ lindex $argv 5 ] set mydir [ lindex $argv 6 ] set reputils_path [ lindex $argv 7 ] set histdir $mydir/../.. puts "Histdir $histdir" set msgtestdir $ctldir/TESTDIR global env cd $histdir set stat [catch {eval exec ./db_printlog -V} result] if { $stat != 0 } { set env(LD_LIBRARY_PATH) ":$histdir:$histdir/.libs:$env(LD_LIBRARY_PATH)" } source ./include.tcl source $test_path/test.tcl # The global variable noenv_messaging must be set after sourcing # test.tcl or its value will be wrong. global noenv_messaging set noenv_messaging 1 set is_repchild 1 puts "Did args. now source reputils" source $reputils_path/reputils.tcl source $reputils_path/reputilsnoenv.tcl set markerdir $msgtestdir/MARKER set markerfile $markerdir/marker.db puts "Calling proc for type $type" if { $type == "START" } { rep065scr_starttest $role $op $envid $msgtestdir $mydir $allids $markerfile } elseif { $type == "PROCMSGS" } { rep065scr_msgs $role $envid $msgtestdir $mydir $allids $markerfile } elseif { $type == "VERIFY" } { file mkdir $mydir/VERIFY rep065scr_verify $op $mydir $envid } else { puts "FAIL: unknown type $type" return }