1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1996,2008 Oracle. All rights reserved. 4# 5# $Id: test044.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST test044 8# TEST Small system integration tests 9# TEST Test proper functioning of the checkpoint daemon, 10# TEST recovery, transactions, etc. 11# TEST 12# TEST System integration DB test: verify that locking, recovery, checkpoint, 13# TEST and all the other utilities basically work. 14# TEST 15# TEST The test consists of $nprocs processes operating on $nfiles files. A 16# TEST transaction consists of adding the same key/data pair to some random 17# TEST number of these files. We generate a bimodal distribution in key size 18# TEST with 70% of the keys being small (1-10 characters) and the remaining 19# TEST 30% of the keys being large (uniform distribution about mean $key_avg). 20# TEST If we generate a key, we first check to make sure that the key is not 21# TEST already in the dataset. If it is, we do a lookup. 22# 23# XXX 24# This test uses grow-only files currently! 25proc test044 { method {nprocs 5} {nfiles 10} {cont 0} args } { 26 source ./include.tcl 27 global encrypt 28 global rand_init 29 30 set args [convert_args $method $args] 31 set omethod [convert_method $method] 32 33 berkdb srand $rand_init 34 35 # If we are using an env, then skip this test. It needs its own. 36 set eindex [lsearch -exact $args "-env"] 37 if { $eindex != -1 } { 38 incr eindex 39 set env [lindex $args $eindex] 40 puts "Test044 skipping for env $env" 41 return 42 } 43 if { $encrypt != 0 } { 44 puts "Test044 skipping for security" 45 return 46 } 47 48 puts "Test044: system integration test db $method $nprocs processes \ 49 on $nfiles files" 50 51 # Parse options 52 set otherargs "" 53 set key_avg 10 54 set data_avg 20 55 set do_exit 0 56 for { set i 0 } { $i < [llength $args] } {incr i} { 57 switch -regexp -- [lindex $args $i] { 58 -key_avg { incr i; set key_avg [lindex $args $i] } 59 -data_avg { incr i; set data_avg [lindex $args $i] } 60 -testdir { incr i; set testdir [lindex $args $i] } 61 -x.* { set do_exit 1 } 62 default { 63 lappend otherargs [lindex $args $i] 64 } 65 } 66 } 67 68 if { $cont == 0 } { 69 # Create the database and open the dictionary 70 env_cleanup $testdir 71 72 # Create an environment 73 puts "\tTest044.a: creating environment and $nfiles files" 74 set dbenv [berkdb_env -create -txn -home $testdir] 75 error_check_good env_open [is_valid_env $dbenv] TRUE 76 77 # Create a bunch of files 78 set m $method 79 80 for { set i 0 } { $i < $nfiles } { incr i } { 81 if { $method == "all" } { 82 switch [berkdb random_int 1 2] { 83 1 { set m -btree } 84 2 { set m -hash } 85 } 86 } else { 87 set m $omethod 88 } 89 90 set db [eval {berkdb_open -env $dbenv -create \ 91 -mode 0644 $m} $otherargs {test044.$i.db}] 92 error_check_good dbopen [is_valid_db $db] TRUE 93 error_check_good db_close [$db close] 0 94 } 95 } 96 97 # Close the environment 98 $dbenv close 99 100 if { $do_exit == 1 } { 101 return 102 } 103 104 # Database is created, now fork off the kids. 105 puts "\tTest044.b: forking off $nprocs processes and utilities" 106 set cycle 1 107 set ncycles 3 108 while { $cycle <= $ncycles } { 109 set dbenv [berkdb_env -create -txn -home $testdir] 110 error_check_good env_open [is_valid_env $dbenv] TRUE 111 112 # Fire off deadlock detector and checkpointer 113 puts "Beginning cycle $cycle" 114 set ddpid [exec $util_path/db_deadlock -h $testdir -t 5 &] 115 set cppid [exec $util_path/db_checkpoint -h $testdir -p 2 &] 116 puts "Deadlock detector: $ddpid Checkpoint daemon $cppid" 117 118 set pidlist {} 119 for { set i 0 } {$i < $nprocs} {incr i} { 120 set p [exec $tclsh_path \ 121 $test_path/sysscript.tcl $testdir \ 122 $nfiles $key_avg $data_avg $omethod \ 123 >& $testdir/test044.$i.log &] 124 lappend pidlist $p 125 } 126 set sleep [berkdb random_int 300 600] 127 puts \ 128"[timestamp] $nprocs processes running $pidlist for $sleep seconds" 129 tclsleep $sleep 130 131 # Now simulate a crash 132 puts "[timestamp] Crashing" 133 134 # 135 # The environment must remain open until this point to get 136 # proper sharing (using the paging file) on Win/9X. [#2342] 137 # 138 error_check_good env_close [$dbenv close] 0 139 140 tclkill $ddpid 141 tclkill $cppid 142 143 foreach p $pidlist { 144 tclkill $p 145 } 146 147 # Check for test failure 148 set errstrings [eval findfail [glob $testdir/test044.*.log]] 149 foreach str $errstrings { 150 puts "FAIL: error message in log file: $str" 151 } 152 153 # Now run recovery 154 test044_verify $testdir $nfiles 155 incr cycle 156 } 157} 158 159proc test044_usage { } { 160 puts -nonewline "test044 method nentries [-d directory] [-i iterations]" 161 puts " [-p procs] -x" 162} 163 164proc test044_verify { dir nfiles } { 165 source ./include.tcl 166 167 # Save everything away in case something breaks 168# for { set f 0 } { $f < $nfiles } {incr f} { 169# file copy -force $dir/test044.$f.db $dir/test044.$f.save1 170# } 171# foreach f [glob $dir/log.*] { 172# if { [is_substr $f save] == 0 } { 173# file copy -force $f $f.save1 174# } 175# } 176 177 # Run recovery and then read through all the database files to make 178 # sure that they all look good. 179 180 puts "\tTest044.verify: Running recovery and verifying file contents" 181 set stat [catch {exec $util_path/db_recover -h $dir} result] 182 if { $stat == 1 } { 183 error "FAIL: Recovery error: $result." 184 } 185 186 # Save everything away in case something breaks 187# for { set f 0 } { $f < $nfiles } {incr f} { 188# file copy -force $dir/test044.$f.db $dir/test044.$f.save2 189# } 190# foreach f [glob $dir/log.*] { 191# if { [is_substr $f save] == 0 } { 192# file copy -force $f $f.save2 193# } 194# } 195 196 for { set f 0 } { $f < $nfiles } { incr f } { 197 set db($f) [berkdb_open $dir/test044.$f.db] 198 error_check_good $f:dbopen [is_valid_db $db($f)] TRUE 199 200 set cursors($f) [$db($f) cursor] 201 error_check_bad $f:cursor_open $cursors($f) NULL 202 error_check_good \ 203 $f:cursor_open [is_substr $cursors($f) $db($f)] 1 204 } 205 206 for { set f 0 } { $f < $nfiles } { incr f } { 207 for {set d [$cursors($f) get -first] } \ 208 { [string length $d] != 0 } \ 209 { set d [$cursors($f) get -next] } { 210 211 set k [lindex [lindex $d 0] 0] 212 set d [lindex [lindex $d 0] 1] 213 214 set flist [zero_list $nfiles] 215 set r $d 216 while { [set ndx [string first : $r]] != -1 } { 217 set fnum [string range $r 0 [expr $ndx - 1]] 218 if { [lindex $flist $fnum] == 0 } { 219 set fl "-set" 220 } else { 221 set fl "-next" 222 } 223 224 if { $fl != "-set" || $fnum != $f } { 225 if { [string compare $fl "-set"] == 0} { 226 set full [$cursors($fnum) \ 227 get -set $k] 228 } else { 229 set full [$cursors($fnum) \ 230 get -next] 231 } 232 set key [lindex [lindex $full 0] 0] 233 set rec [lindex [lindex $full 0] 1] 234 error_check_good \ 235 $f:dbget_$fnum:key $key $k 236 error_check_good \ 237 $f:dbget_$fnum:data $rec $d 238 } 239 240 set flist [lreplace $flist $fnum $fnum 1] 241 incr ndx 242 set r [string range $r $ndx end] 243 } 244 } 245 } 246 247 for { set f 0 } { $f < $nfiles } { incr f } { 248 error_check_good $cursors($f) [$cursors($f) close] 0 249 error_check_good db_close:$f [$db($f) close] 0 250 } 251} 252