1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2005,2008 Oracle. All rights reserved. 4# 5# $Id: rep044.tcl,v 12.16 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST rep044 8# TEST 9# TEST Test rollbacks with open file ids. 10# TEST 11# TEST We have one master with two handles and one client. 12# TEST Each time through the main loop, we open a db, write 13# TEST to the db, and close the db. Each one of these actions 14# TEST is propagated to the client, or a roll back is forced 15# TEST by swapping masters. 16 17proc rep044 { method { tnum "044" } args } { 18 19 source ./include.tcl 20 if { $is_windows9x_test == 1 } { 21 puts "Skipping replication test on Win 9x platform." 22 return 23 } 24 25 # Valid for all access methods. 26 if { $checking_valid_methods } { 27 return "ALL" 28 } 29 30 set args [convert_args $method $args] 31 set logsets [create_logsets 2] 32 33 # HP-UX can't open two handles on the same env, so it 34 # can't run this test. 35 if { $is_hp_test == 1 } { 36 puts "Skipping rep$tnum for HP-UX." 37 return 38 } 39 40 foreach l $logsets { 41 set logindex [lsearch -exact $l "in-memory"] 42 puts "Rep$tnum ($method): Replication with rollbacks\ 43 and open file ids." 44 puts "Rep$tnum: Master logs are [lindex $l 0]" 45 puts "Rep$tnum: Client 0 logs are [lindex $l 1]" 46 rep044_sub $method $tnum $l $args 47 } 48} 49 50proc rep044_sub { method tnum logset largs } { 51 source ./include.tcl 52 set orig_tdir $testdir 53 54 global rep_verbose 55 global verbose_type 56 57 set verbargs "" 58 if { $rep_verbose == 1 } { 59 set verbargs " -verbose {$verbose_type on} " 60 } 61 62 set masterdir $testdir/ENV0 63 set clientdir $testdir/ENV1 64 65 set m_logtype [lindex $logset 0] 66 set c_logtype [lindex $logset 1] 67 68 # In-memory logs require a large log buffer, and cannot 69 # be used with -txn nosync. 70 set m_logargs [adjust_logargs $m_logtype] 71 set c_logargs [adjust_logargs $c_logtype] 72 set m_txnargs [adjust_txnargs $m_logtype] 73 set c_txnargs [adjust_txnargs $c_logtype] 74 75 set niter 20 76 set omethod [convert_method $method] 77 78 # The main loop runs all the permutations of processing/not 79 # processing the database open to the clients; processing/not 80 # processing the database writes to the clients; and processing/ 81 # not processing the database close to the clients. Set up the 82 # options in advance so the loop is not heavily indented. 83 # 84 # Each entry displays { open write close }. 85 # For example { 1 1 0 } means we process messages after the 86 # db open and the db writes but not after the db close. 87 88 set optionsets { 89 {1 1 1} 90 {1 1 0} 91 {1 0 1} 92 {1 0 0} 93 {0 1 1} 94 {0 1 0} 95 {0 0 1} 96 {0 0 0} 97 } 98 99 # Main loop. 100 foreach set $optionsets { 101 102 env_cleanup $testdir 103 replsetup $testdir/MSGQUEUEDIR 104 file mkdir $masterdir 105 file mkdir $clientdir 106 107 set processopens [lindex $set 0] 108 set processwrites [lindex $set 1] 109 set processcloses [lindex $set 2] 110 111 set notdoing {} 112 if { $processopens == 0 } { 113 append notdoing " OPENS" 114 } 115 if { $processwrites == 0 } { 116 append notdoing " WRITES" 117 } 118 if { $processcloses == 0 } { 119 append notdoing " CLOSES" 120 } 121 if { $notdoing != {} } { 122 puts "Rep$tnum:\ 123 Loop with $notdoing not processed to client." 124 } 125 126 # Open a master. 127 repladd 1 128 set envcmd(M0) "berkdb_env_noerr -create $m_txnargs \ 129 $m_logargs -lock_detect default \ 130 -errpfx ENV.M0 $verbargs \ 131 -home $masterdir -rep_transport \[list 1 replsend\]" 132 set menv0 [eval $envcmd(M0) -rep_master] 133 134 # Open second handle on master env. 135 set envcmd(M1) "berkdb_env_noerr $m_txnargs \ 136 $m_logargs -lock_detect default \ 137 -errpfx ENV.M1 $verbargs \ 138 -home $masterdir -rep_transport \[list 1 replsend\]" 139 set menv1 [eval $envcmd(M1)] 140 error_check_good rep_start [$menv1 rep_start -master] 0 141 142 # Open a client 143 repladd 2 144 set envcmd(C) "berkdb_env_noerr -create $c_txnargs \ 145 $c_logargs -errpfx ENV.C $verbargs \ 146 -lock_detect default \ 147 -home $clientdir -rep_transport \[list 2 replsend\]" 148 set cenv [eval $envcmd(C) -rep_client] 149 150 # Bring the client online by processing the startup messages. 151 set envlist "{$menv0 1} {$cenv 2}" 152 process_msgs $envlist 153 154 puts "\tRep$tnum.a: Run rep_test in 1st master env." 155 set start 0 156 eval rep_test $method $menv0 NULL $niter $start $start 0 0 $largs 157 incr start $niter 158 process_msgs $envlist 159 160 puts "\tRep$tnum.b: Open db in 2nd master env." 161 # Open the db here; we want it to remain open after rep_test. 162 set db1 [eval {berkdb_open_noerr -env $menv1 -auto_commit \ 163 -mode 0644} $largs $omethod test.db] 164 error_check_good dbopen [is_valid_db $db1] TRUE 165 166 if { $processopens == 1 } { 167 puts "\tRep$tnum.b1:\ 168 Process db open messages to client." 169 process_msgs $envlist 170 } else { 171 set start [do_switch $method $niter $start $menv0 $cenv $largs] 172 } 173 174 puts "\tRep$tnum.c: Write to database in 2nd master." 175 # We don't use rep_test here, because sometimes we abort. 176 for { set i 1 } { $i <= $niter } { incr i } { 177 set t [$menv1 txn] 178 set key $i 179 set str STRING.$i 180 if [catch {eval {$db1 put}\ 181 -txn $t {$key [chop_data $method $str]}} result] { 182 # If handle is dead, abort txn, then 183 # close and reopen db. 184 error_check_good handle_dead \ 185 [is_substr $result HANDLE_DEAD] 1 186 error_check_good txn_abort [$t abort] 0 187 error_check_good close_handle [$db1 close] 0 188 set db1 [eval {berkdb_open_noerr \ 189 -env $menv1 -auto_commit -mode 0644}\ 190 $largs $omethod test.db] 191 } else { 192 error_check_good txn_commit [$t commit] 0 193 } 194 } 195 196 if { $processwrites == 1 } { 197 puts "\tRep$tnum.c1:\ 198 Process db put messages to client." 199 process_msgs $envlist 200 } else { 201 set start [do_switch $method $niter $start $menv0 $cenv $largs] 202 } 203 204 puts "\tRep$tnum.d: Close database using 2nd master env handle." 205 error_check_good db_close [$db1 close] 0 206 207 if { $processcloses == 1 } { 208 puts "\tRep$tnum.d1:\ 209 Process db close messages to client." 210 process_msgs $envlist 211 } else { 212 set start [do_switch $method $niter $start $menv0 $cenv $largs] 213 } 214 215 puts "\tRep$tnum.e: Clean up." 216 error_check_good menv0_close [$menv0 close] 0 217 error_check_good menv1_close [$menv1 close] 0 218 error_check_good cenv_close [$cenv close] 0 219 220 replclose $testdir/MSGQUEUEDIR 221 } 222 set testdir $orig_tdir 223 return 224} 225 226proc do_switch { method niter start masterenv clientenv largs } { 227 set envlist "{$masterenv 1} {$clientenv 2}" 228 229 # Downgrade master, upgrade client. 230 error_check_good master_downgrade [$masterenv rep_start -client] 0 231 error_check_good client_upgrade [$clientenv rep_start -master] 0 232 process_msgs $envlist 233 234 # Run rep_test in the new master. 235 eval rep_test $method $clientenv NULL $niter $start $start 0 0 $largs 236 incr start $niter 237 process_msgs $envlist 238 239 # Downgrade newmaster, upgrade original master. 240 error_check_good client_downgrade [$clientenv rep_start -client] 0 241 error_check_good master_upgrade [$masterenv rep_start -master] 0 242 243 # Run rep_test in the restored master. 244 eval rep_test $method $masterenv NULL $niter $start $start 0 0 $largs 245 incr start $niter 246 process_msgs $envlist 247 248 return $start 249} 250