1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2003,2008 Oracle. All rights reserved. 4# 5# $Id: test103.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST test103 8# TEST Test bulk get when record numbers wrap around. 9# TEST 10# TEST Load database with items starting before and ending after 11# TEST the record number wrap around point. Run bulk gets (-multi_key) 12# TEST with various buffer sizes and verify the contents returned match 13# TEST the results from a regular cursor get. 14# TEST 15# TEST Then delete items to create a sparse database and make sure it 16# TEST still works. Test both -multi and -multi_key since they behave 17# TEST differently. 18proc test103 { method {nentries 100} {start 4294967250} {tnum "103"} args} { 19 source ./include.tcl 20 21 set args [convert_args $method $args] 22 set omethod [convert_method $method] 23 puts "Test$tnum: $method ($args) Test of bulk get with wraparound." 24 25 if { [is_queueext $method] == 0 } { 26 puts "\tSkipping Test$tnum for method $method." 27 return 28 } 29 30 # Create the database and open the dictionary 31 set txnenv 0 32 set eindex [lsearch -exact $args "-env"] 33 # 34 # If we are using an env, then testfile should just be the db name. 35 # Otherwise it is the test directory and the name. 36 if { $eindex == -1 } { 37 set testfile $testdir/test$tnum.db 38 set env NULL 39 } else { 40 set testfile test$tnum.db 41 incr eindex 42 set env [lindex $args $eindex] 43 set txnenv [is_txnenv $env] 44 if { $txnenv == 1 } { 45 append args " -auto_commit " 46 # 47 # If we are using txns and running with the 48 # default, set the default down a bit. 49 # 50 if { $nentries == 10000 } { 51 set nentries 100 52 } 53 } 54 set testdir [get_home $env] 55 } 56 57 cleanup $testdir $env 58 59 set db [eval {berkdb_open_noerr \ 60 -create -mode 0644} $args $omethod $testfile] 61 error_check_good dbopen [is_valid_db $db] TRUE 62 63 # Find the pagesize so we can use it to size the buffer. 64 set stat [$db stat] 65 set pagesize [get_pagesize $stat] 66 67 set did [open $dict] 68 69 puts "\tTest$tnum.a: put/get loop" 70 set txn "" 71 72 # Here is the loop where we put each key/data pair 73 set count 0 74 set k [expr $start + 1] 75 while { [gets $did str] != -1 && $count < $nentries } { 76 # 77 # We cannot use 'incr' because it gets unhappy since 78 # expr above is using 64-bits. 79 set k [expr $k + 1] 80 # 81 # Detect if we're more than 32 bits now. If so, wrap 82 # our key back to 1. 83 # 84 if { [expr $k > 0xffffffff] } { 85 set k 1 86 } 87 if { $txnenv == 1 } { 88 set t [$env txn] 89 error_check_good txn [is_valid_txn $t $env] TRUE 90 set txn "-txn $t" 91 } 92 set ret [eval {$db put} $txn {$k [chop_data $method $str]}] 93 error_check_good db_put $ret 0 94 if { $txnenv == 1 } { 95 error_check_good txn [$t commit] 0 96 } 97 incr count 98 } 99 close $did 100 101 # Run tests in verbose mode for debugging. 102 set verbose 0 103 104 puts "\tTest$tnum.b: Bulk get with large buffer (retrieves all data)." 105 # Buffer is large enough that everything fits in a single get. 106 check_multi_recno $db [expr $pagesize * $nentries] multi_key $verbose 107 108 puts "\tTest$tnum.c: Bulk get with buffer = (2 x pagesize)." 109 # Buffer gets several items at a get, but not all. 110 check_multi_recno $db [expr $pagesize * 2] multi_key $verbose 111 112 # Skip tests if buffer would be smaller than allowed. 113 if { $pagesize >= 1024 } { 114 puts "\tTest$tnum.d: Bulk get with buffer = pagesize." 115 check_multi_recno $db $pagesize multi_key $verbose 116 } 117 118 if { $pagesize >= 2048 } { 119 puts "\tTest$tnum.e: Bulk get with buffer < pagesize\ 120 (returns EINVAL)." 121 catch { 122 check_multi_recno $db [expr $pagesize / 2] \ 123 multi_key $verbose 124 } res 125 error_check_good \ 126 bufsize_less_than_pagesize [is_substr $res "invalid"] 1 127 } 128 129 # For a sparsely populated database, test with both -multi_key and 130 # -multi. In any sort of record numbered database, -multi does not 131 # return keys, so it returns all items. -multi_key returns both keys 132 # and data so it skips deleted items. 133 puts "\tTest$tnum.f: Delete every 10th item to create sparse database." 134 if { $txnenv == 1 } { 135 set t [$env txn] 136 error_check_good txn [is_valid_txn $t $env] TRUE 137 set txn "-txn $t" 138 } 139 set curs [ eval {$db cursor} $txn] 140 error_check_good cursor [is_valid_cursor $curs $db] TRUE 141 142 set count 0 143 for { set kd [$curs get -first] } { $count < $nentries } \ 144 { set kd [$curs get -next] } { 145 if { [expr $count % 10 == 0] } { 146 error_check_good cdelete [$curs del] 0 147 } 148 incr count 149 } 150 error_check_good curs_close [$curs close] 0 151 if { $txnenv == 1 } { 152 error_check_good txn [$t commit] 0 153 } 154 155 puts "\tTest$tnum.g: Sparse database, large buffer, multi_key." 156 check_multi_recno $db [expr $pagesize * $nentries] multi_key $verbose 157 puts "\tTest$tnum.h: Sparse database, large buffer, multi." 158 check_multi_recno $db [expr $pagesize * $nentries] multi $verbose 159 160 puts "\tTest$tnum.i: \ 161 Sparse database, buffer = (2 x pagesize), multi_key." 162 check_multi_recno $db [expr $pagesize * 2] multi_key $verbose 163 puts "\tTest$tnum.j: Sparse database, buffer = (2 x pagesize), multi." 164 check_multi_recno $db [expr $pagesize * 2] multi $verbose 165 166 if { $pagesize >= 1024 } { 167 puts "\tTest$tnum.k: \ 168 Sparse database, buffer = pagesize, multi_key." 169 check_multi_recno $db $pagesize multi_key $verbose 170 puts "\tTest$tnum.k: Sparse database, buffer = pagesize, multi." 171 check_multi_recno $db $pagesize multi $verbose 172 } 173 174 error_check_good db_close [$db close] 0 175} 176 177# The proc check_multi_recno is a modification of the utility routine 178# check_multi_key specifically for recno methods. We use this instead 179# check_multi, even with the -multi flag, because the check_multi utility 180# assumes that dups are being used which can't happen with record-based 181# methods. 182proc check_multi_recno { db size flag {verbose 0}} { 183 source ./include.tcl 184 set c [eval { $db cursor} ] 185 set m [eval { $db cursor} ] 186 187 set j 1 188 189 # Walk the database with -multi_key or -multi bulk get. 190 for {set d [$m get -first -$flag $size] } { [llength $d] != 0 } { 191 set d [$m get -next -$flag $size] } { 192 if {$verbose == 1 } { 193 puts "FETCH $j" 194 incr j 195 } 196 # For each bulk get return, compare the results to what we 197 # get by walking the db with an ordinary cursor get. 198 for {set i 0} { $i < [llength $d] } { incr i } { 199 set kd [lindex $d $i] 200 set k [lindex $kd 0] 201 set data [lindex $kd 1] 202 set len [string length $data] 203 204 if {$verbose == 1 } { 205 puts ">> $k << >> $len << " 206 } 207 # If we hit a deleted item in -multi, skip over it. 208 if { $flag == "multi" && $len == 0 } { 209 continue 210 } 211 212 set check [$c get -next] 213 set cd [lindex $check 0] 214 set ck [lindex $cd 0] 215 set cdata [lindex $cd 1] 216 217 error_check_good key $k $ck 218 error_check_good data_len $len [string length $cdata] 219 error_check_good data $data $cdata 220 } 221 } 222} 223