1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 2003-2009 Oracle. All rights reserved. 4# 5# $Id$ 6# 7# TEST txn011 8# TEST Test durable and non-durable txns. 9# TEST Test a mixed env (with both durable and non-durable 10# TEST dbs), then a purely non-durable env. Make sure commit 11# TEST and abort work, and that only the log records we 12# TEST expect are written. 13# TEST Test that we can't get a durable handle on an open ND 14# TEST database, or vice versa. Test that all subdb's 15# TEST must be of the same type (D or ND). 16proc txn011 { {ntxns 100} } { 17 source ./include.tcl 18 global util_path 19 20 foreach envtype { "" "-private" } { 21 puts "Txn011: Non-durable txns ($envtype)." 22 env_cleanup $testdir 23 24 puts "\tTxn011.a: Persistent env recovery with -log_inmemory" 25 set lbuf [expr 8 * [expr 1024 * 1024]] 26 set env_cmd "berkdb_env -create \ 27 -home $testdir -txn -log_inmemory -log_buffer $lbuf" 28 set ndenv [eval $env_cmd $envtype] 29 set db [berkdb_open -create -auto_commit \ 30 -btree -env $ndenv -notdurable test.db] 31 check_log_records $testdir 32 error_check_good db_close [$db close] 0 33 error_check_good ndenv_close [$ndenv close] 0 34 35 # Run recovery with -e to retain environment. 36 set stat [catch {exec $util_path/db_recover -e -h $testdir} ret] 37 error_check_good db_printlog $stat 0 38 39 # Rejoin env and make sure that the db is still there. 40 set ndenv [berkdb_env -home $testdir] 41 set db [berkdb_open -auto_commit -env $ndenv test.db] 42 error_check_good db_close [$db close] 0 43 error_check_good ndenv_close [$ndenv close] 0 44 env_cleanup $testdir 45 46 # Start with a new env for the next test. 47 set ndenv [eval $env_cmd] 48 error_check_good env_open [is_valid_env $ndenv] TRUE 49 50 # Open/create the database. 51 set testfile notdurable.db 52 set db [eval berkdb_open -create \ 53 -auto_commit -env $ndenv -notdurable -btree $testfile] 54 error_check_good dbopen [is_valid_db $db] TRUE 55 56 puts "\tTxn011.b: Abort txns in in-memory logging env." 57 txn011_runtxns $ntxns $db $ndenv abort 58 # Make sure there is nothing in the db. 59 txn011_check_empty $db $ndenv 60 61 puts "\tTxn011.c: Commit txns in in-memory logging env." 62 txn011_runtxns $ntxns $db $ndenv commit 63 64 # Make sure we haven't written any inappropriate log records 65 check_log_records $testdir 66 67 # Clean up non-durable env tests. 68 error_check_good db_close [$db close] 0 69 error_check_good ndenv_close [$ndenv close] 0 70 env_cleanup $testdir 71 72 puts "\tTxn011.d: Set up mixed durable/non-durable test." 73 # Open/create the mixed environment 74 set mixed_env_cmd "berkdb_env_noerr -create \ 75 -home $testdir -txn -log_inmemory -log_buffer $lbuf" 76 set env [eval $mixed_env_cmd] 77 error_check_good env_open [is_valid_env $env] TRUE 78 check_log_records $testdir 79 80 # Open/create the non-durable database 81 set nondurfile nondurable.db 82 set ndb [berkdb_open_noerr -create\ 83 -auto_commit -env $env -btree -notdurable $nondurfile] 84 error_check_good dbopen [is_valid_db $ndb] TRUE 85 check_log_records $testdir 86 87 puts "\tTxn011.e: Abort txns in non-durable db." 88 txn011_runtxns $ntxns $ndb $env abort 89 # Make sure there is nothing in the db. 90 txn011_check_empty $ndb $env 91 check_log_records $testdir 92 93 puts "\tTxn011.f: Commit txns in non-durable db." 94 txn011_runtxns $ntxns $ndb $env commit 95 check_log_records $testdir 96 97 # Open/create the durable database 98 set durfile durable.db 99 set ddb [eval berkdb_open_noerr \ 100 -create -auto_commit -env $env -btree $durfile] 101 error_check_good dbopen [is_valid_db $ddb] TRUE 102 103 # Try to get a not-durable handle on the durable db. 104 puts "\tTxn011.g: Try to get a not-durable handle on\ 105 an open durable db." 106 set errormsg "Cannot open DURABLE and NOT DURABLE handles" 107 catch {berkdb_open_noerr \ 108 -auto_commit -env $env -notdurable $durfile} res 109 error_check_good handle_error1 [is_substr $res $errormsg] 1 110 error_check_good ddb_close [$ddb close] 0 111 112 # Try to get a not-durable handle when reopening the durable 113 # db (this should work). 114 set db [berkdb_open_noerr \ 115 -auto_commit -env $env -notdurable $durfile] 116 error_check_good db_reopen [is_valid_db $db] TRUE 117 error_check_good db_close [$db close] 0 118 119 # Now reopen as durable for the remainder of the test. 120 set ddb [berkdb_open_noerr \ 121 -auto_commit -env $env -btree $durfile] 122 error_check_good dbopen [is_valid_db $ddb] TRUE 123 124 puts "\tTxn011.h: Abort txns in durable db." 125 # Add items to db in several txns but abort every one. 126 txn011_runtxns $ntxns $ddb $env abort 127 # Make sure there is nothing in the db. 128 txn011_check_empty $ddb $env 129 130 puts "\tTxn011.i: Commit txns in durable db." 131 txn011_runtxns $ntxns $ddb $env commit 132 133 puts "\tTxn011.j: Subdbs must all be durable or all not durable." 134 # Ask for -notdurable on durable db/subdb 135 set sdb1 [eval berkdb_open_noerr -create -auto_commit \ 136 -env $env -btree testfile1.db subdb1] 137 catch {set sdb2 [eval berkdb_open_noerr -create -auto_commit \ 138 -env $env -btree -notdurable testfile1.db subdb2]} res 139 error_check_good same_type_subdb1 [is_substr $res $errormsg] 1 140 error_check_good sdb1_close [$sdb1 close] 0 141 142 # Ask for durable on notdurable db/subdb 143 set sdb3 [eval berkdb_open_noerr -create -auto_commit \ 144 -env $env -btree -notdurable testfile2.db subdb3] 145 catch {set sdb4 [eval berkdb_open_noerr -create -auto_commit \ 146 -env $env -btree testfile2.db subdb4]} res 147 error_check_good same_type_subdb2 [is_substr $res $errormsg] 1 148 error_check_good sdb3_close [$sdb3 close] 0 149 150 puts "\tTxn011.k: Try to get a durable handle on a\ 151 not-durable db." 152 # Try to get a durable handle on a not-durable database, 153 # while open. This should fail, but getting a durable handle 154 # when re-opening should work. 155 catch {berkdb_open_noerr -auto_commit -env $env $nondurfile} res 156 error_check_good handle_error [is_substr $res $errormsg] 1 157 error_check_good ndb_close [$ndb close] 0 158 159 set ndb [berkdb_open_noerr -auto_commit -env $env $nondurfile] 160 error_check_good ndb_reopen [is_valid_db $ndb] TRUE 161 error_check_good ndb_close [$ndb close] 0 162 163 # Clean up mixed env. 164 error_check_good ddb_close [$ddb close] 0 165 error_check_good env_close [$env close] 0 166 } 167} 168 169proc txn011_runtxns { ntxns db env end } { 170 source ./include.tcl 171 172 set did [open $dict] 173 set i 0 174 while { [gets $did str] != -1 && $i < $ntxns } { 175 set txn [$env txn] 176 error_check_good txn_begin [is_valid_txn $txn $env] TRUE 177 178 error_check_good db_put_txn [$db put -txn $txn $i $str] 0 179 error_check_good txn_$end [$txn $end] 0 180 incr i 181 } 182 close $did 183} 184 185# Verify that a database is empty 186proc txn011_check_empty { db env } { 187 # Start a transaction 188 set t [$env txn] 189 error_check_good txn [is_valid_txn $t $env] TRUE 190 set txn "-txn $t" 191 192 # If a cursor get -first returns nothing, the db is empty. 193 set dbc [eval {$db cursor} $txn] 194 error_check_good db_cursor [is_substr $dbc $db] 1 195 set ret [$dbc get -first] 196 error_check_good get_on_empty [string length $ret] 0 197 error_check_good dbc_close [$dbc close] 0 198 199 # End transaction 200 error_check_good txn [$t commit] 0 201} 202 203# Some log records are still produced when we run create in a 204# non-durable db in a regular env. Just make sure we don't see 205# any unexpected types. 206proc check_log_records { dir } { 207 global util_path 208 209 set tmpfile $dir/printlog.out 210 set stat [catch {exec $util_path/db_printlog -h $dir > $tmpfile} ret] 211 error_check_good db_printlog $stat 0 212 213 set f [open $tmpfile r] 214 while { [gets $f record] >= 0 } { 215 set r [regexp {\[[^\]]*\]\[[^\]]*\]([^\:]*)\:} $record whl name] 216 if { $r == 1 && [string match *_debug $name] != 1 && \ 217 [string match __txn_regop $name] != 1 && \ 218 [string match __txn_child $name] != 1 } { 219 puts "FAIL: unexpected log record $name found" 220 } 221 } 222 close $f 223 fileremove $tmpfile 224} 225