1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2003,2008 Oracle. All rights reserved. 4# 5# $Id: rep042.tcl,v 12.19 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST rep042 8# TEST Concurrency with updates. 9# TEST 10# TEST Verify racing role changes and updates don't result in 11# TEST pages with LSN 0,1. Set up an environment that is master. 12# TEST Spawn child process that does a delete, but using the 13# TEST $env check so that it sleeps in the middle of the call. 14# TEST Master downgrades and then sleeps as a client so that 15# TEST child will run. Verify child does not succeed (should 16# TEST get read-only error) due to role change in the middle of 17# TEST its call. 18proc rep042 { method { niter 10 } { tnum "042" } args } { 19 20 source ./include.tcl 21 if { $is_windows9x_test == 1 } { 22 puts "Skipping replication test on Win 9x platform." 23 return 24 } 25 26 # Valid for all access methods. 27 if { $checking_valid_methods } { 28 return "ALL" 29 } 30 31 set args [convert_args $method $args] 32 set logsets [create_logsets 2] 33 34 # Run the body of the test with and without recovery. 35 foreach r $test_recopts { 36 foreach l $logsets { 37 set logindex [lsearch -exact $l "in-memory"] 38 if { $r == "-recover" && $logindex != -1 } { 39 puts "Rep$tnum: Skipping\ 40 for in-memory logs with -recover." 41 continue 42 } 43 44 puts "Rep$tnum ($method $r):\ 45 Concurrency with updates." 46 puts "Rep$tnum: Master logs are [lindex $l 0]" 47 puts "Rep$tnum: Client logs are [lindex $l 1]" 48 rep042_sub $method $niter $tnum $l $r $args 49 } 50 } 51} 52 53proc rep042_sub { method niter tnum logset recargs largs } { 54 source ./include.tcl 55 global perm_response_list 56 global rep_verbose 57 global verbose_type 58 59 set verbargs "" 60 if { $rep_verbose == 1 } { 61 set verbargs " -verbose {$verbose_type on} " 62 } 63 64 env_cleanup $testdir 65 set omethod [convert_method $method] 66 67 replsetup $testdir/MSGQUEUEDIR 68 69 set masterdir $testdir/MASTERDIR 70 set clientdir $testdir/CLIENTDIR 71 72 file mkdir $masterdir 73 file mkdir $clientdir 74 set m_logtype [lindex $logset 0] 75 set c_logtype [lindex $logset 1] 76 77 # In-memory logs require a large log buffer, and cannot 78 # be used with -txn nosync. 79 set m_logargs [adjust_logargs $m_logtype] 80 set c_logargs [adjust_logargs $c_logtype] 81 set m_txnargs [adjust_txnargs $m_logtype] 82 set c_txnargs [adjust_txnargs $c_logtype] 83 84 # Open a master. 85 repladd 1 86 set ma_cmd "berkdb_env_noerr -create \ 87 -log_max 1000000 $m_txnargs $m_logargs $verbargs \ 88 -home $masterdir -rep_master -errpfx MASTER \ 89 -rep_transport \[list 1 replsend\]" 90 set masterenv [eval $ma_cmd $recargs] 91 92 # Open a client 93 repladd 2 94 set cl_cmd "berkdb_env_noerr -create -home $clientdir \ 95 $c_txnargs $c_logargs $verbargs -errpfx CLIENT -rep_client \ 96 -rep_transport \[list 2 replsend\]" 97 set clientenv [eval $cl_cmd $recargs] 98 99 # Bring the client online. 100 process_msgs "{$masterenv 1} {$clientenv 2}" 101 102 puts "\tRep$tnum.a: Create and populate database." 103 set dbname rep042.db 104 set db [eval "berkdb_open_noerr -create $omethod -auto_commit \ 105 -env $masterenv $largs $dbname"] 106 for { set i 1 } { $i < $niter } { incr i } { 107 set t [$masterenv txn] 108 error_check_good db_put \ 109 [eval $db put -txn $t $i [chop_data $method data$i]] 0 110 error_check_good txn_commit [$t commit] 0 111 } 112 process_msgs "{$masterenv 1} {$clientenv 2}" 113 114 set ops {del truncate} 115 foreach op $ops { 116 # Fork child process on client. The child will do a delete. 117 set sleepval 4 118 set scrlog $testdir/repscript.log 119 puts "\tRep$tnum.b: Fork child process on client ($op)." 120 set pid [exec $tclsh_path $test_path/wrap.tcl \ 121 rep042script.tcl $scrlog \ 122 $masterdir $sleepval $dbname $op &] 123 124 # Wait for child process to start up. 125 while { 1 } { 126 if { [file exists $masterdir/marker.db] == 0 } { 127 tclsleep 1 128 } else { 129 tclsleep 1 130 break 131 } 132 } 133 134 puts "\tRep$tnum.c: Downgrade during child $op." 135 error_check_good downgrade [$masterenv rep_start -client] 0 136 137 puts "\tRep$tnum.d: Waiting for child ..." 138 # Watch until the child is done. 139 watch_procs $pid 5 140 puts "\tRep$tnum.e: Upgrade to master again ..." 141 error_check_good upgrade [$masterenv rep_start -master] 0 142 set end [expr $niter * 2] 143 for { set i $niter } { $i <= $end } { incr i } { 144 set t [$masterenv txn] 145 error_check_good db_put \ 146 [eval $db put -txn $t $i [chop_data $method data$i]] 0 147 error_check_good txn_commit [$t commit] 0 148 } 149 process_msgs "{$masterenv 1} {$clientenv 2}" 150 151 # We expect to find the error "attempt to modify a read-only 152 # database." If we don't, report what we did find as a failure. 153 set readonly_error [check_script $scrlog "read-only"] 154 if { $readonly_error != 1 } { 155 set errstrings [eval findfail $scrlog] 156 if { [llength $errstrings] > 0 } { 157 puts "FAIL: unexpected error(s)\ 158 found in file $scrlog:$errstrings" 159 } 160 } 161 fileremove -f $masterdir/marker.db 162 } 163 164 # Clean up. 165 error_check_good db_close [$db close] 0 166 error_check_good masterenv_close [$masterenv close] 0 167 error_check_good clientenv_close [$clientenv close] 0 168 169 replclose $testdir/MSGQUEUEDIR 170} 171 172proc check_script { log str } { 173 set ret 0 174 set res [catch {open $log} id] 175 if { $res != 0 } { 176 puts "FAIL: open of $log failed: $id" 177 # Return 0 178 return $ret 179 } 180 while { [gets $id val] != -1 } { 181# puts "line: $val" 182 if { [is_substr $val $str] } { 183 set ret 1 184 break 185 } 186 } 187 close $id 188 return $ret 189} 190