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