1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
|
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2000-2002
# Sleepycat Software. All rights reserved.
#
# $Id: test095.tcl,v 1.1.1.1 2003/11/20 22:14:02 toshok Exp $
#
# TEST test095
# TEST Bulk get test. [#2934]
proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } {
source ./include.tcl
set args [convert_args $method $args]
set omethod [convert_method $method]
set txnenv 0
set eindex [lsearch -exact $args "-env"]
#
# If we are using an env, then testfile should just be the db name.
# Otherwise it is the test directory and the name.
if { $eindex == -1 } {
set basename $testdir/test0$tnum
set env NULL
# If we've our own env, no reason to swap--this isn't
# an mpool test.
set carg { -cachesize {0 25000000 0} }
} else {
set basename test0$tnum
incr eindex
set env [lindex $args $eindex]
set txnenv [is_txnenv $env]
if { $txnenv == 1 } {
puts "Skipping for environment with txns"
return
}
set testdir [get_home $env]
set carg {}
}
cleanup $testdir $env
puts "Test0$tnum: $method ($args) Bulk get test"
if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } {
puts "Test0$tnum skipping for method $method"
return
}
# We run the meat of the test twice: once with unsorted dups,
# once with sorted dups.
for { set dflag "-dup"; set sort "unsorted"; set diter 0 } \
{ $diter < 2 } \
{ set dflag "-dup -dupsort"; set sort "sorted"; incr diter } {
set testfile $basename-$sort.db
set did [open $dict]
# Open and populate the database with $nsets sets of dups.
# Each set contains as many dups as its number
puts "\tTest0$tnum.a:\
Creating database with $nsets sets of $sort dups."
set dargs "$dflag $carg $args"
set db [eval {berkdb_open -create} $omethod $dargs $testfile]
error_check_good db_open [is_valid_db $db] TRUE
t95_populate $db $did $nsets 0
# Run basic get tests.
t95_gettest $db $tnum b [expr 8192] 1
t95_gettest $db $tnum c [expr 10 * 8192] 0
# Run cursor get tests.
t95_cgettest $db $tnum d [expr 100] 1
t95_cgettest $db $tnum e [expr 10 * 8192] 0
# Run invalid flag combination tests
# Sync and reopen test file so errors won't be sent to stderr
error_check_good db_sync [$db sync] 0
set noerrdb [eval berkdb_open_noerr $dargs $testfile]
t95_flagtest $noerrdb $tnum f [expr 8192]
t95_cflagtest $noerrdb $tnum g [expr 100]
error_check_good noerrdb_close [$noerrdb close] 0
# Set up for overflow tests
set max [expr 4000 * $noverflows]
puts "\tTest0$tnum.h: Growing\
database with $noverflows overflow sets (max item size $max)"
t95_populate $db $did $noverflows 4000
# Run overflow get tests.
t95_gettest $db $tnum i [expr 10 * 8192] 1
t95_gettest $db $tnum j [expr $max * 2] 1
t95_gettest $db $tnum k [expr $max * $noverflows * 2] 0
# Run overflow cursor get tests.
t95_cgettest $db $tnum l [expr 10 * 8192] 1
t95_cgettest $db $tnum m [expr $max * 2] 0
error_check_good db_close [$db close] 0
close $did
}
}
proc t95_gettest { db tnum letter bufsize expectfail } {
t95_gettest_body $db $tnum $letter $bufsize $expectfail 0
}
proc t95_cgettest { db tnum letter bufsize expectfail } {
t95_gettest_body $db $tnum $letter $bufsize $expectfail 1
}
proc t95_flagtest { db tnum letter bufsize } {
t95_flagtest_body $db $tnum $letter $bufsize 0
}
proc t95_cflagtest { db tnum letter bufsize } {
t95_flagtest_body $db $tnum $letter $bufsize 1
}
# Basic get test
proc t95_gettest_body { db tnum letter bufsize expectfail usecursor } {
global errorCode
if { $usecursor == 0 } {
set action "db get -multi"
} else {
set action "dbc get -multi -set/-next"
}
puts "\tTest0$tnum.$letter: $action with bufsize $bufsize"
set allpassed TRUE
set saved_err ""
# Cursor for $usecursor.
if { $usecursor != 0 } {
set getcurs [$db cursor]
error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
}
# Traverse DB with cursor; do get/c_get(DB_MULTIPLE) on each item.
set dbc [$db cursor]
error_check_good is_valid_dbc [is_valid_cursor $dbc $db] TRUE
for { set dbt [$dbc get -first] } { [llength $dbt] != 0 } \
{ set dbt [$dbc get -nextnodup] } {
set key [lindex [lindex $dbt 0] 0]
set datum [lindex [lindex $dbt 0] 1]
if { $usecursor == 0 } {
set ret [catch {eval $db get -multi $bufsize $key} res]
} else {
set res {}
for { set ret [catch {eval $getcurs get -multi $bufsize\
-set $key} tres] } \
{ $ret == 0 && [llength $tres] != 0 } \
{ set ret [catch {eval $getcurs get -multi $bufsize\
-nextdup} tres]} {
eval lappend res $tres
}
}
# If we expect a failure, be more tolerant if the above fails;
# just make sure it's an ENOMEM, mark it, and move along.
if { $expectfail != 0 && $ret != 0 } {
error_check_good multi_failure_errcode \
[is_substr $errorCode ENOMEM] 1
set allpassed FALSE
continue
}
error_check_good get_multi($key) $ret 0
t95_verify $res FALSE
}
set ret [catch {eval $db get -multi $bufsize} res]
if { $expectfail == 1 } {
error_check_good allpassed $allpassed FALSE
puts "\t\tTest0$tnum.$letter:\
returned at least one ENOMEM (as expected)"
} else {
error_check_good allpassed $allpassed TRUE
puts "\t\tTest0$tnum.$letter: succeeded (as expected)"
}
error_check_good dbc_close [$dbc close] 0
if { $usecursor != 0 } {
error_check_good getcurs_close [$getcurs close] 0
}
}
# Test of invalid flag combinations for -multi
proc t95_flagtest_body { db tnum letter bufsize usecursor } {
global errorCode
if { $usecursor == 0 } {
set action "db get -multi "
} else {
set action "dbc get -multi "
}
puts "\tTest0$tnum.$letter: $action with invalid flag combinations"
# Cursor for $usecursor.
if { $usecursor != 0 } {
set getcurs [$db cursor]
error_check_good getcurs [is_valid_cursor $getcurs $db] TRUE
}
if { $usecursor == 0 } {
# Disallowed flags for basic -multi get
set badflags [list consume consume_wait {rmw some_key}]
foreach flag $badflags {
catch {eval $db get -multi $bufsize -$flag} ret
error_check_good \
db:get:multi:$flag [is_substr $errorCode EINVAL] 1
}
} else {
# Disallowed flags for cursor -multi get
set cbadflags [list last get_recno join_item \
{multi_key 1000} prev prevnodup]
set dbc [$db cursor]
$dbc get -first
foreach flag $cbadflags {
catch {eval $dbc get -multi $bufsize -$flag} ret
error_check_good dbc:get:multi:$flag \
[is_substr $errorCode EINVAL] 1
}
error_check_good dbc_close [$dbc close] 0
}
if { $usecursor != 0 } {
error_check_good getcurs_close [$getcurs close] 0
}
puts "\t\tTest0$tnum.$letter completed"
}
# Verify that a passed-in list of key/data pairs all match the predicted
# structure (e.g. {{thing1 thing1.0}}, {{key2 key2.0} {key2 key2.1}}).
proc t95_verify { res multiple_keys } {
global alphabet
set i 0
set orig_key [lindex [lindex $res 0] 0]
set nkeys [string trim $orig_key $alphabet']
set base_key [string trim $orig_key 0123456789]
set datum_count 0
while { 1 } {
set key [lindex [lindex $res $i] 0]
set datum [lindex [lindex $res $i] 1]
if { $datum_count >= $nkeys } {
if { [llength $key] != 0 } {
# If there are keys beyond $nkeys, we'd
# better have multiple_keys set.
error_check_bad "keys beyond number $i allowed"\
$multiple_keys FALSE
# If multiple_keys is set, accept the new key.
set orig_key $key
set nkeys [eval string trim \
$orig_key {$alphabet'}]
set base_key [eval string trim \
$orig_key 0123456789]
set datum_count 0
} else {
# datum_count has hit nkeys. We're done.
return
}
}
error_check_good returned_key($i) $key $orig_key
error_check_good returned_datum($i) \
$datum $base_key.[format %4u $datum_count]
incr datum_count
incr i
}
}
# Add nsets dup sets, each consisting of {word$ndups word$n} pairs,
# with "word" having (i * pad_bytes) bytes extra padding.
proc t95_populate { db did nsets pad_bytes } {
set txn ""
for { set i 1 } { $i <= $nsets } { incr i } {
# basekey is a padded dictionary word
gets $did basekey
append basekey [repeat "a" [expr $pad_bytes * $i]]
# key is basekey with the number of dups stuck on.
set key $basekey$i
for { set j 0 } { $j < $i } { incr j } {
set data $basekey.[format %4u $j]
error_check_good db_put($key,$data) \
[eval {$db put} $txn {$key $data}] 0
}
}
# This will make debugging easier, and since the database is
# read-only from here out, it's cheap.
error_check_good db_sync [$db sync] 0
}
|