1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1996,2008 Oracle. All rights reserved. 4# 5# $Id: recd005.tcl,v 12.10 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST recd005 8# TEST Verify reuse of file ids works on catastrophic recovery. 9# TEST 10# TEST Make sure that we can do catastrophic recovery even if we open 11# TEST files using the same log file id. 12proc recd005 { method {select 0 } args } { 13 source ./include.tcl 14 global rand_init 15 16 set envargs "" 17 set zero_idx [lsearch -exact $args "-zero_log"] 18 if { $zero_idx != -1 } { 19 set args [lreplace $args $zero_idx $zero_idx] 20 set envargs "-zero_log" 21 } 22 23 set args [convert_args $method $args] 24 set omethod [convert_method $method] 25 26 puts "Recd005: $method catastrophic recovery ($envargs)" 27 28 berkdb srand $rand_init 29 30 set testfile1 recd005.1.db 31 set testfile2 recd005.2.db 32 set max_locks 2000 33 set eflags "-create -txn -lock_max_locks $max_locks \ 34 -lock_max_objects $max_locks -home $testdir $envargs" 35 36 set tnum 0 37 foreach sizes "{1000 10} {10 1000}" { 38 foreach ops "{abort abort} {abort commit} {commit abort} \ 39 {commit commit}" { 40 env_cleanup $testdir 41 incr tnum 42 43 set s1 [lindex $sizes 0] 44 set s2 [lindex $sizes 1] 45 set op1 [lindex $ops 0] 46 set op2 [lindex $ops 1] 47 puts "\tRecd005.$tnum: $s1 $s2 $op1 $op2" 48 49 puts "\tRecd005.$tnum.a: creating environment" 50 set env_cmd "berkdb_env $eflags" 51 set dbenv [eval $env_cmd] 52 error_check_bad dbenv $dbenv NULL 53 54 # Create the two databases. 55 set oflags \ 56 "-create -mode 0644 -env $dbenv $args $omethod" 57 set db1 [eval {berkdb_open} $oflags $testfile1] 58 error_check_bad db_open $db1 NULL 59 error_check_good db_open [is_substr $db1 db] 1 60 error_check_good db_close [$db1 close] 0 61 62 set db2 [eval {berkdb_open} $oflags $testfile2] 63 error_check_bad db_open $db2 NULL 64 error_check_good db_open [is_substr $db2 db] 1 65 error_check_good db_close [$db2 close] 0 66 $dbenv close 67 68 set dbenv [eval $env_cmd] 69 puts "\tRecd005.$tnum.b: Populating databases" 70 do_one_file \ 71 $testdir $method $dbenv $env_cmd $testfile1 $s1 $op1 72 do_one_file \ 73 $testdir $method $dbenv $env_cmd $testfile2 $s2 $op2 74 75 puts "\tRecd005.$tnum.c: Verifying initial population" 76 check_file $testdir $env_cmd $testfile1 $op1 77 check_file $testdir $env_cmd $testfile2 $op2 78 79 # Now, close the environment (so that recovery will work 80 # on NT which won't allow delete of an open file). 81 reset_env $dbenv 82 83 berkdb debug_check 84 puts -nonewline \ 85 "\tRecd005.$tnum.d: About to run recovery ... " 86 flush stdout 87 88 set stat [catch \ 89 {exec $util_path/db_recover -h $testdir -c} \ 90 result] 91 if { $stat == 1 } { 92 error "Recovery error: $result." 93 } 94 puts "complete" 95 96 # Substitute a file that will need recovery and try 97 # running recovery again. 98 if { $op1 == "abort" } { 99 file copy -force $testdir/$testfile1.afterop \ 100 $testdir/$testfile1 101 move_file_extent $testdir $testfile1 \ 102 afterop copy 103 } else { 104 file copy -force $testdir/$testfile1.init \ 105 $testdir/$testfile1 106 move_file_extent $testdir $testfile1 init copy 107 } 108 if { $op2 == "abort" } { 109 file copy -force $testdir/$testfile2.afterop \ 110 $testdir/$testfile2 111 move_file_extent $testdir $testfile2 \ 112 afterop copy 113 } else { 114 file copy -force $testdir/$testfile2.init \ 115 $testdir/$testfile2 116 move_file_extent $testdir $testfile2 init copy 117 } 118 119 berkdb debug_check 120 puts -nonewline "\tRecd005.$tnum.e:\ 121 About to run recovery on pre-op database ... " 122 flush stdout 123 124 set stat \ 125 [catch {exec $util_path/db_recover \ 126 -h $testdir -c} result] 127 if { $stat == 1 } { 128 error "Recovery error: $result." 129 } 130 puts "complete" 131 132 set dbenv [eval $env_cmd] 133 check_file $testdir $env_cmd $testfile1 $op1 134 check_file $testdir $env_cmd $testfile2 $op2 135 reset_env $dbenv 136 137 puts "\tRecd005.$tnum.f:\ 138 Verify db_printlog can read logfile" 139 set tmpfile $testdir/printlog.out 140 set stat [catch \ 141 {exec $util_path/db_printlog -h $testdir \ 142 > $tmpfile} ret] 143 error_check_good db_printlog $stat 0 144 fileremove $tmpfile 145 } 146 } 147} 148 149proc do_one_file { dir method env env_cmd filename num op } { 150 source ./include.tcl 151 152 set init_file $dir/$filename.t1 153 set afterop_file $dir/$filename.t2 154 set final_file $dir/$filename.t3 155 156 # Save the initial file and open the environment and the first file 157 file copy -force $dir/$filename $dir/$filename.init 158 copy_extent_file $dir $filename init 159 set oflags "-auto_commit -unknown -env $env" 160 set db [eval {berkdb_open} $oflags $filename] 161 162 # Dump out file contents for initial case 163 open_and_dump_file $filename $env $init_file nop \ 164 dump_file_direction "-first" "-next" 165 166 set txn [$env txn] 167 error_check_bad txn_begin $txn NULL 168 error_check_good txn_begin [is_substr $txn $env] 1 169 170 # Now fill in the db and the txnid in the command 171 populate $db $method $txn $num 0 0 172 173 # Sync the file so that we can capture a snapshot to test 174 # recovery. 175 error_check_good sync:$db [$db sync] 0 176 file copy -force $dir/$filename $dir/$filename.afterop 177 copy_extent_file $dir $filename afterop 178 open_and_dump_file $testdir/$filename.afterop NULL \ 179 $afterop_file nop dump_file_direction "-first" "-next" 180 error_check_good txn_$op:$txn [$txn $op] 0 181 182 if { $op == "commit" } { 183 puts "\t\tFile $filename executed and committed." 184 } else { 185 puts "\t\tFile $filename executed and aborted." 186 } 187 188 # Dump out file and save a copy. 189 error_check_good sync:$db [$db sync] 0 190 open_and_dump_file $testdir/$filename NULL $final_file nop \ 191 dump_file_direction "-first" "-next" 192 file copy -force $dir/$filename $dir/$filename.final 193 copy_extent_file $dir $filename final 194 195 # If this is an abort, it should match the original file. 196 # If this was a commit, then this file should match the 197 # afterop file. 198 if { $op == "abort" } { 199 filesort $init_file $init_file.sort 200 filesort $final_file $final_file.sort 201 error_check_good \ 202 diff(initial,post-$op):diff($init_file,$final_file) \ 203 [filecmp $init_file.sort $final_file.sort] 0 204 } else { 205 filesort $afterop_file $afterop_file.sort 206 filesort $final_file $final_file.sort 207 error_check_good \ 208 diff(post-$op,pre-commit):diff($afterop_file,$final_file) \ 209 [filecmp $afterop_file.sort $final_file.sort] 0 210 } 211 212 error_check_good close:$db [$db close] 0 213} 214 215proc check_file { dir env_cmd filename op } { 216 source ./include.tcl 217 218 set init_file $dir/$filename.t1 219 set afterop_file $dir/$filename.t2 220 set final_file $dir/$filename.t3 221 222 open_and_dump_file $testdir/$filename NULL $final_file nop \ 223 dump_file_direction "-first" "-next" 224 if { $op == "abort" } { 225 filesort $init_file $init_file.sort 226 filesort $final_file $final_file.sort 227 error_check_good \ 228 diff(initial,post-$op):diff($init_file,$final_file) \ 229 [filecmp $init_file.sort $final_file.sort] 0 230 } else { 231 filesort $afterop_file $afterop_file.sort 232 filesort $final_file $final_file.sort 233 error_check_good \ 234 diff(pre-commit,post-$op):diff($afterop_file,$final_file) \ 235 [filecmp $afterop_file.sort $final_file.sort] 0 236 } 237} 238