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