1
# See the file LICENSE for redistribution information.
3
# Copyright (c) 1996-2002
4
# Sleepycat Software. All rights reserved.
9
# TEST Test recovery after checksum error.
10
proc recd020 { method args} {
12
global log_log_record_types
16
set pgindex [lsearch -exact $args "-pagesize"]
17
if { $pgindex != -1 } {
18
puts "Recd020: skipping for specific pagesizes"
21
if { [is_queueext $method] == 1 } {
22
puts "Recd020: skipping for method $method"
26
puts "Recd020: $method recovery after checksum error"
28
# Create the database and environment.
31
set testfile recd020.db
32
set flags "-create -txn -home $testdir"
34
puts "\tRecd020.a: creating environment"
35
set env_cmd "berkdb_env $flags"
36
set dbenv [eval $env_cmd]
37
error_check_good dbenv [is_valid_env $dbenv] TRUE
40
set orig_fixed_len $fixed_len
41
set fixed_len [expr $pgsize / 4]
42
set opts [convert_args $method $args]
43
set omethod [convert_method $method]
44
set oflags "-create $omethod -mode 0644 \
45
-auto_commit -chksum -pagesize $pgsize $opts $testfile"
46
set db [eval {berkdb_open} -env $dbenv $oflags]
52
puts "\tRecd020.b: Put some data"
53
for { set i 1 } { $i <= $nument } { incr i } {
54
# Use 'i' as key so method doesn't matter
60
error_check_good txn_begin [is_valid_txn $txn $dbenv] TRUE
61
error_check_good db_put \
62
[$db put -txn $txn $key [chop_data $method $data]] 0
63
error_check_good txn_commit [$txn commit] 0
65
error_check_good db_close [$db close] 0
66
error_check_good env_close [$dbenv close] 0
68
# We need to remove the env so that we don't get cached
71
error_check_good env_remove [berkdb envremove -home $testdir] 0
73
puts "\tRecd020.c: Overwrite part of database"
75
# First just touch some bits in the file. We want to go
76
# through the paging system, so touch some data pages,
77
# like the middle of page 2.
78
# We should get a checksum error for the checksummed file.
81
set fid [open $testdir/$testfile r+]
82
fconfigure $fid -translation binary
83
set seeklen [expr $pgsize * $pg + 200]
84
seek $fid $seeklen start
85
set byte [read $fid 1]
86
binary scan $byte c val
87
set newval [expr ~$val]
88
set newbyte [binary format c $newval]
89
seek $fid $seeklen start
90
puts -nonewline $fid $newbyte
94
# Verify we get the checksum error. When we get it, it should
95
# log the error as well, so when we run recovery we'll need to
96
# do catastrophic recovery. We do this in a sub-process so that
97
# the files are closed after the panic.
99
set f1 [open |$tclsh_path r+]
100
puts $f1 "source $test_path/test.tcl"
102
set env_cmd "berkdb_env_noerr $flags"
103
set dbenv [send_cmd $f1 $env_cmd]
104
error_check_good dbenv [is_valid_env $dbenv] TRUE
106
set db [send_cmd $f1 "{berkdb_open_noerr} -env $dbenv $oflags"]
107
error_check_good db [is_valid_db $db] TRUE
109
# We need to set non-blocking mode so that after each command
110
# we can read all the remaining output from that command and
111
# we can know what the output from one command is.
112
fconfigure $f1 -blocking 0
115
for { set i 1 } { $i <= $nument } { incr i } {
116
set stat [send_cmd $f1 "catch {$db get $i} r"]
117
set getret [send_cmd $f1 "puts \$r"]
120
error_check_good dbget:fail [is_substr $getret \
121
"checksum error: catastrophic recovery required"] 1
123
# Now verify that it was an error on the page we set.
124
error_check_good dbget:pg$pg [is_substr $ret \
125
"failed for page $pg"] 1
128
set key [lindex [lindex $getret 0] 0]
129
set data [lindex [lindex $getret 0] 1]
130
error_check_good keychk $key $i
131
error_check_good datachk $data \
132
[pad_data $method $i$datastr]
135
error_check_good got_chksum $got_err 1
136
set ret [send_cmd $f1 "$db close"]
138
error_check_good db:fail [is_substr $ret "run recovery"] 1
140
set ret [send_cmd $f1 "$dbenv close"]
141
error_check_good env_close:fail [is_substr $ret "run recovery"] 1
144
# Keep track of the log types we've seen
145
if { $log_log_record_types == 1} {
146
logtrack_read $testdir
149
puts "\tRecd020.d: Run normal recovery"
150
set ret [catch {exec $util_path/db_recover -h $testdir} r]
151
error_check_good db_recover $ret 1
152
error_check_good dbrec:fail \
153
[is_substr $r "checksum error: catastrophic recovery required"] 1
155
catch {fileremove $testdir/$testfile} ret
156
puts "\tRecd020.e: Run catastrophic recovery"
157
set ret [catch {exec $util_path/db_recover -c -h $testdir} r]
158
error_check_good db_recover $ret 0
161
# Now verify the data was reconstructed correctly.
163
set env_cmd "berkdb_env_noerr $flags"
164
set dbenv [eval $env_cmd]
165
error_check_good dbenv [is_valid_env $dbenv] TRUE
167
set db [eval {berkdb_open} -env $dbenv $oflags]
168
error_check_good db [is_valid_db $db] TRUE
170
for { set i 1 } { $i <= $nument } { incr i } {
171
set stat [catch {$db get $i} ret]
172
error_check_good stat $stat 0
173
set key [lindex [lindex $ret 0] 0]
174
set data [lindex [lindex $ret 0] 1]
175
error_check_good keychk $key $i
176
error_check_good datachk $data [pad_data $method $i$datastr]
178
error_check_good db_close [$db close] 0
179
error_check_good env_close [$dbenv close] 0