1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2004,2008 Oracle. All rights reserved. 4# 5# $Id: rep061.tcl,v 1.14 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST rep061 8# TEST Test of internal initialization multiple files and pagesizes 9# TEST with page gaps. 10# TEST 11# TEST One master, one client. 12# TEST Generate several log files. 13# TEST Remove old master log files. 14# TEST Delete client files and restart client. 15# TEST Put one more record to the master. 16# TEST Force some page messages to get dropped. 17# 18proc rep061 { method { niter 500 } { tnum "061" } args } { 19 20 source ./include.tcl 21 if { $is_windows9x_test == 1 } { 22 puts "Skipping replication test on Win 9x platform." 23 return 24 } 25 26 # Run for btree and queue only. 27 if { $checking_valid_methods } { 28 set test_methods {} 29 foreach method $valid_methods { 30 if { [is_btree $method] == 1 || [is_queue $method] == 1 } { 31 lappend test_methods $method 32 } 33 } 34 return $test_methods 35 } 36 if { [is_btree $method] != 1 && [is_queue $method] != 1 } { 37 puts "Skipping rep061 for method $method." 38 return 39 } 40 set args [convert_args $method $args] 41 42 # This test needs to set its own pagesize. 43 set pgindex [lsearch -exact $args "-pagesize"] 44 if { $pgindex != -1 } { 45 puts "Rep$tnum: skipping for specific pagesizes" 46 return 47 } 48 49 set logsets [create_logsets 2] 50 51 # Run the body of the test with and without recovery, 52 # and with and without cleaning. 53 set opts { noclean clean bulk } 54 # Try varying drop percentages. 55 set dpct { 10 5 } 56 foreach r $test_recopts { 57 foreach c $opts { 58 foreach l $logsets { 59 foreach d $dpct { 60 set logindex [lsearch -exact $l \ 61 "in-memory"] 62 if { $r == "-recover" && \ 63 $logindex != -1 } { 64 puts "Skipping rep$tnum \ 65 for -recover\ 66 with in-memory logs." 67 continue 68 } 69 puts "Rep$tnum ($method $r $c):\ 70 Internal initialization - with\ 71 $d pct page gaps." 72 puts "Rep$tnum: Master logs are \ 73 [lindex $l 0]" 74 puts "Rep$tnum: Client logs are \ 75 [lindex $l 1]" 76 rep061_sub $method $niter $tnum \ 77 $l $r $c $d $args 78 } 79 } 80 } 81 } 82} 83 84proc rep061_sub { method niter tnum logset recargs opts dpct largs } { 85 global testdir 86 global util_path 87 global drop drop_msg 88 global startup_done 89 global rep_verbose 90 global verbose_type 91 92 set verbargs "" 93 if { $rep_verbose == 1 } { 94 set verbargs " -verbose {$verbose_type on} " 95 } 96 97 env_cleanup $testdir 98 99 replsetup $testdir/MSGQUEUEDIR 100 101 set masterdir $testdir/MASTERDIR 102 set clientdir $testdir/CLIENTDIR 103 104 file mkdir $masterdir 105 file mkdir $clientdir 106 107 # Log size is small so we quickly create more than one. 108 # The documentation says that the log file must be at least 109 # four times the size of the in-memory log buffer. 110 set maxpg 16384 111 set log_max [expr $maxpg * 8] 112 set cache [expr $maxpg * 32 ] 113 114 set m_logtype [lindex $logset 0] 115 set c_logtype [lindex $logset 1] 116 117 # In-memory logs cannot be used with -txn nosync. 118 set m_txnargs [adjust_txnargs $m_logtype] 119 set c_txnargs [adjust_txnargs $c_logtype] 120 121 # Open a master. 122 repladd 1 123 set ma_envcmd "berkdb_env_noerr -create $m_txnargs $verbargs \ 124 -log_max $log_max -cachesize { 0 $cache 1 } -errpfx MASTER \ 125 -home $masterdir -rep_transport \[list 1 replsend\]" 126 set masterenv [eval $ma_envcmd $recargs -rep_master] 127 128 # Open a client 129 repladd 2 130 set cl_envcmd "berkdb_env_noerr -create $c_txnargs $verbargs \ 131 -log_max $log_max -cachesize { 0 $cache 1 } -errpfx CLIENT \ 132 -home $clientdir -rep_transport \[list 2 replsend\]" 133 set clientenv [eval $cl_envcmd $recargs -rep_client] 134 135 # 136 # Since we're dropping messages, set the rerequest values 137 # lower so we don't wait too long to request what we're 138 # missing. 139 # 140 # 141 # Set to 200/800 usecs. An average ping to localhost should 142 # be a few 10s usecs. 143 # 144 $clientenv rep_request 200 800 145 # Bring the clients online by processing the startup messages. 146 set envlist "{$masterenv 1} {$clientenv 2}" 147 process_msgs $envlist 148 149 # Clobber replication's 30-second anti-archive timer, which will have 150 # been started by client sync-up internal init, so that we can do a 151 # log_archive in a moment. 152 # 153 $masterenv test force noarchive_timeout 154 155 # 156 # Note that by setting these 2 globals below, message dropping 157 # is automatically enabled. By setting 'drop' to 0, further 158 # down in the test, we disable message dropping. 159 # 160 set drop 1 161 set drop_msg [expr 100 / $dpct] 162 163 # Run rep_test in the master (and update client). 164 set startpgsz 512 165 set pglist "" 166 for { set pgsz $startpgsz } { $pgsz <= $maxpg } \ 167 { set pgsz [expr $pgsz * 2] } { 168 lappend pglist $pgsz 169 } 170 set nfiles [llength $pglist] 171 puts "\tRep$tnum.a.0: Running rep_test $nfiles times in replicated env." 172 set dbopen "" 173 for { set i 0 } { $i < $nfiles } { incr i } { 174 set mult [expr $i * 10] 175 set nentries [expr $niter + $mult] 176 set pagesize [lindex $pglist $i] 177 set largs " -pagesize $pagesize " 178 eval rep_test $method $masterenv NULL $nentries $mult $mult \ 179 0 0 $largs 180 process_msgs $envlist 181 182 # 183 # Everytime we run 'rep_test' we create 'test.db'. So 184 # rename it each time through the loop. 185 # 186 set old "test.db" 187 set new "test.$i.db" 188 error_check_good rename [$masterenv dbrename \ 189 -auto_commit $old $new] 0 190 process_msgs $envlist 191 # 192 # We want to keep some databases open so that we test the 193 # code finding the files in the data dir as well as finding 194 # them in dbreg list. 195 # 196 if { [expr $i % 2 ] == 0 } { 197 set db [berkdb_open_noerr -env $masterenv $new] 198 error_check_good dbopen.$i [is_valid_db $db] TRUE 199 lappend dbopen $db 200 } 201 } 202 # 203 # Set up a few special databases too. We want one with a subdatabase 204 # and we want an empty database. 205 # 206 set testfile "test.db" 207 if { [is_queue $method] } { 208 set sub "" 209 } else { 210 set sub "subdb" 211 } 212 set omethod [convert_method $method] 213 set largs " -pagesize $maxpg " 214 set largs [convert_args $method $largs] 215 set emptyfile "empty.db" 216 # 217 # Create/close an empty database. 218 # 219 set db [eval {berkdb_open_noerr -env $masterenv -auto_commit -create \ 220 -mode 0644} $largs $omethod $emptyfile] 221 error_check_good emptydb [is_valid_db $db] TRUE 222 error_check_good empty_close [$db close] 0 223 # 224 # Keep this subdb (regular if queue) database open. 225 # We need it a few times later on. 226 # 227 set db [eval {berkdb_open_noerr -env $masterenv -auto_commit -create \ 228 -mode 0644} $largs $omethod $testfile $sub] 229 error_check_good subdb [is_valid_db $db] TRUE 230 eval rep_test $method $masterenv $db $niter 0 0 0 0 $largs 231 process_msgs $envlist 232 233 puts "\tRep$tnum.b: Close client." 234 error_check_good client_close [$clientenv close] 0 235 236 # 237 # Run rep_test in the master (don't update client). 238 # Need to guarantee that we will change log files during 239 # this run so run with the largest pagesize and double 240 # the number of entries. 241 # 242 puts "\tRep$tnum.c: Running rep_test ( $largs) in replicated env." 243 set nentries [expr $niter * 2] 244 eval rep_test $method $masterenv $db $nentries 0 0 0 0 $largs 245 replclear 2 246 247 puts "\tRep$tnum.d: Run db_archive on master." 248 set res [eval exec $util_path/db_archive -l -h $masterdir] 249 error_check_bad log.1.present [lsearch -exact $res log.0000000001] -1 250 set res [eval exec $util_path/db_archive -d -h $masterdir] 251 set res [eval exec $util_path/db_archive -l -h $masterdir] 252 error_check_good log.1.gone [lsearch -exact $res log.0000000001] -1 253 254 puts "\tRep$tnum.e: Reopen client ($opts)." 255 if { $opts == "clean" } { 256 env_cleanup $clientdir 257 } 258 if { $opts == "bulk" } { 259 error_check_good bulk [$masterenv rep_config {bulk on}] 0 260 } 261 262 set clientenv [eval $cl_envcmd $recargs -rep_client] 263 error_check_good client_env [is_valid_env $clientenv] TRUE 264 # 265 # Since we are dropping frequent messages, we set the 266 # rerequest rate low to make sure the test finishes. 267 # 268 $clientenv rep_request 200 800 269 set envlist "{$masterenv 1} {$clientenv 2}" 270 process_msgs $envlist 0 NONE err 271 set done 0 272 # 273 # We are done with this loop when the client has achieved 274 # startup_done and we've looped one more time after turning 275 # off dropping messages. Otherwise we might get a few 276 # straggling log records that don't make it over. 277 # 278 # Set a maximum iteration count because some methods can get 279 # into a state where if we're regularly dropping messages we 280 # can never catch up (queue) and we loop forever. 281 # 282 set iter 1 283 set max_drop_iter 200 284 if { $opts == "bulk" } { 285 # 286 # Since bulk is sending several messages at once we need to 287 # loop more times to allow rerequests to get through. 288 # 289 set max_drop_iter [expr $max_drop_iter * 2] 290 $clientenv rep_request 100 400 291 } 292 while { $done == 0 } { 293 puts "\tRep$tnum.e.1.$iter: Trigger log request" 294 # 295 # When we don't clean, starting the client doesn't 296 # trigger any events. We need to generate some log 297 # records so that the client requests the missing 298 # logs and that will trigger it. 299 # 300 set entries 4 301 eval rep_test $method $masterenv $db $entries $niter 0 0 0 $largs 302 process_msgs $envlist 0 NONE err 303 set stat [exec $util_path/db_stat -N -r -R A -h $clientdir] 304 # 305 # Loop until we are done with the RECOVER_PAGE phase. 306 # 307 set in_page [is_substr $stat "REP_F_RECOVER_PAGE"] 308 if { !$in_page || $iter >= $max_drop_iter } { 309 # 310 # If we're dropping, stop doing so. 311 # If we're not dropping, we're done. 312 # 313 if { $drop != 0 } { 314 set drop 0 315 } else { 316 set done 1 317 } 318 } 319 incr iter 320 } 321 error_check_good subdb_close [$db close] 0 322 # 323 # Stop dropping records, we've sent all the pages. 324 # We need to do that in order to make sure we get 325 # all the log records there and can accurately compare. 326 # 327 set drop 0 328 process_msgs $envlist 0 NONE err 329 330 puts "\tRep$tnum.f: Verify logs and databases" 331 # 332 # If doing bulk testing, turn it off now so that it forces us 333 # to flush anything currently in the bulk buffer. We need to 334 # do this because rep_test might have aborted a transaction on 335 # its last iteration and those log records would still be in 336 # the bulk buffer causing the log comparison to fail. 337 # 338 if { $opts == "bulk" } { 339 puts "\tRep$tnum.f.1: Turn off bulk transfers." 340 error_check_good bulk [$masterenv rep_config {bulk off}] 0 341 process_msgs $envlist 0 NONE err 342 } 343 rep_verify $masterdir $masterenv $clientdir $clientenv 1 344 345 for { set i 0 } { $i < $nfiles } { incr i } { 346 set dbname "test.$i.db" 347 rep_verify $masterdir $masterenv $clientdir $clientenv \ 348 1 1 0 $dbname 349 } 350 351 # 352 # Close the database held open on master for initialization. 353 # 354 foreach db $dbopen { 355 error_check_good db_close [$db close] 0 356 } 357 358 # Add records to the master and update client. 359 puts "\tRep$tnum.g: Add more records and check again." 360 set entries 10 361 set db [eval {berkdb_open_noerr -env $masterenv -auto_commit \ 362 -mode 0644} $largs $omethod $testfile $sub] 363 error_check_good subdb [is_valid_db $db] TRUE 364 eval rep_test $method $masterenv $db $entries $niter 0 0 0 $largs 365 error_check_good subdb_close [$db close] 0 366 process_msgs $envlist 0 NONE err 367 368 rep_verify $masterdir $masterenv $clientdir $clientenv 1 369 for { set i 0 } { $i < $nfiles } { incr i } { 370 set dbname "test.$i.db" 371 rep_verify $masterdir $masterenv $clientdir $clientenv \ 372 1 1 0 $dbname 373 } 374 set bulkxfer [stat_field $masterenv rep_stat "Bulk buffer transfers"] 375 if { $opts == "bulk" } { 376 error_check_bad bulkxferon $bulkxfer 0 377 } else { 378 error_check_good bulkxferoff $bulkxfer 0 379 } 380 381 error_check_good masterenv_close [$masterenv close] 0 382 error_check_good clientenv_close [$clientenv close] 0 383 replclose $testdir/MSGQUEUEDIR 384} 385