1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2001-2009 Oracle. All rights reserved. 4# 5# $Id$ 6# 7# TEST rep078 8# TEST 9# TEST Replication and basic lease test. 10# TEST Set leases on master and 2 clients. 11# TEST Do a lease operation and process to all clients. 12# TEST Read with lease on master. Do another lease operation 13# TEST and don't process on any client. Try to read with 14# TEST on the master and verify it fails. Process the messages 15# TEST to the clients and retry the read. 16# 17proc rep078 { method { tnum "078" } args } { 18 source ./include.tcl 19 global databases_in_memory 20 global repfiles_in_memory 21 22 if { $is_windows9x_test == 1 } { 23 puts "Skipping replication test on Win9x platform." 24 return 25 } 26 27 # Valid for all access methods. Other lease tests limit the 28 # test because there is nothing method-specific being tested. 29 # Use all methods for this basic test. 30 if { $checking_valid_methods } { 31 return "ALL" 32 } 33 34 set args [convert_args $method $args] 35 set logsets [create_logsets 3] 36 37 # Set up for on-disk or in-memory databases. 38 set msg "using on-disk databases" 39 if { $databases_in_memory } { 40 set msg "using named in-memory databases" 41 if { [is_queueext $method] } { 42 puts -nonewline "Skipping rep$tnum for method " 43 puts "$method with named in-memory databases." 44 return 45 } 46 } 47 set msg2 "and on-disk replication files" 48 if { $repfiles_in_memory } { 49 set msg2 "and in-memory replication files" 50 } 51 52 # Run the body of the test with and without recovery, 53 # and with and without cleaning. Skip recovery with in-memory 54 # logging - it doesn't make sense. 55 # 56 # Also skip the case where the master is in-memory and at least 57 # one of the clients is on-disk. If the master is in-memory, 58 # the wrong site gets elected because on-disk envs write a log 59 # record when they create the env and in-memory ones do not 60 # and the test wants to control which env gets elected. 61 # 62 foreach r $test_recopts { 63 foreach l $logsets { 64 set logindex [lsearch -exact $l "in-memory"] 65 if { $r == "-recover" && $logindex != -1 } { 66 puts "Skipping rep$tnum for -recover\ 67 with in-memory logs." 68 continue 69 } 70 set master_logs [lindex $l 0] 71 if { $master_logs == "in-memory" } { 72 set client_logs [lsearch -exact $l "on-disk"] 73 if { $client_logs != -1 } { 74 puts "Skipping for in-memory master\ 75 and on-disk client." 76 continue 77 } 78 } 79 80 puts "Rep$tnum ($method $r): Replication\ 81 and basic master leases $msg $msg2." 82 puts "Rep$tnum: Master logs are [lindex $l 0]" 83 puts "Rep$tnum: Client 1 logs are [lindex $l 1]" 84 puts "Rep$tnum: Client 2 logs are [lindex $l 2]" 85 rep078_sub $method $tnum $l $r $args 86 } 87 } 88} 89 90proc rep078_sub { method tnum logset recargs largs } { 91 source ./include.tcl 92 global testdir 93 global databases_in_memory 94 global repfiles_in_memory 95 global rep_verbose 96 global verbose_type 97 98 set verbargs "" 99 if { $rep_verbose == 1 } { 100 set verbargs " -verbose {$verbose_type on} " 101 } 102 103 set repmemargs "" 104 if { $repfiles_in_memory } { 105 set repmemargs "-rep_inmem_files " 106 } 107 108 env_cleanup $testdir 109 110 set qdir $testdir/MSGQUEUEDIR 111 replsetup $qdir 112 113 set masterdir $testdir/MASTERDIR 114 set clientdir $testdir/CLIENTDIR 115 set clientdir2 $testdir/CLIENTDIR2 116 117 file mkdir $masterdir 118 file mkdir $clientdir 119 file mkdir $clientdir2 120 121 set m_logtype [lindex $logset 0] 122 set c_logtype [lindex $logset 1] 123 set c2_logtype [lindex $logset 2] 124 125 # In-memory logs require a large log buffer, and cannot 126 # be used with -txn nosync. 127 set m_logargs [adjust_logargs $m_logtype] 128 set c_logargs [adjust_logargs $c_logtype] 129 set c2_logargs [adjust_logargs $c2_logtype] 130 set m_txnargs [adjust_txnargs $m_logtype] 131 set c_txnargs [adjust_txnargs $c_logtype] 132 set c2_txnargs [adjust_txnargs $c2_logtype] 133 134 # Set leases for 3 sites, 3 second timeout, 0% clock skew 135 set nsites 3 136 set lease_to 3000000 137 set lease_tosec [expr $lease_to / 1000000] 138 set clock_fast 0 139 set clock_slow 0 140 set testfile test.db 141 # 142 # Since we have to use elections, the election code 143 # assumes a 2-off site id scheme. 144 # Open a master. 145 repladd 2 146 set err_cmd(0) "none" 147 set crash(0) 0 148 set pri(0) 100 149 # 150 # Note that using the default clock skew should be the same 151 # as specifying "no skew" through the API. We want to 152 # test both API usages here. 153 # 154 set envcmd(0) "berkdb_env -create $m_txnargs $m_logargs \ 155 $verbargs -errpfx MASTER -home $masterdir \ 156 -rep_lease \[list $nsites $lease_to\] \ 157 -event rep_event $repmemargs \ 158 -rep_client -rep_transport \[list 2 replsend\]" 159 set masterenv [eval $envcmd(0) $recargs] 160 error_check_good master_env [is_valid_env $masterenv] TRUE 161 162 # Open two clients. 163 repladd 3 164 set err_cmd(1) "none" 165 set crash(1) 0 166 set pri(1) 10 167 set envcmd(1) "berkdb_env -create $c_txnargs $c_logargs \ 168 $verbargs -errpfx CLIENT -home $clientdir \ 169 -rep_lease \[list $nsites $lease_to $clock_fast $clock_slow\] \ 170 -event rep_event $repmemargs \ 171 -rep_client -rep_transport \[list 3 replsend\]" 172 set clientenv [eval $envcmd(1) $recargs] 173 error_check_good client_env [is_valid_env $clientenv] TRUE 174 175 repladd 4 176 set err_cmd(2) "none" 177 set crash(2) 0 178 set pri(2) 10 179 set envcmd(2) "berkdb_env -create $c2_txnargs $c2_logargs \ 180 $verbargs -errpfx CLIENT2 -home $clientdir2 \ 181 -rep_lease \[list $nsites $lease_to\] \ 182 -event rep_event $repmemargs \ 183 -rep_client -rep_transport \[list 4 replsend\]" 184 set clientenv2 [eval $envcmd(2) $recargs] 185 error_check_good client_env [is_valid_env $clientenv2] TRUE 186 187 # Bring the clients online by processing the startup messages. 188 set envlist "{$masterenv 2} {$clientenv 3} {$clientenv2 4}" 189 process_msgs $envlist 190 191 # 192 # Run election to get a master. Leases prevent us from 193 # simply assigning a master. 194 # 195 set msg "Rep$tnum.a" 196 puts "\tRep$tnum.a: Run initial election." 197 set nvotes $nsites 198 set winner 0 199 setpriority pri $nsites $winner 200 set elector [berkdb random_int 0 2] 201 # 202 # Note we send in a 0 for nsites because we set nsites back 203 # when we started running with leases. Master leases require 204 # that nsites be set before calling rep_start, and master leases 205 # require that the nsites arg to rep_elect be 0. 206 # 207 run_election envcmd envlist err_cmd pri crash $qdir $msg \ 208 $elector 0 $nvotes $nsites $winner 0 NULL 209 210 puts "\tRep$tnum.b: Spawn a child tclsh to do txn work." 211 set pid [exec $tclsh_path $test_path/wrap.tcl \ 212 rep078script.tcl $testdir/rep078script.log \ 213 $masterdir $testfile $method &] 214 215 # Let child run, create database and put a txn into it. 216 # Process messages while we wait for the child to complete 217 # its txn so that the clients can grant leases. 218 puts "\tRep$tnum.c: Wait for child to write txn." 219 while { 1 } { 220 if { [file exists $testdir/marker.db] == 0 } { 221 tclsleep 1 222 } else { 223 set markerenv [berkdb_env -home $testdir -txn] 224 error_check_good markerenv_open \ 225 [is_valid_env $markerenv] TRUE 226 set marker [berkdb_open -unknown -env $markerenv \ 227 -auto_commit marker.db] 228 set kd [$marker get CHILD1] 229 while { [llength $kd] == 0 } { 230 process_msgs $envlist 231 tclsleep 1 232 set kd [$marker get CHILD1] 233 } 234 process_msgs $envlist 235 # 236 # Child sends us the key it used as the data 237 # of the CHILD1 key. 238 # 239 set key [lindex [lindex $kd 0] 1] 240 break 241 } 242 } 243 set masterdb [eval \ 244 {berkdb_open_noerr -env $masterenv -rdonly $testfile}] 245 error_check_good dbopen [is_valid_db $masterdb] TRUE 246 247 process_msgs $envlist 248 set omethod [convert_method $method] 249 set clientdb [eval {berkdb_open_noerr \ 250 -env $clientenv $omethod -rdonly $testfile}] 251 error_check_good dbopen [is_valid_db $clientdb] TRUE 252 253 set uselease "" 254 set ignorelease "-nolease" 255 puts "\tRep$tnum.d.0: Read with leases." 256 check_leaseget $masterdb $key $uselease 0 257 check_leaseget $clientdb $key $uselease 0 258 puts "\tRep$tnum.d.1: Read ignoring leases." 259 check_leaseget $masterdb $key $ignorelease 0 260 check_leaseget $clientdb $key $ignorelease 0 261 # 262 # This should fail because the lease is expired and all 263 # attempts by master to refresh it will not be processed. 264 # 265 set sleep [expr $lease_tosec + 1] 266 puts "\tRep$tnum.e.0: Sleep $sleep secs to expire leases and read again." 267 tclsleep $sleep 268 # 269 # Verify the master gets REP_LEASE_EXPIRED. Verify that the 270 # read on the client ignores leases and succeeds. 271 # 272 check_leaseget $masterdb $key $uselease REP_LEASE_EXPIRED 273 check_leaseget $clientdb $key $uselease 0 274 puts "\tRep$tnum.e.1: Read ignoring leases." 275 check_leaseget $masterdb $key $ignorelease 0 276 check_leaseget $clientdb $key $ignorelease 0 277 278 error_check_good timestamp_done \ 279 [$marker put PARENT1 [timestamp -r]] 0 280 281 set kd [$marker get CHILD2] 282 while { [llength $kd] == 0 } { 283 process_msgs $envlist 284 tclsleep 1 285 set kd [$marker get CHILD2] 286 } 287 process_msgs $envlist 288 # 289 # Child sends us the key it used as the data 290 # of the CHILD2 key. 291 # 292 set key [lindex [lindex $kd 0] 1] 293 294 puts "\tRep$tnum.f: Child writes txn + ckp. Don't process msgs." 295 # 296 # Child has committed the txn and we have processed it. Now 297 # signal the child process to put a checkpoint, which we 298 # will not process. That will invalidate leases. 299 error_check_good timestamp_done \ 300 [$marker put PARENT2 [timestamp -r]] 0 301 302 set kd [$marker get CHILD3] 303 while { [llength $kd] == 0 } { 304 tclsleep 1 305 set kd [$marker get CHILD3] 306 } 307 308 puts "\tRep$tnum.f.0: Read using leases fails." 309 check_leaseget $masterdb $key $uselease REP_LEASE_EXPIRED 310 puts "\tRep$tnum.f.1: Read ignoring leases." 311 check_leaseget $masterdb $key $ignorelease 0 312 puts "\tRep$tnum.g: Process messages to clients." 313 process_msgs $envlist 314 puts "\tRep$tnum.h: Verify read with leases now succeeds." 315 check_leaseget $masterdb $key $uselease 0 316 317 watch_procs $pid 5 318 319 process_msgs $envlist 320 puts "\tRep$tnum.i: Downgrade master." 321 $masterenv rep_start -client 322 process_msgs $envlist 323 324 rep_verify $masterdir $masterenv $clientdir $clientenv 325 process_msgs $envlist 326 rep_verify $masterdir $masterenv $clientdir2 $clientenv2 0 1 0 327 328 # Clean up. 329 error_check_good marker_db_close [$marker close] 0 330 error_check_good marker_env_close [$markerenv close] 0 331 error_check_good masterdb_close [$masterdb close] 0 332 error_check_good masterdb_close [$clientdb close] 0 333 error_check_good masterenv_close [$masterenv close] 0 334 error_check_good clientenv_close [$clientenv close] 0 335 error_check_good clientenv_close [$clientenv2 close] 0 336 337 replclose $testdir/MSGQUEUEDIR 338 339 # Check log file for failures. 340 set errstrings [eval findfail $testdir/rep078script.log] 341 foreach str $errstrings { 342 puts "FAIL: error message in rep078 log file: $str" 343 } 344} 345 346