1
# See the file LICENSE for redistribution information.
3
# Copyright (c) 1996-2001
4
# Sleepycat Software. All rights reserved.
6
# $Id: txn.tcl,v 11.20 2001/06/13 18:04:16 sue Exp $
9
# -dir <directory in which to store memp>
10
# -max <max number of concurrent transactions>
11
# -iterations <iterations>
14
puts "txn -dir <directory> -iterations <number of ops> \
15
-max <max number of transactions> -stat"
18
proc txntest { args } {
26
for { set i 0 } { $i < [llength $args] } {incr i} {
27
switch -regexp -- [lindex $args $i] {
28
-d.* { incr i; set testdir [lindex $args $i] }
29
-f.* { incr i; set flags [lindex $args $i] }
30
-i.* { incr i; set iterations [lindex $args $i] }
31
-m.* { incr i; set max [lindex $args $i] }
34
puts -nonewline "FAIL:[timestamp] Usage: "
40
if { $max < $iterations } {
44
# Now run the various functionality tests
45
txn001 $testdir $max $iterations $flags
46
txn002 $testdir $max $iterations
50
proc txn001 { dir max ntxns flags} {
53
puts "Txn001: Basic begin, commit, abort"
58
set env [eval {berkdb \
59
env -create -mode 0644 -txn -txn_max $max -home $dir} $flags]
60
error_check_good evn_open [is_valid_env $env] TRUE
61
txn001_suba $ntxns $env
62
txn001_subb $ntxns $env
63
txn001_subc $ntxns $env
64
# Close and unlink the file
65
error_check_good env_close:$env [$env close] 0
68
proc txn001_suba { ntxns env } {
71
# We will create a bunch of transactions and commit them.
74
puts "Txn001.a: Beginning/Committing $ntxns Transactions in $env"
75
for { set i 0 } { $i < $ntxns } { incr i } {
77
error_check_good txn_begin [is_valid_txn $txn $env] TRUE
82
error_check_good tid_check [lsearch $tid_list $tid] -1
89
error_check_good txn_commit:$t [$t commit] 0
93
proc txn001_subb { ntxns env } {
94
# We will create a bunch of transactions and abort them.
97
puts "Txn001.b: Beginning/Aborting Transactions"
98
for { set i 0 } { $i < $ntxns } { incr i } {
100
error_check_good txn_begin [is_valid_txn $txn $env] TRUE
102
lappend txn_list $txn
105
error_check_good tid_check [lsearch $tid_list $tid] -1
107
lappend tid_list $tid
111
foreach t $txn_list {
112
error_check_good txn_abort:$t [$t abort] 0
116
proc txn001_subc { ntxns env } {
117
# We will create a bunch of transactions and commit them.
120
puts "Txn001.c: Beginning/Prepare/Committing Transactions"
121
for { set i 0 } { $i < $ntxns } { incr i } {
123
error_check_good txn_begin [is_valid_txn $txn $env] TRUE
125
lappend txn_list $txn
128
error_check_good tid_check [lsearch $tid_list $tid] -1
130
lappend tid_list $tid
133
# Now prepare them all
134
foreach t $txn_list {
135
error_check_good txn_prepare:$t \
136
[$t prepare [make_gid global:$t]] 0
139
# Now commit them all
140
foreach t $txn_list {
141
error_check_good txn_commit:$t [$t commit] 0
146
# Verify that read-only transactions do not create any log records
147
proc txn002 { dir max ntxns } {
150
puts "Txn002: Read-only transaction test"
154
env -create -mode 0644 -txn -txn_max $max -home $dir]
155
error_check_good dbenv [is_valid_env $env] TRUE
157
# We will create a bunch of transactions and commit them.
160
puts "Txn002.a: Beginning/Committing Transactions"
161
for { set i 0 } { $i < $ntxns } { incr i } {
163
error_check_good txn_begin [is_valid_txn $txn $env] TRUE
165
lappend txn_list $txn
168
error_check_good tid_check [lsearch $tid_list $tid] -1
170
lappend tid_list $tid
173
# Now commit them all
174
foreach t $txn_list {
175
error_check_good txn_commit:$t [$t commit] 0
178
# Now verify that there aren't any log records.
179
set r [$env log_get -first]
180
error_check_good log_get:$r [llength $r] 0
182
error_check_good env_close:$r [$env close] 0
185
# Test abort/commit/prepare of txns with outstanding child txns.
186
proc txn003 { dir } {
189
puts "Txn003: Outstanding child transaction test"
192
set testfile txn003.db
194
set env_cmd "berkdb env -create -txn -home $dir"
195
set env [eval $env_cmd]
196
error_check_good dbenv [is_valid_env $env] TRUE
198
set oflags {-create -btree -mode 0644 -env $env $testfile}
199
set db [eval {berkdb open} $oflags]
200
error_check_good db_open [is_valid_db $db] TRUE
203
# Put some data so that we can check commit or abort of child
206
set origdata some_data
207
set newdata this_is_new_data
208
set newdata2 some_other_new_data
210
error_check_good db_put [$db put $key $origdata] 0
211
error_check_good dbclose [$db close] 0
213
set db [eval {berkdb open} $oflags]
214
error_check_good db_open [is_valid_db $db] TRUE
216
txn003_check $db $key "Origdata" $origdata
218
puts "\tTxn003.a: Parent abort"
219
set parent [$env txn]
220
error_check_good txn_begin [is_valid_txn $parent $env] TRUE
221
set child [$env txn -parent $parent]
222
error_check_good txn_begin [is_valid_txn $child $env] TRUE
223
error_check_good db_put [$db put -txn $child $key $newdata] 0
224
error_check_good parent_abort [$parent abort] 0
225
txn003_check $db $key "parent_abort" $origdata
226
# Check child handle is invalid
227
set stat [catch {$child abort} ret]
228
error_check_good child_handle $stat 1
229
error_check_good child_h2 [is_substr $ret "invalid command name"] 1
231
puts "\tTxn003.b: Parent commit"
232
set parent [$env txn]
233
error_check_good txn_begin [is_valid_txn $parent $env] TRUE
234
set child [$env txn -parent $parent]
235
error_check_good txn_begin [is_valid_txn $child $env] TRUE
236
error_check_good db_put [$db put -txn $child $key $newdata] 0
237
error_check_good parent_commit [$parent commit] 0
238
txn003_check $db $key "parent_commit" $newdata
239
# Check child handle is invalid
240
set stat [catch {$child abort} ret]
241
error_check_good child_handle $stat 1
242
error_check_good child_h2 [is_substr $ret "invalid command name"] 1
243
error_check_good dbclose [$db close] 0
244
error_check_good env_close [$env close] 0
247
# Since the data check assumes what has come before, the 'commit'
248
# operation must be last.
252
{prepare "\tTxn003.d"}
254
{commit "\tTxn003.f"}
257
foreach pair $rlist {
259
set op [lindex $pair 0]
260
set msg [lindex $pair 1]
261
txn003_body $env_cmd $testfile $dir $key $newdata2 $msg $op
262
set env [eval $env_cmd]
263
error_check_good dbenv [is_valid_env $env] TRUE
266
set db [eval {berkdb open} $oflags]
267
error_check_good db_open [is_valid_db $db] TRUE
269
# For prepare we'll then just
270
# end up aborting after we test what we need to.
271
# So set gooddata to the same as abort.
274
set gooddata $newdata
277
set gooddata $newdata
280
set gooddata $newdata2
283
set gooddata $newdata
286
txn003_check $db $key "parent_$op" $gooddata
287
error_check_good dbclose [$db close] 0
288
error_check_good env_close [$env close] 0
291
puts "\tTxn003.g: Attempt child prepare"
292
set env [eval $env_cmd]
293
error_check_good dbenv [is_valid_env $env] TRUE
295
set db [eval {berkdb open} $oflags]
296
error_check_good db_open [is_valid_db $db] TRUE
298
set parent [$env txn]
299
error_check_good txn_begin [is_valid_txn $parent $env] TRUE
300
set child [$env txn -parent $parent]
301
error_check_good txn_begin [is_valid_txn $child $env] TRUE
302
error_check_good db_put [$db put -txn $child $key $newdata] 0
303
set gid [make_gid child_prepare:$child]
304
set stat [catch {$child prepare $gid} ret]
305
error_check_good child_prepare $stat 1
306
error_check_good child_prep_err \
307
[is_substr $ret "Prepare disallowed on child"] 1
309
puts "\tTxn003.h: Attempt child discard"
310
set stat [catch {$child discard} ret]
311
error_check_good child_discard $stat 1
312
error_check_good child_disc_err \
313
[is_substr $ret "not a restored transaction"] 1
315
# Just commit everybody. We are done.
317
error_check_good parent_commit [$parent commit] 0
318
error_check_good dbclose [$db close] 0
319
error_check_good env_close [$env close] 0
322
proc txn003_body { env_cmd testfile dir key newdata2 msg op } {
327
set gidf $dir/gidfile
330
puts "$msg.0: Executing child script to prepare txns"
332
set p [exec $tclsh_path $test_path/wrap.tcl txnscript.tcl \
333
$testdir/txnout $env_cmd $testfile $gidf $key $newdata2 &]
336
set f1 [open $testdir/txnout r]
340
fileremove -f $testdir/txnout
343
puts -nonewline "$msg.1: Running recovery ... "
346
set env [eval $env_cmd "-recover -verbose {recovery on}"]
347
error_check_good dbenv-recover [is_valid_env $env] TRUE
350
puts "$msg.2: getting txns from txn_recover"
351
set txnlist [$env txn_recover]
352
error_check_good txnlist_len [llength $txnlist] 1
353
set tpair [lindex $txnlist 0]
355
set gfd [open $gidf r]
356
set ret [gets $gfd parentgid]
358
set txn [lindex $tpair 0]
359
set gid [lindex $tpair 1]
360
if { $op == "begin" } {
361
puts "$msg.2: $op new txn"
363
puts "$msg.2: $op parent"
365
error_check_good gidcompare $gid $parentgid
366
if { $op == "prepare" } {
367
set gid [make_gid prepare_recover:$txn]
368
set stat [catch {$txn $op $gid} ret]
369
error_check_good prep_error $stat 1
370
error_check_good prep_err \
371
[is_substr $ret "transaction already prepared"] 1
372
error_check_good txn:prep_abort [$txn abort] 0
373
} elseif { $op == "begin" } {
374
set stat [catch {$env txn} ret]
375
error_check_good begin_error $stat 1
376
error_check_good begin_err \
377
[is_substr $ret "not yet committed transactions is incomplete"] 1
378
error_check_good txn:prep_abort [$txn abort] 0
380
error_check_good txn:$op [$txn $op] 0
382
error_check_good envclose [$env close] 0
385
proc txn003_check { db key msg gooddata } {
386
set kd [$db get $key]
387
set data [lindex [lindex $kd 0] 1]
388
error_check_good $msg $data $gooddata