1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2004,2008 Oracle. All rights reserved. 4# 5# $Id: rep036.tcl,v 12.15 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST rep036 8# TEST Multiple master processes writing to the database. 9# TEST One process handles all message processing. 10 11proc rep036 { method { niter 200 } { tnum "036" } args } { 12 13 source ./include.tcl 14 if { $is_windows9x_test == 1 } { 15 puts "Skipping replication test on Win 9x platform." 16 return 17 } 18 19 # Valid for btree only. 20 if { $checking_valid_methods } { 21 set test_methods { btree } 22 return $test_methods 23 } 24 if { [is_btree $method] == 0 } { 25 puts "Rep$tnum: Skipping for method $method." 26 return 27 } 28 29 set saved_args $args 30 set logsets [create_logsets 3] 31 32 foreach l $logsets { 33 set envargs "" 34 set args $saved_args 35 puts "Rep$tnum: Test sync-up recovery ($method)." 36 puts "Rep$tnum: Master logs are [lindex $l 0]" 37 puts "Rep$tnum: Client 0 logs are [lindex $l 1]" 38 puts "Rep$tnum: Client 1 logs are [lindex $l 2]" 39 rep036_sub $method $niter $tnum $envargs $l $args 40 } 41} 42 43proc rep036_sub { method niter tnum envargs logset args } { 44 source ./include.tcl 45 global rep_verbose 46 global verbose_type 47 48 set verbargs "" 49 if { $rep_verbose == 1 } { 50 set verbargs " -verbose {$verbose_type on} " 51 } 52 53 env_cleanup $testdir 54 55 replsetup $testdir/MSGQUEUEDIR 56 57 set masterdir $testdir/MASTERDIR 58 set clientdir $testdir/CLIENTDIR 59 60 file mkdir $masterdir 61 file mkdir $clientdir 62 63 set m_logtype [lindex $logset 0] 64 set c_logtype [lindex $logset 1] 65 66 # In-memory logs require a large log buffer. 67 # We always run this test with -txn, so don't adjust txnargs. 68 set m_logargs [adjust_logargs $m_logtype] 69 set c_logargs [adjust_logargs $c_logtype] 70 71 # Open a master. 72 repladd 1 73 set env_cmd(M) "berkdb_env_noerr -create $verbargs \ 74 -log_max 1000000 $envargs -home $masterdir $m_logargs \ 75 -errpfx MASTER -errfile /dev/stderr -txn -rep_master \ 76 -rep_transport \[list 1 replsend\]" 77 set env1 [eval $env_cmd(M)] 78 79 # Open a client 80 repladd 2 81 set env_cmd(C) "berkdb_env_noerr -create $verbargs \ 82 -log_max 1000000 $envargs -home $clientdir $c_logargs \ 83 -errfile /dev/stderr -errpfx CLIENT -txn -rep_client \ 84 -rep_transport \[list 2 replsend\]" 85 set env2 [eval $env_cmd(C)] 86 87 # Bring the client online by processing the startup messages. 88 set envlist "{$env1 1} {$env2 2}" 89 process_msgs $envlist 90 91# # Start up deadlock detector. 92# # Commented out, as are two more sections below - see [#15049]. 93# set dpid [eval {exec $util_path/db_deadlock} \ 94# -a o -v -t 2.0 -h $masterdir >& $testdir/dd.parent.out &] 95 96 # Set up master database. 97 set testfile "rep$tnum.db" 98 set omethod [convert_method $method] 99 set mdb [eval {berkdb_open_noerr} -env $env1 -auto_commit \ 100 -create -mode 0644 $omethod $testfile] 101 error_check_good dbopen [is_valid_db $mdb] TRUE 102 103 # Put a record in the master database. 104 set key MAIN_KEY 105 set string MAIN_STRING 106 set t [$env1 txn] 107 error_check_good txn [is_valid_txn $t $env1] TRUE 108 set txn "-txn $t" 109 110 set ret [eval \ 111 {$mdb put} $txn {$key [chop_data $method $string]}] 112 error_check_good mdb_put $ret 0 113 error_check_good txn_commit [$t commit] 0 114 115 # Fork two writers that write to the master. 116 set pidlist {} 117 foreach writer { 1 2 } { 118 puts "\tRep$tnum.a: Fork child process WRITER$writer." 119 set pid [exec $tclsh_path $test_path/wrap.tcl \ 120 rep036script.tcl $testdir/rep036script.log.$writer \ 121 $masterdir $writer $niter btree &] 122 lappend pidlist $pid 123 } 124 125 # Run the main loop until the writers signal completion. 126 set i 0 127 while { [file exists $testdir/1.db] == 0 && \ 128 [file exists $testdir/2.db] == 0 } { 129 set string MAIN_STRING.$i 130 131 set t [$env1 txn] 132 error_check_good txn [is_valid_txn $t $env1] TRUE 133 set txn "-txn $t" 134 set ret [eval \ 135 {$mdb put} $txn {$key [chop_data $method $string]}] 136 137# # Writing to this database can deadlock. If we do, let the 138# # deadlock detector break the lock, wait a second, and try again. 139# while { [catch {eval {$mdb put}\ 140# $txn {$key [chop_data $method $string]}} ret] } { 141# # Make sure the failure is a deadlock. 142# error_check_good deadlock [is_substr $ret DB_LOCK_DEADLOCK] 1 143# tclsleep 1 144# } 145 146 147 error_check_good mdb_put $ret 0 148 error_check_good txn_commit [$t commit] 0 149 150 if { [expr $i % 10] == 0 } { 151 puts "\tRep036.c: Wrote MAIN record $i" 152 } 153 incr i 154 155 # Process messages. 156 process_msgs $envlist 157 158 # Wait a while, then do it all again. 159 tclsleep 1 160 } 161 162 163 # Confirm that the writers are done and process the messages 164 # once more to be sure the client is caught up. 165 watch_procs $pidlist 1 166 process_msgs $envlist 167 168# # We are done with the deadlock detector. 169# error_check_good kill_deadlock_detector [tclkill $dpid] "" 170 171 puts "\tRep$tnum.c: Verify logs and databases" 172 # Check that master and client logs and dbs are identical. 173 # Logs first ... 174 set stat [catch {eval exec $util_path/db_printlog \ 175 -h $masterdir > $masterdir/prlog} result] 176 error_check_good stat_mprlog $stat 0 177 set stat [catch {eval exec $util_path/db_printlog \ 178 -h $clientdir > $clientdir/prlog} result] 179 error_check_good mdb [$mdb close] 0 180 error_check_good stat_cprlog $stat 0 181# error_check_good log_cmp \ 182# [filecmp $masterdir/prlog $clientdir/prlog] 0 183 184 # ... now the databases. 185 set db1 [eval {berkdb_open_noerr -env $env1 -rdonly $testfile}] 186 set db2 [eval {berkdb_open_noerr -env $env2 -rdonly $testfile}] 187 188 error_check_good comparedbs [db_compare \ 189 $db1 $db2 $masterdir/$testfile $clientdir/$testfile] 0 190 error_check_good db1_close [$db1 close] 0 191 error_check_good db2_close [$db2 close] 0 192 193 error_check_good env1_close [$env1 close] 0 194 error_check_good env2_close [$env2 close] 0 195 replclose $testdir/MSGQUEUEDIR 196} 197