1
# See the file LICENSE for redistribution information.
3
# Copyright (c) 1999-2002
4
# Sleepycat Software. All rights reserved.
9
# TEST This is a recovery test for create/delete of queue extents. We
10
# TEST then need to recover and make sure the file is correctly existing
11
# TEST or not, as the case may be.
12
proc recd014 { method args} {
16
if { ![is_queueext $method] == 1 } {
17
puts "Recd014: Skipping for method $method"
20
set pgindex [lsearch -exact $args "-pagesize"]
21
if { $pgindex != -1 } {
22
puts "Recd014: skipping for specific pagesizes"
26
set orig_fixed_len $fixed_len
28
# We will use 512-byte pages, to be able to control
29
# when extents get created/removed.
33
set opts [convert_args $method $args]
34
set omethod [convert_method $method]
36
# We want to set -extent 1 instead of what
37
# convert_args gave us.
39
set exti [lsearch -exact $opts "-extent"]
41
set opts [lreplace $opts $exti $exti 1]
43
puts "Recd014: $method extent creation/deletion tests"
45
# Create the database and environment.
48
set testfile recd014.db
49
set flags "-create -txn -home $testdir"
51
puts "\tRecd014.a: creating environment"
52
set env_cmd "berkdb_env $flags"
54
puts "\tRecd014.b: Create test commit"
55
ext_recover_create $testdir $env_cmd $omethod \
56
$opts $testfile commit
57
puts "\tRecd014.b: Create test abort"
58
ext_recover_create $testdir $env_cmd $omethod \
61
puts "\tRecd014.c: Consume test commit"
62
ext_recover_consume $testdir $env_cmd $omethod \
63
$opts $testfile commit
64
puts "\tRecd014.c: Consume test abort"
65
ext_recover_consume $testdir $env_cmd $omethod \
68
set fixed_len $orig_fixed_len
69
puts "\tRecd014.d: Verify db_printlog can read logfile"
70
set tmpfile $testdir/printlog.out
71
set stat [catch {exec $util_path/db_printlog -h $testdir \
73
error_check_good db_printlog $stat 0
77
proc ext_recover_create { dir env_cmd method opts dbfile txncmd } {
78
global log_log_record_types
83
# Keep track of the log types we've seen
84
if { $log_log_record_types == 1} {
89
# Open the environment and set the copy/abort locations
90
set env [eval $env_cmd]
92
set init_file $dir/$dbfile.init
93
set noenvflags "-create $method -mode 0644 -pagesize 512 $opts $dbfile"
94
set oflags "-env $env $noenvflags"
97
error_check_good txn_begin [is_valid_txn $t $env] TRUE
99
set ret [catch {eval {berkdb_open} -txn $t $oflags} db]
100
error_check_good txn_commit [$t commit] 0
103
error_check_good txn_begin [is_valid_txn $t $env] TRUE
106
# The command to execute to create an extent is a put.
107
# We are just creating the first one, so our extnum is 0.
110
set data [chop_data $method [replicate $alphabet 512]]
111
puts "\t\tExecuting command"
112
set putrecno [$db put -txn $t -append $data]
113
error_check_good db_put $putrecno 1
115
# Sync the db so any changes to the file that are
116
# in mpool get written to the disk file before the
119
error_check_good db_sync [$db sync] 0
121
catch { file copy -force $dir/$dbfile $dir/$dbfile.afterop } res
122
copy_extent_file $dir $dbfile afterop
124
error_check_good txn_$txncmd:$t [$t $txncmd] 0
126
# If we don't abort, then we expect success.
127
# If we abort, we expect no file created.
129
set dbq [make_ext_filename $dir $dbfile $extnum]
130
error_check_good extput:exists1 [file exists $dbq] 1
131
set ret [$db get $putrecno]
132
if {$txncmd == "abort"} {
134
# Operation was aborted. Verify our entry is not there.
136
puts "\t\tCommand executed and aborted."
137
error_check_good db_get [llength $ret] 0
140
# Operation was committed, verify it exists.
142
puts "\t\tCommand executed and committed."
143
error_check_good db_get [llength $ret] 1
144
catch { file copy -force $dir/$dbfile $init_file } res
145
copy_extent_file $dir $dbfile init
148
error_check_good txn_begin [is_valid_txn $t $env] TRUE
149
error_check_good db_close [$db close] 0
150
error_check_good txn_commit [$t commit] 0
151
error_check_good env_close [$env close] 0
154
# Run recovery here. Should be a no-op. Verify that
155
# the file still does/n't exist when we are done.
158
puts -nonewline "\t\tAbout to run recovery (no-op) ... "
161
set stat [catch {exec $util_path/db_recover -h $dir -c} result]
163
error "FAIL: Recovery error: $result."
168
# Verify it did not change.
170
error_check_good extput:exists2 [file exists $dbq] 1
171
ext_create_check $dir $txncmd $init_file $dbfile $noenvflags $putrecno
174
# Need a new copy to get the right LSN into the file.
176
catch { file copy -force $dir/$dbfile $init_file } res
177
copy_extent_file $dir $dbfile init
181
# Now move the .afterop file to $dbfile. Run recovery again.
183
file copy -force $dir/$dbfile.afterop $dir/$dbfile
184
move_file_extent $dir $dbfile afterop copy
187
puts -nonewline "\t\tAbout to run recovery (afterop) ... "
190
set stat [catch {exec $util_path/db_recover -h $dir -c} result]
192
error "FAIL: Recovery error: $result."
196
ext_create_check $dir $txncmd $init_file $dbfile $noenvflags $putrecno
199
# To redo, remove the dbfiles. Run recovery again.
201
catch { file rename -force $dir/$dbfile $dir/$dbfile.renamed } res
202
copy_extent_file $dir $dbfile renamed rename
205
puts -nonewline "\t\tAbout to run recovery (init) ... "
208
set stat [catch {exec $util_path/db_recover -h $dir -c} result]
211
# Even though db_recover exits with status 0, it should print out
212
# a warning because the file didn't exist. Db_recover writes this
213
# to stderr. Tcl assumes that ANYTHING written to stderr is an
214
# error, so even though we exit with 0 status, we still get an
215
# error back from 'catch'. Look for the warning.
217
if { $stat == 1 && [is_substr $result "warning"] == 0 } {
218
error "FAIL: Recovery error: $result."
224
# Verify it was redone. However, since we removed the files
225
# to begin with, recovery with abort will not recreate the
226
# extent. Recovery with commit will.
228
if {$txncmd == "abort"} {
229
error_check_good extput:exists3 [file exists $dbq] 0
231
error_check_good extput:exists3 [file exists $dbq] 1
235
proc ext_create_check { dir txncmd init_file dbfile oflags putrecno } {
236
if { $txncmd == "commit" } {
238
# Operation was committed. Verify it did not change.
241
diff(initial,post-recover2):diff($init_file,$dir/$dbfile) \
242
[dbdump_diff "-dar" $init_file $dir $dbfile] 0
245
# Operation aborted. The file is there, but make
246
# sure the item is not.
248
set xdb [eval {berkdb_open} $oflags]
249
error_check_good db_open [is_valid_db $xdb] TRUE
250
set ret [$xdb get $putrecno]
251
error_check_good db_get [llength $ret] 0
252
error_check_good db_close [$xdb close] 0
256
proc ext_recover_consume { dir env_cmd method opts dbfile txncmd} {
257
global log_log_record_types
261
# Keep track of the log types we've seen
262
if { $log_log_record_types == 1} {
267
# Open the environment and set the copy/abort locations
268
set env [eval $env_cmd]
270
set oflags "-create -auto_commit $method -mode 0644 -pagesize 512 \
271
-env $env $opts $dbfile"
274
# Open our db, add some data, close and copy as our
277
set db [eval {berkdb_open} $oflags]
278
error_check_good db_open [is_valid_db $db] TRUE
281
set data [chop_data $method [replicate $alphabet 512]]
284
error_check_good txn_begin [is_valid_txn $txn $env] TRUE
285
set putrecno [$db put -txn $txn -append $data]
286
error_check_good db_put $putrecno 1
287
error_check_good commit [$txn commit] 0
288
error_check_good db_close [$db close] 0
290
puts "\t\tExecuting command"
292
set init_file $dir/$dbfile.init
293
catch { file copy -force $dir/$dbfile $init_file } res
294
copy_extent_file $dir $dbfile init
297
# If we don't abort, then we expect success.
298
# If we abort, we expect no file removed until recovery is run.
300
set db [eval {berkdb_open} $oflags]
301
error_check_good db_open [is_valid_db $db] TRUE
304
error_check_good txn_begin [is_valid_txn $t $env] TRUE
306
set dbcmd "$db get -txn $t -consume"
307
set ret [eval $dbcmd]
308
error_check_good db_sync [$db sync] 0
310
catch { file copy -force $dir/$dbfile $dir/$dbfile.afterop } res
311
copy_extent_file $dir $dbfile afterop
313
error_check_good txn_$txncmd:$t [$t $txncmd] 0
314
error_check_good db_sync [$db sync] 0
315
set dbq [make_ext_filename $dir $dbfile $extnum]
316
if {$txncmd == "abort"} {
318
# Operation was aborted, verify ext did not change.
320
puts "\t\tCommand executed and aborted."
323
# Check that the file exists. Final state.
324
# Since we aborted the txn, we should be able
325
# to get to our original entry.
327
error_check_good postconsume.1 [file exists $dbq] 1
329
diff(init,postconsume.2):diff($init_file,$dir/$dbfile)\
330
[dbdump_diff "-dar" $init_file $dir $dbfile] 0
333
# Operation was committed, verify it does
336
puts "\t\tCommand executed and committed."
338
# Check file existence. Consume operations remove
339
# the extent when we move off, which we should have
341
error_check_good consume_exists [file exists $dbq] 0
343
error_check_good db_close [$db close] 0
344
error_check_good env_close [$env close] 0
347
# Run recovery here on what we ended up with. Should be a no-op.
350
puts -nonewline "\t\tAbout to run recovery (no-op) ... "
353
set stat [catch {exec $util_path/db_recover -h $dir -c} result]
355
error "FAIL: Recovery error: $result."
359
if { $txncmd == "abort"} {
361
# Operation was aborted, verify it did not change.
364
diff(initial,post-recover1):diff($init_file,$dir/$dbfile) \
365
[dbdump_diff "-dar" $init_file $dir $dbfile] 0
368
# Operation was committed, verify it does
369
# not exist. Both operations should result
370
# in no file existing now that we've run recovery.
372
error_check_good after_recover1 [file exists $dbq] 0
376
# Run recovery here. Re-do the operation.
377
# Verify that the file doesn't exist
378
# (if we committed) or change (if we aborted)
381
catch { file copy -force $dir/$dbfile $init_file } res
382
copy_extent_file $dir $dbfile init
384
puts -nonewline "\t\tAbout to run recovery (init) ... "
387
set stat [catch {exec $util_path/db_recover -h $dir -c} result]
389
error "FAIL: Recovery error: $result."
393
if { $txncmd == "abort"} {
395
# Operation was aborted, verify it did not change.
398
diff(initial,post-recover1):diff($init_file,$dir/$dbfile) \
399
[dbdump_diff "-dar" $init_file $dir $dbfile] 0
402
# Operation was committed, verify it does
403
# not exist. Both operations should result
404
# in no file existing now that we've run recovery.
406
error_check_good after_recover2 [file exists $dbq] 0
410
# Now move the .afterop file to $dbfile. Run recovery again.
412
set filecopy [glob $dir/*.afterop]
413
set afterop [lindex $filecopy 0]
414
file rename -force $afterop $dir/$dbfile
415
set afterop [string range $afterop \
416
[expr [string last "/" $afterop] + 1] \
417
[string last "." $afterop]]
418
move_file_extent $dir $dbfile afterop rename
421
puts -nonewline "\t\tAbout to run recovery (afterop) ... "
424
set stat [catch {exec $util_path/db_recover -h $dir -c} result]
426
error "FAIL: Recovery error: $result."
431
if { $txncmd == "abort"} {
433
# Operation was aborted, verify it did not change.
436
diff(initial,post-recover2):diff($init_file,$dir/$dbfile) \
437
[dbdump_diff "-dar" $init_file $dir $dbfile] 0
440
# Operation was committed, verify it still does
443
error_check_good after_recover3 [file exists $dbq] 0