1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 1996,2008 Oracle.  All rights reserved.
4#
5# $Id: recd022.tcl,v 12.10 2008/01/08 20:58:53 bostic Exp $
6#
7# TEST	recd022
8# TEST	Test that pages allocated by an aborted subtransaction
9# TEST	within an aborted prepared parent transaction are returned
10# TEST 	to the free list after recovery.  This exercises
11# TEST	__db_pg_prepare in systems without FTRUNCATE.  [#7403]
12
13proc recd022 { method args} {
14	global log_log_record_types
15	global fixed_len
16	global is_hp_test
17	source ./include.tcl
18
19	# Skip test for specified page sizes -- we want to
20	# specify our own page size.
21	set pgindex [lsearch -exact $args "-pagesize"]
22	if { $pgindex != -1 } {
23		puts "Recd022: Skipping for specific pagesizes"
24		return
25	}
26
27	# Skip the test for HP-UX, where we can't open an env twice.
28	if { $is_hp_test == 1 } {
29		puts "Recd022: Skipping for HP-UX."
30		return
31	}
32
33
34	# Increase size of fixed-length records to match other methods.
35	set orig_fixed_len $fixed_len
36	set fixed_len 53
37	set opts [convert_args $method $args]
38	set omethod [convert_method $method]
39
40	puts "Recd022: ($method) Page allocation and recovery"
41	puts "Recd022: with aborted prepared txns and child txns."
42
43	# Create the database and environment.
44	env_cleanup $testdir
45	set testfile recd022.db
46
47	puts "\tRecd022.a: creating environment"
48	# We open the env and database with _noerr so we don't
49	# get error messages when cleaning up at the end of the test.
50	set env_cmd "berkdb_env_noerr -create -txn -home $testdir"
51	set dbenv [eval $env_cmd]
52	error_check_good dbenv [is_valid_env $dbenv] TRUE
53
54	# Open database with small pages.
55	puts "\tRecd022.b: creating database with small pages"
56	set pagesize 512
57	set oflags "-create $omethod -mode 0644 -pagesize $pagesize \
58	    -env $dbenv -auto_commit $opts $testfile"
59	set db [eval {berkdb_open_noerr} $oflags]
60	error_check_good db_open [is_valid_db $db] TRUE
61
62	puts "\tRecd022.c: start transaction, put some data"
63	set iter 10
64	set datasize 53
65	set data [repeat "a" $datasize]
66	set iter2 [expr $iter * 2]
67
68        # Start parent and child txns.
69	puts "\tRecd022.d: start child txn, put some data"
70	set parent [$dbenv txn]
71	set child1 [$dbenv txn -parent $parent]
72
73	# Child puts some new data.
74	for { set i 1 } {$i <= $iter } { incr i } {
75		eval {$db put} -txn $child1 $i $data
76	}
77
78	# Abort the child txn.
79	puts "\tRecd022.e: abort child txn"
80	error_check_good child1_abort [$child1 abort] 0
81
82	# Start a second child.  Put some data, enough to allocate
83	# a new page, then delete it.
84	puts "\tRecd022.f: start second child txn, put some data"
85	set child2 [$dbenv txn -parent $parent]
86	for { set i 1 } { $i <= $iter2 } { incr i } {
87		eval {$db put} -txn $child2 $i $data
88	}
89	for { set i 1 } { $i <= $iter2 } { incr i } {
90		eval {$db del} -txn $child2 $i
91	}
92
93	# Put back half the data.
94	for { set i 1 } { $i <= $iter } { incr i } {
95		eval {$db put} -txn $child2 $i $data
96	}
97
98	# Commit second child
99	puts "\tRecd022.g: commit second child txn, prepare parent"
100	error_check_good child2_commit [$child2 commit] 0
101
102	# Prepare parent
103	error_check_good prepare [$parent prepare "ABC"] 0
104
105	# Recover, then abort the recovered parent txn
106	puts "\tRecd022.h: recover, then abort parent"
107	set env1 [berkdb_env -create -recover -home $testdir -txn]
108	set txnlist [$env1 txn_recover]
109	set aborttxn [lindex [lindex $txnlist 0] 0]
110	error_check_good parent_abort [$aborttxn abort] 0
111
112	# Verify database and then clean up.  We still need to get
113	# rid of the handles created before recovery.
114	puts "\tRecd022.i: verify and clean up"
115	verify_dir $testdir
116	set stat [catch {$db close} res]
117	error_check_good db_close [is_substr $res "run recovery"] 1
118	error_check_good env1_close [$env1 close] 0
119	set stat [catch {$dbenv close} res]
120	error_check_good dbenv_close [is_substr $res "run recovery"] 1
121
122	# Track the log types we've seen
123	if { $log_log_record_types == 1} {
124		logtrack_read $testdir
125	}
126
127	# Set fixed_len back to the global value so we don't
128	# mess up other tests.
129	set fixed_len $orig_fixed_len
130	return
131}
132