1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2005,2008 Oracle. All rights reserved. 4# 5# $Id: si008.tcl,v 12.10 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST si008 8# TEST Secondary index put/delete with lorder test 9# TEST 10# TEST This test is the same as si001 except that we 11# TEST create the secondaries with different byte orders: 12# TEST one native, one swapped. 13 14proc si008 { methods {nentries 10} {tnum "008"} args } { 15 source ./include.tcl 16 global dict nsecondaries 17 18 # Primary method/args. 19 set pmethod [lindex $methods 0] 20 set pargs [convert_args $pmethod $args] 21 if [big_endian] { 22 set nativeargs " -lorder 4321" 23 set swappedargs " -lorder 1234" 24 } else { 25 set swappedargs " -lorder 4321" 26 set nativeargs " -lorder 1234" 27 } 28 set argtypes "{$nativeargs} {$swappedargs}" 29 set pomethod [convert_method $pmethod] 30 31 # Renumbering recno databases can't be used as primaries. 32 if { [is_rrecno $pmethod] == 1 } { 33 puts "Skipping si$tnum for method $pmethod" 34 return 35 } 36 37 # Method/args for all the secondaries. If only one method 38 # was specified, assume the same method (for btree or hash) 39 # and a standard number of secondaries. If primary is not 40 # btree or hash, force secondaries to be one btree, one hash. 41 set methods [lrange $methods 1 end] 42 if { [llength $methods] == 0 } { 43 for { set i 0 } { $i < $nsecondaries } { incr i } { 44 if { [is_btree $pmethod] || [is_hash $pmethod] } { 45 lappend methods $pmethod 46 } else { 47 if { [expr $i % 2] == 0 } { 48 lappend methods "-btree" 49 } else { 50 lappend methods "-hash" 51 } 52 } 53 } 54 } 55 56 set argses [convert_argses $methods $args] 57 set omethods [convert_methods $methods] 58 59 # If we are given an env, use it. Otherwise, open one. 60 set eindex [lsearch -exact $args "-env"] 61 if { $eindex == -1 } { 62 env_cleanup $testdir 63 set cacheargs " -cachesize {0 1048576 1} " 64 set env [eval berkdb_env -create $cacheargs -home $testdir] 65 error_check_good env_open [is_valid_env $env] TRUE 66 } else { 67 incr eindex 68 set env [lindex $args $eindex] 69 set envflags [$env get_open_flags] 70 if { [lsearch -exact $envflags "-thread"] != -1 &&\ 71 [is_queue $pmethod] == 1 } { 72 puts "Skipping si$tnum for threaded env" 73 return 74 } 75 set testdir [get_home $env] 76 } 77 78 set pname "primary$tnum.db" 79 set snamebase "secondary$tnum" 80 81 foreach pbyteargs $argtypes { 82 if { $pbyteargs == $nativeargs } { 83 puts "Si$tnum: Using native\ 84 byteorder $nativeargs for primary." 85 } else { 86 puts "Si$tnum: Using swapped\ 87 byteorder $swappedargs for primary." 88 } 89 90 puts "si$tnum\ 91 \{\[ list $pmethod $methods \]\} $nentries" 92 cleanup $testdir $env 93 94 # Open primary. 95 set pdb [eval {berkdb_open -create -env} $env \ 96 $pomethod $pargs $pbyteargs $pname] 97 error_check_good primary_open [is_valid_db $pdb] TRUE 98 99 # Open and associate the secondaries 100 set sdbs {} 101 for { set i 0 } { $i < [llength $omethods] } { incr i } { 102 if { [expr $i % 2] == 0 } { 103 set sbyteargs $nativeargs 104 } else { 105 set sbyteargs $swappedargs 106 } 107 108 if { $sbyteargs == $nativeargs } { 109 puts "Si$tnum: Using native byteorder\ 110 $nativeargs for secondary $i." 111 } else { 112 puts "Si$tnum: Using swapped byteorder\ 113 $swappedargs for secondary $i." 114 } 115 116 set sdb [eval {berkdb_open -create -env} $env \ 117 [lindex $omethods $i] [lindex $argses $i] \ 118 $sbyteargs $snamebase.$i.db] 119 error_check_good second_open($i) [is_valid_db $sdb] TRUE 120 121 error_check_good db_associate($i) \ 122 [$pdb associate [callback_n $i] $sdb] 0 123 lappend sdbs $sdb 124 } 125 126 puts "\tSi$tnum.a: Put loop" 127 set did [open $dict] 128 for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } { 129 if { [is_record_based $pmethod] == 1 } { 130 set key [expr $n + 1] 131 set datum $str 132 } else { 133 set key $str 134 gets $did datum 135 } 136 set keys($n) $key 137 set data($n) [pad_data $pmethod $datum] 138 139 set ret [eval {$pdb put}\ 140 {$key [chop_data $pmethod $datum]}] 141 error_check_good put($n) $ret 0 142 } 143 close $did 144 145 check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.a" 146 147 puts "\tSi$tnum.b: Put/overwrite loop" 148 for { set n 0 } { $n < $nentries } { incr n } { 149 set newd $data($n).$keys($n) 150 set ret [eval {$pdb put}\ 151 {$keys($n) [chop_data $pmethod $newd]}] 152 error_check_good put_overwrite($n) $ret 0 153 set data($n) [pad_data $pmethod $newd] 154 } 155 check_secondaries\ 156 $pdb $sdbs $nentries keys data "Si$tnum.b" 157 158 # Delete the second half of the entries through 159 # the primary. We do the second half so we can 160 # just pass keys(0 ... n/2) to check_secondaries. 161 set half [expr $nentries / 2] 162 puts "\tSi$tnum.c:\ 163 Primary delete loop: deleting $half entries" 164 for { set n $half } { $n < $nentries } { incr n } { 165 set ret [$pdb del $keys($n)] 166 error_check_good pdel($n) $ret 0 167 } 168 check_secondaries\ 169 $pdb $sdbs $half keys data "Si$tnum.c" 170 171 # Delete half of what's left through 172 # the first secondary. 173 set quar [expr $half / 2] 174 puts "\tSi$tnum.d:\ 175 Secondary delete loop: deleting $quar entries" 176 set sdb [lindex $sdbs 0] 177 set callback [callback_n 0] 178 for { set n $quar } { $n < $half } { incr n } { 179 set skey [$callback $keys($n)\ 180 [pad_data $pmethod $data($n)]] 181 set ret [$sdb del $skey] 182 error_check_good sdel($n) $ret 0 183 } 184 check_secondaries\ 185 $pdb $sdbs $quar keys data "Si$tnum.d" 186 set left $quar 187 188 # For queue and recno only, test append, adding back 189 # a quarter of the original number of entries. 190 if { [is_record_based $pmethod] == 1 } { 191 set did [open $dict] 192 puts "\tSi$tnum.e:\ 193 Append loop: append $quar entries" 194 for { set n 0 } { $n < $nentries } { incr n } { 195 # Skip over dictionary entries we've 196 # already used. 197 gets $did str 198 } 199 for { set n $quar } \ 200 { [gets $did str] != -1 && $n < $half } \ 201 { incr n } { 202 set key [expr $n + 1] 203 set datum $str 204 set keys($n) $key 205 set data($n) [pad_data $pmethod $datum] 206 207 set ret [eval {$pdb put} \ 208 {$key [chop_data $pmethod $datum]}] 209 error_check_good put($n) $ret 0 210 } 211 close $did 212 213 check_secondaries\ 214 $pdb $sdbs $half keys data "Si$tnum.e" 215 set left $half 216 } 217 218 puts "\tSi$tnum.f:\ 219 Truncate primary, check secondaries are empty." 220 error_check_good truncate [$pdb truncate] $left 221 foreach sdb $sdbs { 222 set scursor [$sdb cursor] 223 error_check_good\ 224 db_cursor [is_substr $scursor $sdb] 1 225 set ret [$scursor get -first] 226 error_check_good\ 227 sec_empty [string length $ret] 0 228 error_check_good cursor_close [$scursor close] 0 229 } 230 231 232 puts "\tSi$tnum.g: Closing/disassociating primary first" 233 error_check_good primary_close [$pdb close] 0 234 foreach sdb $sdbs { 235 error_check_good secondary_close [$sdb close] 0 236 } 237 238 # Don't close the env if this test was given one. 239 # Skip the test of truncating the secondary since 240 # we can't close and reopen the outside env. 241 if { $eindex == -1 } { 242 error_check_good env_close [$env close] 0 243 244 # Reopen with _noerr for test of 245 # truncate secondary. 246 puts "\tSi$tnum.h:\ 247 Truncate secondary (should fail)" 248 249 set env [berkdb_env_noerr\ 250 -create -home $testdir] 251 error_check_good\ 252 env_open [is_valid_env $env] TRUE 253 254 set pdb [eval {berkdb_open_noerr -create -env}\ 255 $env $pomethod $pargs $pname] 256 set sdb [eval {berkdb_open_noerr -create -env}\ 257 $env [lindex $omethods 0]\ 258 [lindex $argses 0] $snamebase.0.db ] 259 $pdb associate [callback_n 0] $sdb 260 261 set ret [catch {$sdb truncate} ret] 262 error_check_good trunc_secondary $ret 1 263 264 error_check_good primary_close [$pdb close] 0 265 error_check_good secondary_close [$sdb close] 0 266 } 267 } 268 269 # If this test made the last env, close it. 270 if { $eindex == -1 } { 271 error_check_good env_close [$env close] 0 272 } 273} 274