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