1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1996,2008 Oracle. All rights reserved. 4# 5# $Id: sysscript.tcl,v 12.7 2008/01/08 20:58:53 bostic Exp $ 6# 7# System integration test script. 8# This script runs a single process that tests the full functionality of 9# the system. The database under test contains nfiles files. Each process 10# randomly generates a key and some data. Both keys and data are bimodally 11# distributed between small keys (1-10 characters) and large keys (the avg 12# length is indicated via the command line parameter. 13# The process then decides on a replication factor between 1 and nfiles. 14# It writes the key and data to that many files and tacks on the file ids 15# of the files it writes to the data string. For example, let's say that 16# I randomly generate the key dog and data cat. Then I pick a replication 17# factor of 3. I pick 3 files from the set of n (say 1, 3, and 5). I then 18# rewrite the data as 1:3:5:cat. I begin a transaction, add the key/data 19# pair to each file and then commit. Notice that I may generate replication 20# of the form 1:3:3:cat in which case I simply add a duplicate to file 3. 21# 22# Usage: sysscript dir nfiles key_avg data_avg 23# 24# dir: DB_HOME directory 25# nfiles: number of files in the set 26# key_avg: average big key size 27# data_avg: average big data size 28 29source ./include.tcl 30source $test_path/test.tcl 31source $test_path/testutils.tcl 32 33set mypid [pid] 34 35set usage "sysscript dir nfiles key_avg data_avg method" 36 37# Verify usage 38if { $argc != 5 } { 39 puts stderr "FAIL:[timestamp] Usage: $usage" 40 exit 41} 42 43puts [concat "Argc: " $argc " Argv: " $argv] 44 45# Initialize arguments 46set dir [lindex $argv 0] 47set nfiles [ lindex $argv 1 ] 48set key_avg [ lindex $argv 2 ] 49set data_avg [ lindex $argv 3 ] 50set method [ lindex $argv 4 ] 51 52# Initialize seed 53global rand_init 54berkdb srand $rand_init 55 56puts "Beginning execution for $mypid" 57puts "$dir DB_HOME" 58puts "$nfiles files" 59puts "$key_avg average key length" 60puts "$data_avg average data length" 61 62flush stdout 63 64# Create local environment 65set dbenv [berkdb_env -txn -home $dir] 66set err [catch {error_check_good $mypid:dbenv [is_substr $dbenv env] 1} ret] 67if {$err != 0} { 68 puts $ret 69 return 70} 71 72# Now open the files 73for { set i 0 } { $i < $nfiles } { incr i } { 74 set file test044.$i.db 75 set db_set($i) [berkdb open -auto_commit -env $dbenv $method $file] 76 set err [catch {error_check_bad $mypid:dbopen $db_set($i) NULL} ret] 77 if {$err != 0} { 78 puts $ret 79 return 80 } 81 set err [catch {error_check_bad $mypid:dbopen [is_substr $db_set($i) \ 82 error] 1} ret] 83 if {$err != 0} { 84 puts $ret 85 return 86 } 87} 88 89set record_based [is_record_based $method] 90while { 1 } { 91 # Decide if we're going to create a big key or a small key 92 # We give small keys a 70% chance. 93 if { [berkdb random_int 1 10] < 8 } { 94 set k [random_data 5 0 0 $record_based] 95 } else { 96 set k [random_data $key_avg 0 0 $record_based] 97 } 98 set data [chop_data $method [random_data $data_avg 0 0]] 99 100 set txn [$dbenv txn] 101 set err [catch {error_check_good $mypid:txn_begin [is_substr $txn \ 102 $dbenv.txn] 1} ret] 103 if {$err != 0} { 104 puts $ret 105 return 106 } 107 108 # Open cursors 109 for { set f 0 } {$f < $nfiles} {incr f} { 110 set cursors($f) [$db_set($f) cursor -txn $txn] 111 set err [catch {error_check_good $mypid:cursor_open \ 112 [is_substr $cursors($f) $db_set($f)] 1} ret] 113 if {$err != 0} { 114 puts $ret 115 return 116 } 117 } 118 set aborted 0 119 120 # Check to see if key is already in database 121 set found 0 122 for { set i 0 } { $i < $nfiles } { incr i } { 123 set r [$db_set($i) get -txn $txn $k] 124 set r [$db_set($i) get -txn $txn $k] 125 if { $r == "-1" } { 126 for {set f 0 } {$f < $nfiles} {incr f} { 127 set err [catch {error_check_good \ 128 $mypid:cursor_close \ 129 [$cursors($f) close] 0} ret] 130 if {$err != 0} { 131 puts $ret 132 return 133 } 134 } 135 set err [catch {error_check_good $mypid:txn_abort \ 136 [$txn abort] 0} ret] 137 if {$err != 0} { 138 puts $ret 139 return 140 } 141 set aborted 1 142 set found 2 143 break 144 } elseif { $r != "Key $k not found." } { 145 set found 1 146 break 147 } 148 } 149 switch $found { 150 2 { 151 # Transaction aborted, no need to do anything. 152 } 153 0 { 154 # Key was not found, decide how much to replicate 155 # and then create a list of that many file IDs. 156 set repl [berkdb random_int 1 $nfiles] 157 set fset "" 158 for { set i 0 } { $i < $repl } {incr i} { 159 set f [berkdb random_int 0 [expr $nfiles - 1]] 160 lappend fset $f 161 set data [chop_data $method $f:$data] 162 } 163 164 foreach i $fset { 165 set r [$db_set($i) put -txn $txn $k $data] 166 if {$r == "-1"} { 167 for {set f 0 } {$f < $nfiles} {incr f} { 168 set err [catch {error_check_good \ 169 $mypid:cursor_close \ 170 [$cursors($f) close] 0} ret] 171 if {$err != 0} { 172 puts $ret 173 return 174 } 175 } 176 set err [catch {error_check_good \ 177 $mypid:txn_abort [$txn abort] 0} ret] 178 if {$err != 0} { 179 puts $ret 180 return 181 } 182 set aborted 1 183 break 184 } 185 } 186 } 187 1 { 188 # Key was found. Make sure that all the data values 189 # look good. 190 set f [zero_list $nfiles] 191 set data $r 192 while { [set ndx [string first : $r]] != -1 } { 193 set fnum [string range $r 0 [expr $ndx - 1]] 194 if { [lindex $f $fnum] == 0 } { 195 #set flag -set 196 set full [record $cursors($fnum) get -set $k] 197 } else { 198 #set flag -next 199 set full [record $cursors($fnum) get -next] 200 } 201 if {[llength $full] == 0} { 202 for {set f 0 } {$f < $nfiles} {incr f} { 203 set err [catch {error_check_good \ 204 $mypid:cursor_close \ 205 [$cursors($f) close] 0} ret] 206 if {$err != 0} { 207 puts $ret 208 return 209 } 210 } 211 set err [catch {error_check_good \ 212 $mypid:txn_abort [$txn abort] 0} ret] 213 if {$err != 0} { 214 puts $ret 215 return 216 } 217 set aborted 1 218 break 219 } 220 set err [catch {error_check_bad \ 221 $mypid:curs_get($k,$data,$fnum,$flag) \ 222 [string length $full] 0} ret] 223 if {$err != 0} { 224 puts $ret 225 return 226 } 227 set key [lindex [lindex $full 0] 0] 228 set rec [pad_data $method [lindex [lindex $full 0] 1]] 229 set err [catch {error_check_good \ 230 $mypid:dbget_$fnum:key $key $k} ret] 231 if {$err != 0} { 232 puts $ret 233 return 234 } 235 set err [catch {error_check_good \ 236 $mypid:dbget_$fnum:data($k) $rec $data} ret] 237 if {$err != 0} { 238 puts $ret 239 return 240 } 241 set f [lreplace $f $fnum $fnum 1] 242 incr ndx 243 set r [string range $r $ndx end] 244 } 245 } 246 } 247 if { $aborted == 0 } { 248 for {set f 0 } {$f < $nfiles} {incr f} { 249 set err [catch {error_check_good $mypid:cursor_close \ 250 [$cursors($f) close] 0} ret] 251 if {$err != 0} { 252 puts $ret 253 return 254 } 255 } 256 set err [catch {error_check_good $mypid:commit [$txn commit] \ 257 0} ret] 258 if {$err != 0} { 259 puts $ret 260 return 261 } 262 } 263} 264 265# Close files 266for { set i 0 } { $i < $nfiles} { incr i } { 267 set r [$db_set($i) close] 268 set err [catch {error_check_good $mypid:db_close:$i $r 0} ret] 269 if {$err != 0} { 270 puts $ret 271 return 272 } 273} 274 275# Close tm and environment 276$dbenv close 277 278puts "[timestamp] [pid] Complete" 279flush stdout 280 281filecheck $file 0 282