1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2001,2008 Oracle. All rights reserved. 4# 5# $Id: rep066.tcl,v 12.13 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST rep066 8# TEST Replication and dead log handles. 9# TEST 10# TEST Run rep_test on master and a client. 11# TEST Simulate client crashes (master continues) until log 2. 12# TEST Open 2nd master env handle and put something in log and flush. 13# TEST Downgrade master, restart client as master. 14# TEST Run rep_test on newmaster until log 2. 15# TEST New master writes log records, newclient processes records 16# TEST and 2nd newclient env handle calls log_flush. 17# TEST New master commits, newclient processes and should succeed. 18# TEST Make sure 2nd handle detects the old log handle and doesn't 19# TEST write to a stale handle (if it does, the processing of the 20# TEST commit will fail). 21# 22proc rep066 { method { niter 10 } { tnum "066" } args } { 23 24 source ./include.tcl 25 if { $is_windows9x_test == 1 } { 26 puts "Skipping replication test on Win 9x platform." 27 return 28 } 29 30 # Run for all access methods. 31 if { $checking_valid_methods } { 32 return "ALL" 33 } 34 35 # This test requires a second handle on an env, and HP-UX 36 # doesn't support that. 37 if { $is_hp_test } { 38 puts "Skipping rep$tnum for HP-UX." 39 return 40 } 41 42 set args [convert_args $method $args] 43 set logsets [create_logsets 2] 44 45 # Run the body of the test with and without recovery. 46 foreach r $test_recopts { 47 foreach l $logsets { 48 set logindex [lsearch -exact $l "in-memory"] 49 if { $r == "-recover" && $logindex != -1 } { 50 puts "Rep$tnum: Skipping\ 51 for in-memory logs with -recover." 52 continue 53 } 54 puts "Rep$tnum ($method $r):\ 55 Replication and dead log handles." 56 puts "Rep$tnum: Master logs are [lindex $l 0]" 57 puts "Rep$tnum: Client logs are [lindex $l 1]" 58 rep066_sub $method $niter $tnum $l $r $args 59 } 60 } 61} 62 63proc rep066_sub { method niter tnum logset recargs largs } { 64 global testdir 65 global rep_verbose 66 global verbose_type 67 68 set verbargs "" 69 if { $rep_verbose == 1 } { 70 set verbargs " -verbose {$verbose_type on} " 71 } 72 73 env_cleanup $testdir 74 75 replsetup $testdir/MSGQUEUEDIR 76 77 set masterdir $testdir/MASTERDIR 78 set clientdir $testdir/CLIENTDIR 79 file mkdir $masterdir 80 file mkdir $clientdir 81 82 # Log size is small so we quickly create more than one. 83 # The documentation says that the log file must be at least 84 # four times the size of the in-memory log buffer. 85 set pagesize 4096 86 append largs " -pagesize $pagesize " 87 set log_max [expr $pagesize * 8] 88 89 set m_logtype [lindex $logset 0] 90 set c_logtype [lindex $logset 1] 91 92 # In-memory logs require a large log buffer, and cannot 93 # be used with -txn nosync. 94 set m_logargs [adjust_logargs $m_logtype] 95 set c_logargs [adjust_logargs $c_logtype] 96 set m_txnargs [adjust_txnargs $m_logtype] 97 set c_txnargs [adjust_txnargs $c_logtype] 98 99 # Open a master. 100 # Later we'll open a 2nd handle to this env. 101 repladd 1 102 set ma_envcmd "berkdb_env_noerr -create $m_txnargs \ 103 $m_logargs -errpfx ENV0 -log_max $log_max $verbargs \ 104 -home $masterdir -rep_transport \[list 1 replsend\]" 105 set env0 [eval $ma_envcmd $recargs -rep_master] 106 set masterenv $env0 107 108 # Open a client. 109 repladd 2 110 set cl_envcmd "berkdb_env_noerr -create $c_txnargs \ 111 $c_logargs -errpfx ENV1 -log_max $log_max $verbargs \ 112 -home $clientdir -rep_transport \[list 2 replsend\]" 113 set env1 [eval $cl_envcmd $recargs -rep_client] 114 set clientenv $env1 115 116 # Bring the clients online by processing the startup messages. 117 set envlist "{$env0 1} {$env1 2}" 118 process_msgs $envlist 119 120 # Run a modified test001 in the master (and update clients). 121 puts "\tRep$tnum.a.0: Running rep_test in replicated env." 122 eval rep_test $method $masterenv NULL $niter 0 0 0 0 $largs 123 process_msgs $envlist 124 125 set nstart $niter 126 set last_client_log [get_logfile $env1 last] 127 set stop 0 128 while { $stop == 0 } { 129 puts "\tRep$tnum.b: Run test on master until log file changes." 130 eval rep_test\ 131 $method $masterenv NULL $niter $nstart $nstart 0 0 $largs 132 incr nstart $niter 133 replclear 2 134 set last_master_log [get_logfile $masterenv last] 135 if { $last_master_log > $last_client_log } { 136 set stop 1 137 } 138 } 139 140 # Open a 2nd env handle on the master. 141 # We want to have some operations happen on the normal 142 # handle and then flush them with this handle. 143 puts "\tRep$tnum.c: Open 2nd master env and flush log." 144 set 2ndenv [eval $ma_envcmd -rep_master -errpfx 2NDENV] 145 error_check_good master_env [is_valid_env $2ndenv] TRUE 146 147 set testfile2 "test$tnum.2.db" 148 set omethod [convert_method $method] 149 set txn [$masterenv txn] 150 error_check_good txn [is_valid_txn $txn $masterenv] TRUE 151 set db [eval {berkdb_open_noerr -env $masterenv -errpfx MASTER \ 152 -txn $txn -create -mode 0644} $largs $omethod $testfile2] 153 error_check_good dbopen [is_valid_db $db] TRUE 154 155 # Flush on the 2nd handle 156 set lf [stat_field $2ndenv log_stat "Times log flushed to disk"] 157 error_check_good flush [$2ndenv log_flush] 0 158 set lf2 [stat_field $2ndenv log_stat "Times log flushed to disk"] 159 error_check_bad log_flush $lf $lf2 160 161 # The detection of dead log handle is based on a 1-second resolution 162 # timestamp comparison. Now that we've established the threatening 163 # source of the dead handle in $2ndenv, wait a moment to make sure that 164 # the fresh handle that we're about to create gets a later timestamp. 165 tclsleep 1 166 167 # Resolve the txn and close the database 168 error_check_good commit [$txn commit] 0 169 error_check_good close [$db close] 0 170 171 # Nuke those messages for client about to become master. 172 replclear 2 173 174 puts "\tRep$tnum.d: Swap envs" 175 set masterenv $env1 176 set clientenv $env0 177 error_check_good downgrade [$clientenv rep_start -client] 0 178 error_check_good upgrade [$masterenv rep_start -master] 0 179 set envlist "{$env0 1} {$env1 2}" 180 process_msgs $envlist 181 182 # 183 # At this point, env0 should have rolled back across the log file. 184 # We need to do some operations on the master, process them on 185 # the client (but not a commit because that flushes). We want 186 # the message processing client env (env0) to put records in 187 # the log buffer and the 2nd env handle to flush the log. 188 # 189 puts "\tRep$tnum.e: Run test until create new log file." 190 # 191 # Set this to the last log file the old master had. 192 # 193 set last_client_log $last_master_log 194 set last_master_log [get_logfile $masterenv last] 195 set stop 0 196 while { $stop == 0 } { 197 puts "\tRep$tnum.b: Run test on master until log file changes." 198 eval rep_test\ 199 $method $masterenv NULL $niter $nstart $nstart 0 0 $largs 200 process_msgs $envlist 201 incr nstart $niter 202 set last_master_log [get_logfile $masterenv last] 203 if { $last_master_log == $last_client_log } { 204 set stop 1 205 } 206 } 207 puts "\tRep$tnum.f: Create some log records." 208 set txn [$masterenv txn] 209 error_check_good txn [is_valid_txn $txn $masterenv] TRUE 210 set db [eval {berkdb_open_noerr -env $masterenv -errpfx MASTER \ 211 -txn $txn -create -mode 0644} $largs $omethod $testfile2] 212 error_check_good dbopen [is_valid_db $db] TRUE 213 214 process_msgs $envlist 215 # Flush on the 2nd handle 216 puts "\tRep$tnum.g: Flush on 2nd env handle." 217 set lf [stat_field $2ndenv log_stat "Times log flushed to disk"] 218 error_check_good flush [$2ndenv log_flush] 0 219 set lf2 [stat_field $2ndenv log_stat "Times log flushed to disk"] 220 error_check_bad log_flush2 $lf $lf2 221 222 # Resolve the txn and close the database 223 puts "\tRep$tnum.h: Process commit on client env handle." 224 error_check_good commit [$txn commit] 0 225 error_check_good close [$db close] 0 226 process_msgs $envlist 227 228 error_check_good cl2_close [$2ndenv close] 0 229 error_check_good env0_close [$env0 close] 0 230 error_check_good env1_close [$env1 close] 0 231 replclose $testdir/MSGQUEUEDIR 232 return 233} 234 235