1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2005,2008 Oracle.  All rights reserved.
4#
5# $Id: test116.tcl,v 12.10 2008/01/08 20:58:53 bostic Exp $
6#
7# TEST	test116
8# TEST	Test of basic functionality of lsn_reset.
9# TEST
10# TEST	Create a database in an env.  Copy it to a new file within
11# TEST	the same env.  Reset the page LSNs.
12proc test116 { method {tnum "116"} args } {
13	source ./include.tcl
14	global util_path
15	global passwd
16
17	set orig_tdir $testdir
18	puts "Test$tnum ($method): Test lsn_reset."
19
20	set args [convert_args $method $args]
21	set encargs ""
22	set args [split_encargs $args encargs]
23	set omethod [convert_method $method]
24
25	set testfile A.db
26	set newfile B.db
27	set nentries 50
28	set filenames "A B C D E"
29
30	# This test needs two envs.  If one is provided, create the
31	# second under it.  If no env is provided, create both.
32	set txn ""
33	set txnenv 0
34	set envargs ""
35	set resetargs ""
36	set eindex [lsearch -exact $args "-env"]
37
38	if { $eindex == -1 } {
39		puts "\tTest$tnum.a: Creating env."
40		env_cleanup $testdir
41		set env [eval {berkdb_env} \
42		    -create $encargs $envargs -home $testdir -txn]
43		append args " -auto_commit "
44		error_check_good dbenv [is_valid_env $env] TRUE
45	} else {
46		incr eindex
47		set env [lindex $args $eindex]
48		puts "\tTest$tnum.a: Using provided env $env."
49
50		# Make sure the second env we create has all the
51		# same flags the provided env does.
52		if { [is_substr [$env get_open_flags] "-thread"] } {
53			append envargs " -thread "
54		}
55		if { [is_substr $args "-encrypt"] } {
56			append envargs " -encryptaes $passwd "
57		}
58		if { [is_substr [$env get_encrypt_flags] "-encryptaes"] } {
59			append envargs " -encryptaes $passwd "
60			append resetargs " -encrypt "
61		}
62		set txn ""
63		set txnenv [is_txnenv $env]
64		if { $txnenv == 1 } {
65			append args " -auto_commit "
66		} elseif { $txnenv == 0 } {
67			puts "Skipping Test$tnum for non-transactional env."
68			return
69		}
70	 	set testdir [get_home $env]
71	}
72
73	foreach lorder { 1234 4321 } {
74		# Open database A, populate and close.
75		puts "\tTest$tnum.b: Creating database with lorder $lorder."
76	 	cleanup $testdir $env
77
78		# Create a second directory, and create an env there.
79		set testdir [get_home $env]
80		set newdir $testdir/NEWDIR
81		file mkdir $newdir
82		set newenv [eval {berkdb_env} \
83		    -create $encargs $envargs -home $newdir -txn]
84		error_check_good newenv [is_valid_env $newenv] TRUE
85
86		# We test with subdatabases except with the queue access
87		# method, where they are not allowed.
88		if { [is_queue $method] == 1 } {
89			set db [eval {berkdb_open} -env $env \
90			    $omethod $args -create -mode 0644 $testfile]
91			error_check_good dbopen [is_valid_db $db] TRUE
92			set pgsize [stat_field $db stat "Page size"]
93			if { $txnenv == 1 } {
94				set t [$env txn]
95				error_check_good txn [is_valid_txn $t $env] TRUE
96				set txn "-txn $t"
97			}
98			for { set i 1 } { $i <= $nentries } { incr i } {
99				set key $i
100				set data DATA.$i
101				error_check_good db_put [eval {$db put} \
102				    $txn $key [chop_data $method $data]] 0
103			}
104			if { $txnenv == 1 } {
105				error_check_good t_commit [$t commit] 0
106			}
107			error_check_good db_close [$db close] 0
108		} else {
109			foreach filename $filenames {
110				set db [eval {berkdb_open} -env $env \
111				    $omethod $args -create \
112				    -mode 0644 $testfile $filename]
113				error_check_good dbopen [is_valid_db $db] TRUE
114				set pgsize [stat_field $db stat "Page size"]
115				if { $txnenv == 1 } {
116					set t [$env txn]
117					error_check_good \
118					    txn [is_valid_txn $t $env] TRUE
119					set txn "-txn $t"
120				}
121				for { set i 1 } { $i <= $nentries } { incr i } {
122					set key $i
123					set data DATA.$i
124					error_check_good \
125					    db_put [eval {$db put} $txn \
126					    $key [chop_data $method $data]] 0
127				}
128				if { $txnenv == 1 } {
129					error_check_good t_commit [$t commit] 0
130				}
131				error_check_good db_close [$db close] 0
132			}
133		}
134
135		# Copy database file A.  Reset LSNs on the copy. Then
136		# test that the copy is usable both in its native env
137		# and in a new env.
138
139		puts "\tTest$tnum.c: Copy database and reset its LSNs."
140		set testdir [get_home $env]
141		set newdir [get_home $newenv]
142
143		# Reset LSNs before copying.  We do a little dance here:
144		# first copy the file within the same directory, then reset
145		# the fileid on the copy, then reset the LSNs on the copy,
146		# and only then copy the new file to the new env.  Otherwise
147		# the LSNs would get reset on the original file.
148
149		file copy -force $testdir/$testfile $testdir/$newfile
150		error_check_good fileid_reset [$env id_reset $newfile] 0
151		error_check_good \
152		    lsn_reset [eval {$env lsn_reset} $resetargs {$newfile}] 0
153
154		file copy -force $testdir/$newfile $newdir/$testfile
155
156		# If we're using queue extents, we must copy the extents.
157		if { [is_queueext $method] } {
158			set cwd [pwd]
159			cd $testdir
160			set extents [glob __dbq.*]
161			foreach extent $extents {
162				set idx [string last . $extent]
163				incr idx
164				set suffix [string range $extent $idx end]
165				file copy -force $extent __dbq.$newfile.$suffix
166				file copy -force \
167				    $extent NEWDIR/__dbq.$testfile.$suffix
168			}
169			cd $cwd
170		}
171
172		# Get the LSNs and compare them.
173		set npages [getlsns $testdir/$testfile $pgsize orig_lsns]
174		set newpages [getlsns $testdir/$newfile $pgsize new_lsns]
175		set newdirpages [getlsns $newdir/$testfile $pgsize newdir_lsns]
176		error_check_good newpages_match $npages $newpages
177		error_check_good newdirpages_match $npages $newdirpages
178		for { set i 0 } { $i < $npages } { incr i } {
179			error_check_bad \
180			    newlsns_match $orig_lsns($i) $new_lsns($i)
181			error_check_bad \
182			    newdirlsns_match $orig_lsns($i) $newdir_lsns($i)
183		}
184
185		puts "\tTest$tnum.d: Verify directories with reset LSNs."
186	 	error_check_good \
187		    verify [verify_dir $testdir "\tTest$tnum.d: "] 0
188	 	error_check_good \
189		    verify [verify_dir $newdir "\tTest$tnum.e: "] 0
190
191		puts "\tTest$tnum.f: Open new db, check data, close db."
192		if { [is_queue $method] == 1 } {
193			set db [eval {berkdb_open} -env $newenv \
194			    $omethod $args -create -mode 0644 $testfile]
195			error_check_good dbopen [is_valid_db $db] TRUE
196			if { $txnenv == 1 } {
197				set t [$newenv txn]
198				error_check_good txn [is_valid_txn $t $newenv] TRUE
199				set txn "-txn $t"
200			}
201			for { set i 1 } { $i <= $nentries } { incr i } {
202				set key $i
203				set ret [eval {$db get} $txn $key]
204				error_check_good db_get \
205				    [lindex [lindex $ret 0] 1] \
206				    [pad_data $method DATA.$i]
207			}
208			if { $txnenv == 1 } {
209				error_check_good txn_commit [$t commit] 0
210			}
211			error_check_good db_close [$db close] 0
212		} else {
213			foreach filename $filenames {
214				set db [eval {berkdb_open} \
215				    -env $newenv $omethod $args \
216				    -create -mode 0644 $testfile $filename ]
217				error_check_good dbopen [is_valid_db $db] TRUE
218				if { $txnenv == 1 } {
219					set t [$newenv txn]
220					error_check_good \
221					    txn [is_valid_txn $t $newenv] TRUE
222					set txn "-txn $t"
223				}
224				for { set i 1 } { $i <= $nentries } { incr i } {
225					set key $i
226					set ret [eval {$db get} $txn $key]
227					error_check_good db_get \
228					    [lindex [lindex $ret 0] 1] \
229					    [pad_data $method DATA.$i]
230				}
231				if { $txnenv == 1 } {
232					error_check_good txn_commit [$t commit] 0
233				}
234				error_check_good db_close [$db close] 0
235			}
236		}
237		error_check_good newenv_close [$newenv close] 0
238		fileremove -f $newdir
239	}
240
241	set testdir $orig_tdir
242	# Close the parent env if this test created it.
243	if { $eindex == -1 } {
244		error_check_good env_close [$env close] 0
245	}
246}
247
248proc getlsns { dbfile pgsize lsns } {
249	upvar $lsns file_lsns
250	set fid [open $dbfile r]
251	fconfigure $fid -translation binary
252	set eof 0
253	set pg 0
254	while { $eof == 0 } {
255		set offset [expr $pg * $pgsize]
256		seek $fid $offset start
257		set file_lsns($pg) [read $fid 8]
258		set eof [eof $fid]
259		incr pg
260	}
261	close $fid
262	incr pg -1
263	return $pg
264}
265