1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2004-2009 Oracle. All rights reserved. 4# 5# $Id$ 6# 7# TEST rep024 8# TEST Replication page allocation / verify test 9# TEST 10# TEST Start a master (site 1) and a client (site 2). Master 11# TEST closes (simulating a crash). Site 2 becomes the master 12# TEST and site 1 comes back up as a client. Verify database. 13 14proc rep024 { method { niter 1000 } { tnum "024" } args } { 15 16 source ./include.tcl 17 global databases_in_memory 18 global repfiles_in_memory 19 20 if { $is_windows9x_test == 1 } { 21 puts "Skipping replication test on Win 9x platform." 22 return 23 } 24 25 # Run for all access methods. 26 if { $checking_valid_methods } { 27 return "ALL" 28 } 29 30 global fixed_len 31 set orig_fixed_len $fixed_len 32 set fixed_len 448 33 set args [convert_args $method $args] 34 set logsets [create_logsets 2] 35 36 # This test is not appropriate for in-memory databases. 37 if { $databases_in_memory } { 38 puts "Skipping rep$tnum for named in-memory databases." 39 return 40 } 41 42 set msg2 "and on-disk replication files" 43 if { $repfiles_in_memory } { 44 set msg2 "and in-memory replication files" 45 } 46 47 # Run all tests with and without recovery. 48 set envargs "" 49 foreach r $test_recopts { 50 foreach l $logsets { 51 set logindex [lsearch -exact $l "in-memory"] 52 if { $r == "-recover" && $logindex != -1 } { 53 puts "Rep$tnum: Skipping\ 54 for in-memory logs with -recover." 55 continue 56 } 57 puts "Rep$tnum ($method $r): \ 58 Replication page allocation/verify test $msg2." 59 puts "Rep$tnum: Master logs are [lindex $l 0]" 60 puts "Rep$tnum: Client logs are [lindex $l 1]" 61 rep024_sub $method $niter $tnum $envargs $l $r $args 62 } 63 } 64 set fixed_len $orig_fixed_len 65 return 66} 67 68proc rep024_sub { method niter tnum envargs logset recargs largs } { 69 source ./include.tcl 70 global repfiles_in_memory 71 global rep_verbose 72 global verbose_type 73 74 set verbargs "" 75 if { $rep_verbose == 1 } { 76 set verbargs " -verbose {$verbose_type on} " 77 } 78 79 set repmemargs "" 80 if { $repfiles_in_memory } { 81 set repmemargs "-rep_inmem_files " 82 } 83 84 env_cleanup $testdir 85 86 replsetup $testdir/MSGQUEUEDIR 87 88 set masterdir $testdir/MASTERDIR 89 set clientdir $testdir/CLIENTDIR 90 91 file mkdir $masterdir 92 file mkdir $clientdir 93 set m_logtype [lindex $logset 0] 94 set c_logtype [lindex $logset 1] 95 96 # In-memory logs require a large log buffer, and cannot 97 # be used with -txn nosync. This test requires -txn, so 98 # we only have to adjust the logargs. 99 set m_logargs [adjust_logargs $m_logtype] 100 set c_logargs [adjust_logargs $c_logtype] 101 102 # Open a master. 103 repladd 1 104 set env_cmd(1) "berkdb_env_noerr -create $repmemargs \ 105 -log_max 1000000 $envargs $recargs -home $masterdir \ 106 -errpfx MASTER $verbargs -txn $m_logargs \ 107 -rep_transport \[list 1 replsend\]" 108 set masterenv [eval $env_cmd(1) -rep_master] 109 110 # Open a client 111 repladd 2 112 set env_cmd(2) "berkdb_env_noerr -create $repmemargs \ 113 -log_max 1000000 $envargs $recargs -home $clientdir \ 114 -errpfx CLIENT $verbargs -txn $c_logargs \ 115 -rep_transport \[list 2 replsend\]" 116 set clientenv [eval $env_cmd(2) -rep_client] 117 118 # Bring the client online by processing the startup messages. 119 set envlist "{$masterenv 1} {$clientenv 2}" 120 process_msgs $envlist 121 122 puts "\tRep$tnum.a: Add data to master, update client." 123 # 124 # This test uses a small page size and a large fixed_len 125 # so it is easy to force a page allocation. 126 set key [expr $niter + 1] 127 set data A 128 set pagesize 512 129 if { [is_fixed_length $method] == 1 } { 130 set bigdata [repeat $data [expr $pagesize / 2]] 131 } else { 132 set bigdata [repeat $data [expr 2 * $pagesize]] 133 } 134 135 set omethod [convert_method $method] 136 set testfile "test$tnum.db" 137 set db [eval "berkdb_open_noerr -create $omethod -auto_commit \ 138 -pagesize $pagesize -env $masterenv $largs $testfile"] 139 eval rep_test $method $masterenv $db $niter 0 0 0 0 $largs 140 $masterenv txn_checkpoint 141 process_msgs $envlist 142 143 # Close client. Force a page allocation on the master. 144 # An overflow page (or big page, for hash) will do the job. 145 # 146 puts "\tRep$tnum.b: Close client, force page allocation on master." 147 error_check_good client_close [$clientenv close] 0 148 149 error_check_good client_verify \ 150 [verify_dir $clientdir "\tRep$tnum.b: " 0 0 1 0 0] 0 151 152 set pages1 [r24_check_pages $db $method] 153 set txn [$masterenv txn] 154 error_check_good put_bigdata [eval {$db put} \ 155 -txn $txn {$key [chop_data $method $bigdata]}] 0 156 error_check_good txn_commit [$txn commit] 0 157 158 # Verify that we have allocated new pages. 159 set pages2 [r24_check_pages $db $method] 160 set newpages [expr $pages2 - $pages1] 161 162 # Close master and discard messages for site 2. Now everybody 163 # is closed and sites 1 and 2 have different contents. 164 puts "\tRep$tnum.c: Close master." 165 error_check_good db_close [$db close] 0 166 error_check_good master_close [$masterenv close] 0 167 if { $newpages <= 0 } { 168 puts "FAIL: no new pages allocated." 169 return 170 } 171 error_check_good master_verify \ 172 [verify_dir $masterdir "\tRep$tnum.c: " 0 0 1] 0 173 174 # Run a loop, opening the original client as master and the 175 # original master as client. Test db_verify. 176 foreach option { "no new data" "add new data" } { 177 puts "\tRep$tnum.d: Swap master and client ($option)." 178 set newmasterenv [eval $env_cmd(2) -rep_master] 179 set newclientenv [eval $env_cmd(1) -rep_client] 180 set newmasterdir [$newmasterenv get_home] 181 set newclientdir [$newclientenv get_home] 182 set envlist "{$newmasterenv 2} {$newclientenv 1}" 183 process_msgs $envlist 184 if { $option == "add new data" } { 185 set key [expr $niter + 2] 186 set db [eval "berkdb_open_noerr -create $omethod \ 187 -auto_commit -pagesize $pagesize \ 188 -env $newmasterenv $largs $testfile"] 189 set pages1 [r24_check_pages $db $method] 190 set txn [$newmasterenv txn] 191 error_check_good put_bigdata [eval {$db put} \ 192 -txn $txn {$key [chop_data $method $bigdata]}] 0 193 error_check_good txn_commit [$txn commit] 0 194 set pages2 [r24_check_pages $db $method] 195 set newpages [expr $pages2 - $pages1] 196 error_check_good db_close [$db close] 0 197 process_msgs $envlist 198 } 199 puts "\tRep$tnum.e: Close master and client, run verify." 200 # 201 # Verify_dir will db_verify with its own private environment, 202 # which means any dirty pages still in our environment won't be 203 # noticed. So, make sure there are no dirty pages. Running 204 # checkpoint at the master flushes its cache, and replicating 205 # that checkpoint to the client makes the client flush its 206 # cache. 207 # 208 $newmasterenv txn_checkpoint 209 process_msgs $envlist 210 211 error_check_good newmasterenv_close [$newmasterenv close] 0 212 error_check_good newclientenv_close [$newclientenv close] 0 213 if { $newpages <= 0 } { 214 puts "FAIL: no new pages allocated." 215 return 216 } 217 # This test can leave unreferenced pages on systems without 218 # FTRUNCATE and that's OK, so set unref to 0. 219 error_check_good verify \ 220 [verify_dir $newmasterdir "\tRep$tnum.f: " 0 0 1 0 0] 0 221 error_check_good verify \ 222 [verify_dir $newclientdir "\tRep$tnum.g: " 0 0 1 0 0] 0 223 } 224 replclose $testdir/MSGQUEUEDIR 225} 226 227proc r24_check_pages { db method } { 228 if { [is_hash $method] == 1 } { 229 set pages [stat_field $db stat "Number of big pages"] 230 } elseif { [is_queue $method] == 1 } { 231 set pages [stat_field $db stat "Number of pages"] 232 } else { 233 set pages [stat_field $db stat "Overflow pages"] 234 } 235 return $pages 236} 237