1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1996,2008 Oracle. All rights reserved. 4# 5# $Id: test092.tcl,v 12.7 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST test092 8# TEST Test of DB_DIRTY_READ [#3395] 9# TEST 10# TEST We set up a database with nentries in it. We then open the 11# TEST database read-only twice. One with dirty reads and one without. 12# TEST We open the database for writing and update some entries in it. 13# TEST Then read those new entries via db->get (clean and dirty), and 14# TEST via cursors (clean and dirty). 15proc test092 { method {nentries 1000} args } { 16 source ./include.tcl 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 "Test092 skipping for env $env" 24 return 25 } 26 set args [convert_args $method $args] 27 set encargs "" 28 set args [split_encargs $args encargs] 29 set omethod [convert_method $method] 30 31 puts "Test092: Dirty Read Test $method $nentries" 32 33 # Create the database and open the dictionary 34 set testfile test092.db 35 set t1 $testdir/t1 36 set t2 $testdir/t2 37 set t3 $testdir/t3 38 39 env_cleanup $testdir 40 41 set lmax [expr $nentries * 2] 42 set lomax [expr $nentries * 2] 43 set env [eval {berkdb_env -create -txn} $encargs -home $testdir \ 44 -lock_max_locks $lmax -lock_max_objects $lomax] 45 error_check_good dbenv [is_valid_env $env] TRUE 46 47 set db [eval {berkdb_open -env $env -create \ 48 -mode 0644 $omethod} $args {$testfile}] 49 error_check_good dbopen [is_valid_db $db] TRUE 50 51 # Here is the loop where we put each key/data pair. 52 # Key is entry, data is entry also. 53 puts "\tTest092.a: put loop" 54 set count 0 55 set did [open $dict] 56 while { [gets $did str] != -1 && $count < $nentries } { 57 if { [is_record_based $method] == 1 } { 58 global kvals 59 60 set key [expr $count + 1] 61 set kvals($key) [pad_data $method $str] 62 } else { 63 set key $str 64 } 65 set ret [eval {$db put} {$key [chop_data $method $str]}] 66 error_check_good put:$db $ret 0 67 incr count 68 } 69 close $did 70 error_check_good close:$db [$db close] 0 71 72 puts "\tTest092.b: Opening all the handles" 73 # 74 # Open all of our handles. 75 # We need: 76 # 1. Our main txn (t). 77 # 2. A txn that can read dirty data (tdr). 78 # 3. A db handle for writing via txn (dbtxn). 79 # 4. A db handle for clean data (dbcl). 80 # 5. A db handle for dirty data (dbdr). 81 # 6. A cursor handle for dirty txn data (clean db handle using 82 # the dirty txn handle on the cursor call) (dbccl1). 83 # 7. A cursor handle for dirty data (dirty on get call) (dbcdr0). 84 # 8. A cursor handle for dirty data (dirty on cursor call) (dbcdr1). 85 set t [$env txn] 86 error_check_good txnbegin [is_valid_txn $t $env] TRUE 87 88 set tdr [$env txn -read_uncommitted] 89 error_check_good txnbegin:dr [is_valid_txn $tdr $env] TRUE 90 set dbtxn [eval {berkdb_open -auto_commit -env $env -read_uncommitted \ 91 -mode 0644 $omethod} {$testfile}] 92 error_check_good dbopen:dbtxn [is_valid_db $dbtxn] TRUE 93 94 set dbcl [eval {berkdb_open -auto_commit -env $env \ 95 -rdonly -mode 0644 $omethod} {$testfile}] 96 error_check_good dbopen:dbcl [is_valid_db $dbcl] TRUE 97 98 set dbdr [eval {berkdb_open -auto_commit -env $env -read_uncommitted \ 99 -rdonly -mode 0644 $omethod} {$testfile}] 100 error_check_good dbopen:dbdr [is_valid_db $dbdr] TRUE 101 102 set dbccl [$dbcl cursor -txn $tdr] 103 error_check_good dbcurs:dbcl [is_valid_cursor $dbccl $dbcl] TRUE 104 105 set dbcdr0 [$dbdr cursor] 106 error_check_good dbcurs:dbdr0 [is_valid_cursor $dbcdr0 $dbdr] TRUE 107 108 set dbcdr1 [$dbdr cursor -read_uncommitted] 109 error_check_good dbcurs:dbdr1 [is_valid_cursor $dbcdr1 $dbdr] TRUE 110 111 # Test that $db stat can use -read_uncommitted flag. 112 puts "\tTest092.c: Smoke test for db_stat -txn -read_uncommitted" 113 if { [catch \ 114 {set statret [$dbcl stat -txn $t -read_uncommitted]} res] } { 115 puts "FAIL: db_stat -txn -read_uncommitted returned $res" 116 } 117 118 # 119 # Now that we have all of our handles, change all the data in there 120 # to be the key and data the same, but data is capitalized. 121 puts "\tTest092.d: put/get data within a txn" 122 set gflags "" 123 if { [is_record_based $method] == 1 } { 124 set checkfunc test092dr_recno.check 125 append gflags " -recno" 126 } else { 127 set checkfunc test092dr.check 128 } 129 set count 0 130 set did [open $dict] 131 while { [gets $did str] != -1 && $count < $nentries } { 132 if { [is_record_based $method] == 1 } { 133 set key [expr $count + 1] 134 } else { 135 set key $str 136 } 137 set ustr [string toupper $str] 138 set clret [list [list $key [pad_data $method $str]]] 139 set drret [list [list $key [pad_data $method $ustr]]] 140 # 141 # Put the data in the txn. 142 # 143 set ret [eval {$dbtxn put} -txn $t \ 144 {$key [chop_data $method $ustr]}] 145 error_check_good put:$dbtxn $ret 0 146 147 # 148 # Now get the data using the different db handles and 149 # make sure it is dirty or clean data. 150 # 151 # Using the dirty txn should show us dirty data 152 set ret [eval {$dbcl get -txn $tdr} $gflags {$key}] 153 error_check_good dbdr2:get $ret $drret 154 155 set ret [eval {$dbdr get -read_uncommitted} $gflags {$key}] 156 error_check_good dbdr1:get $ret $drret 157 158 set ret [eval {$dbdr get -txn $tdr} $gflags {$key}] 159 error_check_good dbdr2:get $ret $drret 160 161 incr count 162 } 163 close $did 164 165 puts "\tTest092.e: Check dirty data using dirty txn and clean db/cursor" 166 dump_file_walk $dbccl $t1 $checkfunc "-first" "-next" 167 168 puts "\tTest092.f: Check dirty data using -read_uncommitted cget flag" 169 dump_file_walk \ 170 $dbcdr0 $t2 $checkfunc "-first" "-next" "-read_uncommitted" 171 172 puts "\tTest092.g: Check dirty data using -read_uncommitted cursor" 173 dump_file_walk $dbcdr1 $t3 $checkfunc "-first" "-next" 174 175 # 176 # We must close these before aborting the real txn 177 # because they all hold read locks on the pages. 178 # 179 error_check_good dbccl:close [$dbccl close] 0 180 error_check_good dbcdr0:close [$dbcdr0 close] 0 181 error_check_good dbcdr1:close [$dbcdr1 close] 0 182 183 # 184 # Now abort the modifying transaction and rerun the data checks. 185 # 186 puts "\tTest092.h: Aborting the write-txn" 187 error_check_good txnabort [$t abort] 0 188 189 set dbccl [$dbcl cursor -txn $tdr] 190 error_check_good dbcurs:dbcl [is_valid_cursor $dbccl $dbcl] TRUE 191 192 set dbcdr0 [$dbdr cursor] 193 error_check_good dbcurs:dbdr0 [is_valid_cursor $dbcdr0 $dbdr] TRUE 194 195 set dbcdr1 [$dbdr cursor -read_uncommitted] 196 error_check_good dbcurs:dbdr1 [is_valid_cursor $dbcdr1 $dbdr] TRUE 197 198 if { [is_record_based $method] == 1 } { 199 set checkfunc test092cl_recno.check 200 } else { 201 set checkfunc test092cl.check 202 } 203 puts "\tTest092.i: Check clean data using -read_uncommitted cget flag" 204 dump_file_walk $dbccl $t1 $checkfunc "-first" "-next" 205 206 puts "\tTest092.j: Check clean data using -read_uncommitted cget flag" 207 dump_file_walk \ 208 $dbcdr0 $t2 $checkfunc "-first" "-next" "-read_uncommitted" 209 210 puts "\tTest092.k: Check clean data using -read_uncommitted cursor" 211 dump_file_walk $dbcdr1 $t3 $checkfunc "-first" "-next" 212 213 # Clean up our handles 214 error_check_good dbccl:close [$dbccl close] 0 215 error_check_good tdrcommit [$tdr commit] 0 216 error_check_good dbcdr0:close [$dbcdr0 close] 0 217 error_check_good dbcdr1:close [$dbcdr1 close] 0 218 error_check_good dbclose [$dbcl close] 0 219 error_check_good dbclose [$dbdr close] 0 220 error_check_good dbclose [$dbtxn close] 0 221 error_check_good envclose [$env close] 0 222} 223 224# Check functions for test092; keys and data are identical 225# Clean checks mean keys and data are identical. 226# Dirty checks mean data are uppercase versions of keys. 227proc test092cl.check { key data } { 228 error_check_good "key/data mismatch" $key $data 229} 230 231proc test092cl_recno.check { key data } { 232 global kvals 233 234 error_check_good key"$key"_exists [info exists kvals($key)] 1 235 error_check_good "key/data mismatch, key $key" $data $kvals($key) 236} 237 238proc test092dr.check { key data } { 239 error_check_good "key/data mismatch" $key [string tolower $data] 240} 241 242proc test092dr_recno.check { key data } { 243 global kvals 244 245 error_check_good key"$key"_exists [info exists kvals($key)] 1 246 error_check_good "key/data mismatch, key $key" $data \ 247 [string toupper $kvals($key)] 248} 249 250