1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1999,2008 Oracle. All rights reserved. 4# 5# $Id: test074.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST test074 8# TEST Test of DB_NEXT_NODUP. 9proc test074 { method {dir -nextnodup} {nitems 100} {tnum "074"} args } { 10 source ./include.tcl 11 global alphabet 12 global is_je_test 13 global rand_init 14 15 set omethod [convert_method $method] 16 set args [convert_args $method $args] 17 18 berkdb srand $rand_init 19 20 # Data prefix--big enough that we get a mix of on-page, off-page, 21 # and multi-off-page dups with the default nitems 22 if { [is_fixed_length $method] == 1 } { 23 set globaldata "somedata" 24 } else { 25 set globaldata [repeat $alphabet 4] 26 } 27 28 puts "Test$tnum $omethod ($args): Test of $dir" 29 30 # First, test non-dup (and not-very-interesting) case with 31 # all db types. 32 33 puts "\tTest$tnum.a: No duplicates." 34 35 set txnenv 0 36 set eindex [lsearch -exact $args "-env"] 37 # 38 # If we are using an env, then testfile should just be the db name. 39 # Otherwise it is the test directory and the name. 40 if { $eindex == -1 } { 41 set testfile $testdir/test$tnum-nodup.db 42 set env NULL 43 } else { 44 set testfile test$tnum-nodup.db 45 incr eindex 46 set env [lindex $args $eindex] 47 set txnenv [is_txnenv $env] 48 if { $txnenv == 1 } { 49 append args " -auto_commit " 50 } 51 set testdir [get_home $env] 52 } 53 cleanup $testdir $env 54 set db [eval {berkdb_open -create -mode 0644} $omethod\ 55 $args {$testfile}] 56 error_check_good db_open [is_valid_db $db] TRUE 57 set txn "" 58 59 # Insert nitems items. 60 puts "\t\tTest$tnum.a.1: Put loop." 61 for {set i 1} {$i <= $nitems} {incr i} { 62 # 63 # If record based, set key to $i * 2 to leave 64 # holes/unused entries for further testing. 65 # 66 if {[is_record_based $method] == 1} { 67 set key [expr $i * 2] 68 } else { 69 set key "key$i" 70 } 71 set data "$globaldata$i" 72 if { $txnenv == 1 } { 73 set t [$env txn] 74 error_check_good txn [is_valid_txn $t $env] TRUE 75 set txn "-txn $t" 76 } 77 set ret [eval {$db put} $txn {$key \ 78 [chop_data $method $data]}] 79 error_check_good put($i) $ret 0 80 if { $txnenv == 1 } { 81 error_check_good txn [$t commit] 0 82 } 83 } 84 85 puts "\t\tTest$tnum.a.2: Get($dir)" 86 87 # foundarray($i) is set when key number i is found in the database 88 if { $txnenv == 1 } { 89 set t [$env txn] 90 error_check_good txn [is_valid_txn $t $env] TRUE 91 set txn "-txn $t" 92 } 93 set dbc [eval {$db cursor} $txn] 94 error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE 95 96 # Initialize foundarray($i) to zero for all $i 97 for {set i 1} {$i < $nitems} {incr i} { 98 set foundarray($i) 0 99 } 100 101 # Walk database using $dir and record each key gotten. 102 for {set i 1} {$i <= $nitems} {incr i} { 103 set dbt [$dbc get $dir] 104 set key [lindex [lindex $dbt 0] 0] 105 if {[is_record_based $method] == 1} { 106 set num [expr $key / 2] 107 set desired_key $key 108 error_check_good $method:num $key [expr $num * 2] 109 } else { 110 set num [string range $key 3 end] 111 set desired_key key$num 112 } 113 114 error_check_good dbt_correct($i) $dbt\ 115 [list [list $desired_key\ 116 [pad_data $method $globaldata$num]]] 117 118 set foundarray($num) 1 119 } 120 121 puts "\t\tTest$tnum.a.3: Final key." 122 error_check_good last_db_get [$dbc get $dir] [list] 123 124 puts "\t\tTest$tnum.a.4: Verify loop." 125 for { set i 1 } { $i <= $nitems } { incr i } { 126 error_check_good found_key($i) $foundarray($i) 1 127 } 128 129 error_check_good dbc_close(nodup) [$dbc close] 0 130 if { $txnenv == 1 } { 131 error_check_good txn [$t commit] 0 132 } 133 134 # If we are a method that doesn't allow dups, verify that 135 # we get an empty list if we try to use DB_NEXT_DUP 136 if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } { 137 if { $txnenv == 1 } { 138 set t [$env txn] 139 error_check_good txn [is_valid_txn $t $env] TRUE 140 set txn "-txn $t" 141 } 142 puts "\t\tTest$tnum.a.5: Check DB_NEXT_DUP for $method." 143 set dbc [eval {$db cursor} $txn] 144 error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE 145 146 set dbt [$dbc get $dir] 147 error_check_good $method:nextdup [$dbc get -nextdup] [list] 148 error_check_good dbc_close(nextdup) [$dbc close] 0 149 if { $txnenv == 1 } { 150 error_check_good txn [$t commit] 0 151 } 152 } 153 error_check_good db_close(nodup) [$db close] 0 154 155 # Quit here if we're a method that won't allow dups. 156 if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } { 157 puts "\tTest$tnum: Skipping remainder for method $method." 158 return 159 } 160 161 foreach opt { "-dup" "-dupsort" } { 162 if { $is_je_test && $opt == "-dup" } { 163 continue 164 } 165 166 # 167 # If we are using an env, then testfile should just be the 168 # db name. Otherwise it is the test directory and the name. 169 if { $eindex == -1 } { 170 set testfile $testdir/test$tnum$opt.db 171 } else { 172 set testfile test$tnum$opt.db 173 } 174 175 if { [string compare $opt "-dupsort"] == 0 } { 176 set opt "-dup -dupsort" 177 } 178 179 puts "\tTest$tnum.b: Duplicates ($opt)." 180 181 puts "\t\tTest$tnum.b.1 ($opt): Put loop." 182 set db [eval {berkdb_open -create -mode 0644}\ 183 $opt $omethod $args {$testfile}] 184 error_check_good db_open [is_valid_db $db] TRUE 185 186 # Insert nitems different keys such that key i has i dups. 187 for {set i 1} {$i <= $nitems} {incr i} { 188 set key key$i 189 190 for {set j 1} {$j <= $i} {incr j} { 191 if { $j < 10 } { 192 set data "${globaldata}00$j" 193 } elseif { $j < 100 } { 194 set data "${globaldata}0$j" 195 } else { 196 set data "$globaldata$j" 197 } 198 199 if { $txnenv == 1 } { 200 set t [$env txn] 201 error_check_good txn \ 202 [is_valid_txn $t $env] TRUE 203 set txn "-txn $t" 204 } 205 set ret [eval {$db put} $txn {$key $data}] 206 error_check_good put($i,$j) $ret 0 207 if { $txnenv == 1 } { 208 error_check_good txn [$t commit] 0 209 } 210 } 211 } 212 213 # Initialize foundarray($i) to 0 for all i. 214 unset foundarray 215 for { set i 1 } { $i <= $nitems } { incr i } { 216 set foundarray($i) 0 217 } 218 219 # Get loop--after each get, move forward a random increment 220 # within the duplicate set. 221 puts "\t\tTest$tnum.b.2 ($opt): Get loop." 222 set one "001" 223 if { $txnenv == 1 } { 224 set t [$env txn] 225 error_check_good txn [is_valid_txn $t $env] TRUE 226 set txn "-txn $t" 227 } 228 set dbc [eval {$db cursor} $txn] 229 error_check_good dbc($opt) [is_valid_cursor $dbc $db] TRUE 230 for { set i 1 } { $i <= $nitems } { incr i } { 231 set dbt [$dbc get $dir] 232 set key [lindex [lindex $dbt 0] 0] 233 set num [string range $key 3 end] 234 235 set desired_key key$num 236 if { [string compare $dir "-prevnodup"] == 0 } { 237 if { $num < 10 } { 238 set one "00$num" 239 } elseif { $num < 100 } { 240 set one "0$num" 241 } else { 242 set one $num 243 } 244 } 245 246 error_check_good dbt_correct($i) $dbt\ 247 [list [list $desired_key\ 248 "$globaldata$one"]] 249 250 set foundarray($num) 1 251 252 # Go forward by some number w/i dup set. 253 set inc [berkdb random_int 0 [expr $num - 1]] 254 for { set j 0 } { $j < $inc } { incr j } { 255 eval {$dbc get -nextdup} 256 } 257 } 258 259 puts "\t\tTest$tnum.b.3 ($opt): Final key." 260 error_check_good last_db_get($opt) [$dbc get $dir] [list] 261 262 # Verify 263 puts "\t\tTest$tnum.b.4 ($opt): Verify loop." 264 for { set i 1 } { $i <= $nitems } { incr i } { 265 error_check_good found_key($i) $foundarray($i) 1 266 } 267 268 error_check_good dbc_close [$dbc close] 0 269 if { $txnenv == 1 } { 270 error_check_good txn [$t commit] 0 271 } 272 error_check_good db_close [$db close] 0 273 } 274} 275