1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1996,2008 Oracle. All rights reserved. 4# 5# $Id: test089.tcl,v 12.7 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST test089 8# TEST Concurrent Data Store test (CDB) 9# TEST 10# TEST Enhanced CDB testing to test off-page dups, cursor dups and 11# TEST cursor operations like c_del then c_get. 12proc test089 { method {nentries 1000} args } { 13 global datastr 14 global encrypt 15 source ./include.tcl 16 17 # 18 # If we are using an env, then skip this test. It needs its own. 19 set eindex [lsearch -exact $args "-env"] 20 if { $eindex != -1 } { 21 incr eindex 22 set env [lindex $args $eindex] 23 puts "Test089 skipping for env $env" 24 return 25 } 26 set encargs "" 27 set args [convert_args $method $args] 28 set oargs [split_encargs $args encargs] 29 set omethod [convert_method $method] 30 31 puts "Test089: ($oargs) $method CDB Test cursor/dup operations" 32 33 # Process arguments 34 # Create the database and open the dictionary 35 set testfile test089.db 36 set testfile1 test089a.db 37 38 env_cleanup $testdir 39 40 set env [eval {berkdb_env -create -cdb} $encargs -home $testdir] 41 error_check_good dbenv [is_valid_env $env] TRUE 42 43 set db [eval {berkdb_open -env $env -create \ 44 -mode 0644 $omethod} $oargs {$testfile}] 45 error_check_good dbopen [is_valid_db $db] TRUE 46 47 set db1 [eval {berkdb_open -env $env -create \ 48 -mode 0644 $omethod} $oargs {$testfile1}] 49 error_check_good dbopen [is_valid_db $db1] TRUE 50 51 set pflags "" 52 set gflags "" 53 set txn "" 54 set count 0 55 56 # Here is the loop where we put each key/data pair 57 puts "\tTest089.a: Put loop" 58 set did [open $dict] 59 while { [gets $did str] != -1 && $count < $nentries } { 60 if { [is_record_based $method] == 1 } { 61 set key [expr $count + 1] 62 } else { 63 set key $str 64 } 65 set ret [eval {$db put} \ 66 $txn $pflags {$key [chop_data $method $datastr]}] 67 error_check_good put:$db $ret 0 68 set ret [eval {$db1 put} \ 69 $txn $pflags {$key [chop_data $method $datastr]}] 70 error_check_good put:$db1 $ret 0 71 incr count 72 } 73 close $did 74 error_check_good close:$db [$db close] 0 75 error_check_good close:$db1 [$db1 close] 0 76 77 # Database is created, now set up environment 78 79 # Remove old mpools and Open/create the lock and mpool regions 80 error_check_good env:close:$env [$env close] 0 81 set ret [eval {berkdb envremove} $encargs -home $testdir] 82 error_check_good env_remove $ret 0 83 84 set env [eval {berkdb_env_noerr -create -cdb} $encargs -home $testdir] 85 error_check_good dbenv [is_valid_widget $env env] TRUE 86 87 puts "\tTest089.b: CDB cursor dups" 88 89 set db1 [eval {berkdb_open_noerr -env $env -create \ 90 -mode 0644 $omethod} $oargs {$testfile1}] 91 error_check_good dbopen [is_valid_db $db1] TRUE 92 93 # Create a read-only cursor and make sure we can't write with it. 94 set dbcr [$db1 cursor] 95 error_check_good dbcursor [is_valid_cursor $dbcr $db1] TRUE 96 set ret [$dbcr get -first] 97 catch { [$dbcr put -current data] } ret 98 error_check_good is_read_only \ 99 [is_substr $ret "Write attempted on read-only cursor"] 1 100 error_check_good dbcr_close [$dbcr close] 0 101 102 # Create a write cursor and duplicate it. 103 set dbcw [$db1 cursor -update] 104 error_check_good dbcursor [is_valid_cursor $dbcw $db1] TRUE 105 set dup_dbcw [$dbcw dup] 106 error_check_good dup_write_cursor [is_valid_cursor $dup_dbcw $db1] TRUE 107 108 # Position both cursors at get -first. They should find the same data. 109 set get_first [$dbcw get -first] 110 set get_first_dup [$dup_dbcw get -first] 111 error_check_good dup_read $get_first $get_first_dup 112 113 # Test that the write cursors can both write and that they 114 # read each other's writes correctly. First write reversed 115 # datastr with original cursor and read with dup cursor. 116 error_check_good put_current_orig \ 117 [$dbcw put -current [chop_data $method [reverse $datastr]]] 0 118 set reversed [$dup_dbcw get -current] 119 error_check_good check_with_dup [lindex [lindex $reversed 0] 1] \ 120 [pad_data $method [reverse $datastr]] 121 122 # Write forward datastr with dup cursor and read with original. 123 error_check_good put_current_dup \ 124 [$dup_dbcw put -current [chop_data $method $datastr]] 0 125 set forward [$dbcw get -current] 126 error_check_good check_with_orig $forward $get_first 127 128 error_check_good dbcw_close [$dbcw close] 0 129 error_check_good dup_dbcw_close [$dup_dbcw close] 0 130 131 # This tests the failure found in #1923 132 puts "\tTest089.c: Test delete then get" 133 134 set dbc [$db1 cursor -update] 135 error_check_good dbcursor [is_valid_cursor $dbc $db1] TRUE 136 137 for {set kd [$dbc get -first] } { [llength $kd] != 0 } \ 138 {set kd [$dbc get -next] } { 139 error_check_good dbcdel [$dbc del] 0 140 } 141 error_check_good dbc_close [$dbc close] 0 142 error_check_good db_close [$db1 close] 0 143 error_check_good env_close [$env close] 0 144 145 if { [is_btree $method] != 1 } { 146 puts "Skipping rest of test089 for $method method." 147 return 148 } 149 set pgindex [lsearch -exact $args "-pagesize"] 150 if { $pgindex != -1 } { 151 puts "Skipping rest of test089 for specific pagesizes" 152 return 153 } 154 append oargs " -dup " 155 test089_dup $testdir $encargs $oargs $omethod $nentries 156 append oargs " -dupsort " 157 test089_dup $testdir $encargs $oargs $omethod $nentries 158} 159 160proc test089_dup { testdir encargs oargs method nentries } { 161 env_cleanup $testdir 162 set env [eval {berkdb_env -create -cdb} $encargs -home $testdir] 163 error_check_good dbenv [is_valid_env $env] TRUE 164 165 # 166 # Set pagesize small to generate lots of off-page dups 167 # 168 set page 512 169 set nkeys 5 170 set data "data" 171 set key "test089_key" 172 set testfile test089.db 173 puts "\tTest089.d: CDB ($oargs) off-page dups" 174 set oflags "-env $env -create -mode 0644 $oargs $method" 175 set db [eval {berkdb_open} -pagesize $page $oflags $testfile] 176 error_check_good dbopen [is_valid_db $db] TRUE 177 178 puts "\tTest089.e: Fill page with $nkeys keys, with $nentries dups" 179 for { set k 0 } { $k < $nkeys } { incr k } { 180 for { set i 0 } { $i < $nentries } { incr i } { 181 set ret [$db put $key$k $i$data$k] 182 error_check_good dbput $ret 0 183 } 184 } 185 186 # Verify we have off-page duplicates 187 set stat [$db stat] 188 error_check_bad stat:offpage [is_substr $stat "{{Internal pages} 0}"] 1 189 190 # This tests the failure reported in #6950. Skip for -dupsort. 191 puts "\tTest089.f: Clear locks for duped off-page dup cursors." 192 if { [is_substr $oargs dupsort] != 1 } { 193 # Create a read cursor, put it on an off-page dup. 194 set dbcr [$db cursor] 195 error_check_good dbcr [is_valid_cursor $dbcr $db] TRUE 196 set offpage [$dbcr get -get_both test089_key4 900data4] 197 error_check_bad offpage [llength $offpage] 0 198 199 # Create a write cursor, put it on an off-page dup. 200 set dbcw [$db cursor -update] 201 error_check_good dbcw [is_valid_cursor $dbcw $db] TRUE 202 set offpage [$dbcw get -get_both test089_key3 900data3] 203 error_check_bad offpage [llength $offpage] 0 204 205 # Add a new item using the write cursor, then close the cursor. 206 error_check_good add_dup [$dbcw put -after $data] 0 207 error_check_good close_dbcw [$dbcw close] 0 208 209 # Get next dup with read cursor, then close the cursor. 210 set nextdup [$dbcr get -nextdup] 211 error_check_good close_dbcr [$dbcr close] 0 212 } 213 214 puts "\tTest089.g: CDB duplicate write cursors with off-page dups" 215 # Create a write cursor and duplicate it. 216 set dbcw [$db cursor -update] 217 error_check_good dbcursor [is_valid_cursor $dbcw $db] TRUE 218 set dup_dbcw [$dbcw dup] 219 error_check_good dup_write_cursor [is_valid_cursor $dup_dbcw $db] TRUE 220 221 # Position both cursors at get -first. They should find the same data. 222 set get_first [$dbcw get -first] 223 set get_first_dup [$dup_dbcw get -first] 224 error_check_good dup_read $get_first $get_first_dup 225 226 # Test with -after and -before. Skip for -dupsort. 227 if { [is_substr $oargs dupsort] != 1 } { 228 # Original and duplicate cursors both point to first item. 229 # Do a put -before of new string with original cursor, 230 # and a put -after of new string with duplicate cursor. 231 set newdata "newdata" 232 error_check_good put_before [$dbcw put -before $newdata] 0 233 error_check_good put_after [$dup_dbcw put -after $newdata] 0 234 235 # Now walk forward with original cursor ... 236 set first [$dbcw get -first] 237 error_check_good check_first [lindex [lindex $first 0] 1] $newdata 238 set next1 [$dbcw get -next] 239 error_check_good check_next1 $next1 $get_first 240 set next2 [$dbcw get -next] 241 error_check_good check_next2 [lindex [lindex $next2 0] 1] $newdata 242 243 # ... and backward with duplicate cursor. 244 set current [$dup_dbcw get -current] 245 error_check_good check_current [lindex [lindex $current 0] 1] $newdata 246 set prev1 [$dup_dbcw get -prev] 247 error_check_good check_prev1 $prev1 $get_first 248 set prev2 [$dup_dbcw get -prev] 249 error_check_good check_prev2 [lindex [lindex $prev2 0] 1] $newdata 250 } 251 252 puts "\tTest089.h: test delete then get of off-page dups" 253 for {set kd [$dbcw get -first] } { [llength $kd] != 0 } \ 254 {set kd [$dbcw get -next] } { 255 error_check_good dbcdel [$dbcw del] 0 256 } 257 258 error_check_good dbcw_close [$dbcw close] 0 259 error_check_good dup_dbcw_close [$dup_dbcw close] 0 260 261 error_check_good db_close [$db close] 0 262 error_check_good env_close [$env close] 0 263} 264