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