1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2005-2009 Oracle.  All rights reserved.
4#
5# $Id$
6#
7# TEST	txn014
8# TEST	Test of parent and child txns working on the same database.
9# TEST	A txn that will become a parent create a database.
10# TEST	A txn that will not become a parent creates another database.
11# TEST	Start a child txn of the 1st txn.
12# TEST  Verify that the parent txn is disabled while child is open.
13# TEST	1. Child reads contents with child handle (should succeed).
14# TEST	2. Child reads contents with parent handle (should succeed).
15# TEST  Verify that the non-parent txn can read from its database,
16# TEST	and that the child txn cannot.
17# TEST	Return to the child txn.
18# TEST	3. Child writes with child handle (should succeed).
19# TEST	4. Child writes with parent handle (should succeed).
20# TEST
21# TEST	Commit the child, verify that the parent can write again.
22# TEST	Check contents of database with a second child.
23proc txn014 { } {
24	source ./include.tcl
25	global default_pagesize
26
27	set page_size $default_pagesize
28	# If the page size is very small, we increase page size,
29	# so we won't run out of lockers.
30	if { $page_size < 2048 } {
31		set page_size 2048
32	}
33	set tnum "014"
34	puts "Txn$tnum: Test use of parent and child txns."
35	set parentfile test$tnum.db
36	set nonparentfile test$tnum.db.2
37	set method "-btree"
38
39	# Use 5000 entries so there will be new items on the wordlist
40	# when we double nentries in part h.
41	set nentries 5000
42
43	env_cleanup $testdir
44
45	puts "\tTxn$tnum.a: Create environment."
46	set eflags "-create -mode 0644 -txn -home $testdir"
47	set env [eval {berkdb_env_noerr} $eflags]
48	error_check_good env [is_valid_env $env] TRUE
49
50	# Open a database with parent txn and populate.  We populate
51	# before starting up the child txn, because the only allowed
52	# Berkeley DB calls for a parent txn are beginning child txns,
53	# committing, or aborting.
54
55	puts "\tTxn$tnum.b: Start parent txn and open database."
56	set parent [$env txn]
57	error_check_good parent_begin [is_valid_txn $parent $env] TRUE
58	set db [berkdb_open_noerr -pagesize $page_size \
59	    -env $env -txn $parent -create $method $parentfile]
60	populate $db $method $parent $nentries 0 0
61
62	puts "\tTxn$tnum.c: Start non-parent txn and open database."
63	set nonparent [$env txn]
64	error_check_good nonparent_begin [is_valid_txn $nonparent $env] TRUE
65	set db2 [berkdb_open_noerr -pagesize $page_size \
66	    -env $env -txn $nonparent -create $method $nonparentfile]
67	populate $db2 $method $nonparent $nentries 0 0
68
69	# Start child txn and open database.  Parent txn is not yet
70	# committed, but the child should be able to read what's there.
71	# The child txn should also be able to use the parent txn.
72
73	puts "\tTxn$tnum.d: Start child txn."
74	set child [$env txn -parent $parent]
75
76	puts "\tTxn$tnum.e: Verify parent is disabled."
77	catch {$db put -txn $parent a a} ret
78	error_check_good \
79	    parent_disabled [is_substr $ret "Child transaction is active"] 1
80
81	puts "\tTxn$tnum.f: Get a handle on parent's database using child txn."
82	set childdb [berkdb_open_noerr -pagesize $page_size \
83	    -env $env -txn $child $method $parentfile]
84
85	puts "\tTxn$tnum.g: Read database with child txn/child handle,"
86	puts "\tTxn$tnum.g:     and with child txn/parent handle."
87	set did [open $dict]
88	set count 0
89	while { [gets $did str] != -1 && $count < $nentries } {
90		set key $str
91
92		# First use child's handle.
93		set ret [$childdb get -txn $child $key]
94		error_check_good \
95		    get $ret [list [list $key [pad_data $method $str]]]
96
97		# Have the child use the parent's handle.
98		set ret [$db get -txn $child $key]
99		error_check_good \
100		    get $ret [list [list $key [pad_data $method $str]]]
101		incr count
102	}
103	close $did
104
105	# Read the last key from the non-parent database, then try
106	# to read the same key using the child txn.  It will fail.
107	puts "\tTxn$tnum.h: Child cannot read data from non-parent."
108	set ret [$db2 get -txn $nonparent $key]
109
110	# Check the return against $key, because $str has gone on to
111	# the next item in the wordlist.
112	error_check_good \
113	    np_get $ret [list [list $key [pad_data $method $key]]]
114	catch {$db2 get -txn $child $key} ret
115	error_check_good \
116	    child_np_get [is_substr $ret "is still active"] 1
117
118	# The child should also be able to update the database, using
119	# either handle.
120	puts "\tTxn$tnum.i: Write to database with child txn & child handle."
121	populate $childdb $method $child $nentries 0 0
122	puts "\tTxn$tnum.j: Write to database with child txn & parent handle."
123	populate $db $method $child $nentries 0 0
124
125	puts "\tTxn$tnum.k: Commit child, freeing parent."
126	error_check_good child_commit [$child commit] 0
127	error_check_good childdb_close [$childdb close] 0
128
129	puts "\tTxn$tnum.l: Add more entries to db using parent txn."
130	set nentries [expr $nentries * 2]
131	populate $db $method $parent $nentries 0 0
132
133	puts "\tTxn$tnum.m: Start new child txn and read database."
134	set child2 [$env txn -parent $parent]
135	set child2db [berkdb_open_noerr -pagesize $page_size \
136	    -env $env -txn $child2 $method $parentfile]
137
138	set did [open $dict]
139	set count 0
140	while { [gets $did str] != -1 && $count < $nentries } {
141		set key $str
142		set ret [$child2db get -txn $child2 $key]
143		error_check_good \
144		    get $ret [list [list $key [pad_data $method $str]]]	1
145		incr count
146	}
147	close $did
148
149	puts "\tTxn$tnum.n: Clean up."
150	error_check_good child2_commit [$child2 commit] 0
151	error_check_good nonparent_commit [$nonparent commit] 0
152	error_check_good parent_commit [$parent commit] 0
153	error_check_good db_close [$db close] 0
154	error_check_good db2_close [$db2 close] 0
155	error_check_good childdb_close [$child2db close] 0
156	error_check_good env_close [$env close] 0
157}
158
159