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