1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
|
# See the file LICENSE for redistribution information.
#
# Copyright (c) 1996-2002
# Sleepycat Software. All rights reserved.
#
# $Id: recd001.tcl,v 1.1.1.1 2003/11/20 22:13:57 toshok Exp $
#
# TEST recd001
# TEST Per-operation recovery tests for non-duplicate, non-split
# TEST messages. Makes sure that we exercise redo, undo, and do-nothing
# TEST condition. Any test that appears with the message (change state)
# TEST indicates that we've already run the particular test, but we are
# TEST running it again so that we can change the state of the data base
# TEST to prepare for the next test (this applies to all other recovery
# TEST tests as well).
# TEST
# TEST These are the most basic recovery tests. We do individual recovery
# TEST tests for each operation in the access method interface. First we
# TEST create a file and capture the state of the database (i.e., we copy
# TEST it. Then we run a transaction containing a single operation. In
# TEST one test, we abort the transaction and compare the outcome to the
# TEST original copy of the file. In the second test, we restore the
# TEST original copy of the database and then run recovery and compare
# TEST this against the actual database.
proc recd001 { method {select 0} args} {
global fixed_len
source ./include.tcl
set orig_fixed_len $fixed_len
set opts [convert_args $method $args]
set omethod [convert_method $method]
puts "Recd001: $method operation/transaction tests"
# Create the database and environment.
env_cleanup $testdir
# The recovery tests were originally written to
# do a command, abort, do it again, commit, and then
# repeat the sequence with another command. Each command
# tends to require that the previous command succeeded and
# left the database a certain way. To avoid cluttering up the
# op_recover interface as well as the test code, we create two
# databases; one does abort and then commit for each op, the
# other does prepare, prepare-abort, and prepare-commit for each
# op. If all goes well, this allows each command to depend
# exactly one successful iteration of the previous command.
set testfile recd001.db
set testfile2 recd001-2.db
set flags "-create -txn -home $testdir"
puts "\tRecd001.a.0: creating environment"
set env_cmd "berkdb_env $flags"
set dbenv [eval $env_cmd]
error_check_good dbenv [is_valid_env $dbenv] TRUE
#
# We need to create a database to get the pagesize (either
# the default or whatever might have been specified).
# Then remove it so we can compute fixed_len and create the
# real database.
set oflags "-create $omethod -mode 0644 \
-env $dbenv $opts $testfile"
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
set stat [$db stat]
#
# Compute the fixed_len based on the pagesize being used.
# We want the fixed_len to be 1/4 the pagesize.
#
set pg [get_pagesize $stat]
error_check_bad get_pagesize $pg -1
set fixed_len [expr $pg / 4]
error_check_good db_close [$db close] 0
error_check_good dbremove [berkdb dbremove -env $dbenv $testfile] 0
# Convert the args again because fixed_len is now real.
# Create the databases and close the environment.
# cannot specify db truncate in txn protected env!!!
set opts [convert_args $method ""]
set omethod [convert_method $method]
set oflags "-create $omethod -mode 0644 \
-env $dbenv $opts $testfile"
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
error_check_good db_close [$db close] 0
set oflags "-create $omethod -mode 0644 \
-env $dbenv $opts $testfile2"
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
error_check_good db_close [$db close] 0
error_check_good env_close [$dbenv close] 0
puts "\tRecd001.a.1: Verify db_printlog can read logfile"
set tmpfile $testdir/printlog.out
set stat [catch {exec $util_path/db_printlog -h $testdir \
> $tmpfile} ret]
error_check_good db_printlog $stat 0
fileremove $tmpfile
# List of recovery tests: {CMD MSG} pairs.
set rlist {
{ {DB put -txn TXNID $key $data} "Recd001.b: put"}
{ {DB del -txn TXNID $key} "Recd001.c: delete"}
{ {DB put -txn TXNID $bigkey $data} "Recd001.d: big key put"}
{ {DB del -txn TXNID $bigkey} "Recd001.e: big key delete"}
{ {DB put -txn TXNID $key $bigdata} "Recd001.f: big data put"}
{ {DB del -txn TXNID $key} "Recd001.g: big data delete"}
{ {DB put -txn TXNID $key $data} "Recd001.h: put (change state)"}
{ {DB put -txn TXNID $key $newdata} "Recd001.i: overwrite"}
{ {DB put -txn TXNID -partial {$off $len} $key $partial_grow}
"Recd001.j: partial put growing"}
{ {DB put -txn TXNID $key $newdata} "Recd001.k: overwrite (fix)"}
{ {DB put -txn TXNID -partial {$off $len} $key $partial_shrink}
"Recd001.l: partial put shrinking"}
{ {DB put -txn TXNID -append $data} "Recd001.m: put -append"}
{ {DB get -txn TXNID -consume} "Recd001.n: db get -consume"}
}
# These are all the data values that we're going to need to read
# through the operation table and run the recovery tests.
if { [is_record_based $method] == 1 } {
set key 1
} else {
set key recd001_key
}
set data recd001_data
set newdata NEWrecd001_dataNEW
set off 3
set len 12
set partial_grow replacement_record_grow
set partial_shrink xxx
if { [is_fixed_length $method] == 1 } {
set len [string length $partial_grow]
set partial_shrink $partial_grow
}
set bigdata [replicate $key $fixed_len]
if { [is_record_based $method] == 1 } {
set bigkey $fixed_len
} else {
set bigkey [replicate $key $fixed_len]
}
foreach pair $rlist {
set cmd [subst [lindex $pair 0]]
set msg [lindex $pair 1]
if { $select != 0 } {
set tag [lindex $msg 0]
set tail [expr [string length $tag] - 2]
set tag [string range $tag $tail $tail]
if { [lsearch $select $tag] == -1 } {
continue
}
}
if { [is_queue $method] != 1 } {
if { [string first append $cmd] != -1 } {
continue
}
if { [string first consume $cmd] != -1 } {
continue
}
}
# if { [is_fixed_length $method] == 1 } {
# if { [string first partial $cmd] != -1 } {
# continue
# }
# }
op_recover abort $testdir $env_cmd $testfile $cmd $msg
op_recover commit $testdir $env_cmd $testfile $cmd $msg
#
# Note that since prepare-discard ultimately aborts
# the txn, it must come before prepare-commit.
#
op_recover prepare-abort $testdir $env_cmd $testfile2 \
$cmd $msg
op_recover prepare-discard $testdir $env_cmd $testfile2 \
$cmd $msg
op_recover prepare-commit $testdir $env_cmd $testfile2 \
$cmd $msg
}
set fixed_len $orig_fixed_len
if { [is_fixed_length $method] == 1 } {
puts "Skipping remainder of test for fixed length methods"
return
}
#
# Check partial extensions. If we add a key/data to the database
# and then expand it using -partial, then recover, recovery was
# failing in #3944. Check that scenario here.
#
# !!!
# We loop here because on each iteration, we need to clean up
# the old env (i.e. this test does not depend on earlier runs).
# If we run it without cleaning up the env inbetween, we do not
# test the scenario of #3944.
#
set len [string length $data]
set len2 256
set part_data [replicate "abcdefgh" 32]
set p [list 0 $len]
set cmd [subst \
{DB put -txn TXNID -partial {$len $len2} $key $part_data}]
set msg "Recd001.o: partial put prepopulated/expanding"
foreach op {abort commit prepare-abort prepare-discard prepare-commit} {
env_cleanup $testdir
set dbenv [eval $env_cmd]
error_check_good dbenv [is_valid_env $dbenv] TRUE
set t [$dbenv txn]
error_check_good txn_begin [is_valid_txn $t $dbenv] TRUE
set oflags "-create $omethod -mode 0644 \
-env $dbenv -txn $t $opts $testfile"
set db [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db] TRUE
set oflags "-create $omethod -mode 0644 \
-env $dbenv -txn $t $opts $testfile2"
set db2 [eval {berkdb_open} $oflags]
error_check_good db_open [is_valid_db $db2] TRUE
set ret [$db put -txn $t -partial $p $key $data]
error_check_good dbput $ret 0
set ret [$db2 put -txn $t -partial $p $key $data]
error_check_good dbput $ret 0
error_check_good txncommit [$t commit] 0
error_check_good dbclose [$db close] 0
error_check_good dbclose [$db2 close] 0
error_check_good dbenvclose [$dbenv close] 0
op_recover $op $testdir $env_cmd $testfile $cmd $msg
}
return
}
|