1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2001,2008 Oracle. All rights reserved. 4# 5# $Id: si003.tcl,v 12.11 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST si003 8# TEST si001 with secondaries created and closed mid-test 9# TEST Basic secondary index put/delete test with secondaries 10# TEST created mid-test. 11proc si003 { methods {nentries 200} {tnum "003"} args } { 12 source ./include.tcl 13 global dict nsecondaries 14 15 # There's no reason to run this test on large lists. 16 if { $nentries > 1000 } { 17 puts "Skipping si003 for large lists (over 1000 items)" 18 return 19 } 20 21 # Primary method/args. 22 set pmethod [lindex $methods 0] 23 set pargs [convert_args $pmethod $args] 24 set pomethod [convert_method $pmethod] 25 26 # Renumbering recno databases can't be used as primaries. 27 if { [is_rrecno $pmethod] == 1 } { 28 puts "Skipping si$tnum for method $pmethod" 29 return 30 } 31 32 # Method/args for all the secondaries. If only one method 33 # was specified, assume the same method (for btree or hash) 34 # and a standard number of secondaries. If primary is not 35 # btree or hash, force secondaries to be one btree, one hash. 36 set methods [lrange $methods 1 end] 37 if { [llength $methods] == 0 } { 38 for { set i 0 } { $i < $nsecondaries } { incr i } { 39 if { [is_btree $pmethod] || [is_hash $pmethod] } { 40 lappend methods $pmethod 41 } else { 42 if { [expr $i % 2] == 0 } { 43 lappend methods "-btree" 44 } else { 45 lappend methods "-hash" 46 } 47 } 48 } 49 } 50 51 set argses [convert_argses $methods $args] 52 set omethods [convert_methods $methods] 53 54 # If we are given an env, use it. Otherwise, open one. 55 set eindex [lsearch -exact $args "-env"] 56 if { $eindex == -1 } { 57 env_cleanup $testdir 58 set env [berkdb_env -create -home $testdir] 59 error_check_good env_open [is_valid_env $env] TRUE 60 } else { 61 incr eindex 62 set env [lindex $args $eindex] 63 set envflags [$env get_open_flags] 64 if { [lsearch -exact $envflags "-thread"] != -1 &&\ 65 [is_queue $pmethod] == 1 } { 66 puts "Skipping si$tnum for threaded env with queue" 67 return 68 } 69 set testdir [get_home $env] 70 } 71 72 puts "si$tnum \{\[ list $pmethod $methods \]\} $nentries" 73 cleanup $testdir $env 74 75 set pname "primary$tnum.db" 76 set snamebase "secondary$tnum" 77 78 # Open the primary. 79 set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname] 80 error_check_good primary_open [is_valid_db $pdb] TRUE 81 82 puts -nonewline "\tSi$tnum.a: Put loop ... " 83 set did [open $dict] 84 for { set n 0 } { [gets $did str] != -1 && $n < $nentries } { incr n } { 85 if { [is_record_based $pmethod] == 1 } { 86 set key [expr $n + 1] 87 set datum $str 88 } else { 89 set key $str 90 gets $did datum 91 } 92 set keys($n) $key 93 set data($n) [pad_data $pmethod $datum] 94 95 set ret [eval {$pdb put} {$key [chop_data $pmethod $datum]}] 96 error_check_good put($n) $ret 0 97 } 98 close $did 99 100 # Open and associate the secondaries 101 set sdbs {} 102 puts "opening secondaries." 103 for { set i 0 } { $i < [llength $omethods] } { incr i } { 104 set sdb [eval {berkdb_open -create -env} $env \ 105 [lindex $omethods $i] [lindex $argses $i] $snamebase.$i.db] 106 error_check_good second_open($i) [is_valid_db $sdb] TRUE 107 108 error_check_good db_associate($i) \ 109 [$pdb associate -create [callback_n $i] $sdb] 0 110 lappend sdbs $sdb 111 } 112 check_secondaries $pdb $sdbs $nentries keys data "Si$tnum.a" 113 114 puts -nonewline "\tSi$tnum.b: Put/overwrite loop ... " 115 for { set n 0 } { $n < $nentries } { incr n } { 116 set newd $data($n).$keys($n) 117 set ret [eval {$pdb put} {$keys($n) [chop_data $pmethod $newd]}] 118 error_check_good put_overwrite($n) $ret 0 119 set data($n) [pad_data $pmethod $newd] 120 } 121 122 # Close the secondaries again. 123 puts "closing secondaries." 124 for { set sdb [lindex $sdbs end] } { [string length $sdb] > 0 } \ 125 { set sdb [lindex $sdbs end] } { 126 error_check_good second_close($sdb) [$sdb close] 0 127 set sdbs [lrange $sdbs 0 end-1] 128 check_secondaries \ 129 $pdb $sdbs $nentries keys data "Si$tnum.b" 130 } 131 132 # Delete the second half of the entries through the primary. 133 # We do the second half so we can just pass keys(0 ... n/2) 134 # to check_secondaries. 135 set half [expr $nentries / 2] 136 puts -nonewline \ 137 "\tSi$tnum.c: Primary delete loop: deleting $half entries ..." 138 for { set n $half } { $n < $nentries } { incr n } { 139 set ret [$pdb del $keys($n)] 140 error_check_good pdel($n) $ret 0 141 } 142 143 # Open and associate the secondaries 144 set sdbs {} 145 puts "\n\t\topening secondaries." 146 for { set i 0 } { $i < [llength $omethods] } { incr i } { 147 set sdb [eval {berkdb_open -create -env} $env \ 148 [lindex $omethods $i] [lindex $argses $i] \ 149 $snamebase.r2.$i.db] 150 error_check_good second_open($i) [is_valid_db $sdb] TRUE 151 152 error_check_good db_associate($i) \ 153 [$pdb associate -create [callback_n $i] $sdb] 0 154 lappend sdbs $sdb 155 } 156 check_secondaries $pdb $sdbs $half keys data "Si$tnum.c" 157 158 # Delete half of what's left, through the first secondary. 159 set quar [expr $half / 2] 160 puts "\tSi$tnum.d: Secondary delete loop: deleting $quar entries" 161 set sdb [lindex $sdbs 0] 162 set callback [callback_n 0] 163 for { set n $quar } { $n < $half } { incr n } { 164 set skey [$callback $keys($n) [pad_data $pmethod $data($n)]] 165 set ret [$sdb del $skey] 166 error_check_good sdel($n) $ret 0 167 } 168 check_secondaries $pdb $sdbs $quar keys data "Si$tnum.d" 169 170 foreach sdb $sdbs { 171 error_check_good secondary_close [$sdb close] 0 172 } 173 error_check_good primary_close [$pdb close] 0 174 175 # Close the env if it was created within this test. 176 if { $eindex == -1 } { 177 error_check_good env_close [$env close] 0 178 } 179} 180