1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2005-2009 Oracle.  All rights reserved.
4#
5# $Id$
6#
7# TEST	test117
8# TEST	Test database compaction with requested fill percent.
9# TEST
10# TEST	Populate a database.  Remove a high proportion of entries.
11# TEST	Dump and save contents.  Compact the database, requesting
12# TEST	fill percentages starting at 10% and working our way up to
13# TEST	100.  On each cycle, make sure we still have the same contents.
14# TEST
15# TEST	Unlike the other compaction tests, this one does not
16# TEST	use -freespace.
17
18proc test117 { method {nentries 10000} {tnum "117"} args } {
19	source ./include.tcl
20
21	# Compaction is an option for btree and recno databases only.
22	if { [is_hash $method] == 1 || [is_queue $method] == 1 } {
23		puts "Skipping test$tnum for method $method."
24		return
25	}
26
27	set args [convert_args $method $args]
28	set omethod [convert_method $method]
29	if  { [is_partition_callback $args] == 1 } {
30		set nodump 1
31	} else {
32		set nodump 0
33	}
34
35	# If we are using an env, then testfile should just be the db name.
36	# Otherwise it is the test directory and the name.
37	set txnenv 0
38	set eindex [lsearch -exact $args "-env"]
39	if { $eindex == -1 } {
40		set basename $testdir/test$tnum
41		set env NULL
42	} else {
43		set basename test$tnum
44		incr eindex
45		set env [lindex $args $eindex]
46		set rpcenv [is_rpcenv $env]
47		if { $rpcenv == 1 } {
48			puts "Test$tnum: skipping for RPC"
49			return
50		}
51		set txnenv [is_txnenv $env]
52		if { $txnenv == 1 } {
53			append args " -auto_commit "
54		}
55		set testdir [get_home $env]
56	}
57	puts "Test$tnum: ($method $args) Database compaction and fillpercent."
58	set t1 $testdir/t1
59	set t2 $testdir/t2
60	set splitopts { "" "-revsplitoff" }
61	set txn ""
62
63	if { [is_record_based $method] == 1 } {
64		set checkfunc test001_recno.check
65	} else {
66		set checkfunc test001.check
67	}
68
69	foreach splitopt $splitopts {
70		set testfile $basename.db
71		if { $splitopt == "-revsplitoff" } {
72			set testfile $basename.rev.db
73	 		if { [is_record_based $method] == 1 } {
74				puts "Skipping\
75				    -revsplitoff option for method $method."
76				continue
77			}
78		}
79		set did [open $dict]
80		if { $env != "NULL" } {
81			set testdir [get_home $env]
82		}
83		cleanup $testdir $env
84
85		puts "\tTest$tnum.a: Create and populate database ($splitopt)."
86		set db [eval {berkdb_open -create \
87		    -mode 0644} $splitopt $args $omethod $testfile]
88		error_check_good dbopen [is_valid_db $db] TRUE
89
90		set count 0
91		if { $txnenv == 1 } {
92			set t [$env txn]
93			error_check_good txn [is_valid_txn $t $env] TRUE
94			set txn "-txn $t"
95		}
96		while { [gets $did str] != -1 && $count < $nentries } {
97			global kvals
98
99			if { [is_record_based $method] == 1 } {
100				set key [expr $count + 1]
101				set kvals($key) [pad_data $method $str]
102			} else {
103				set key $str
104				set str [reverse $str]
105			}
106
107			set ret [eval \
108			    {$db put} $txn {$key [chop_data $method $str]}]
109			error_check_good put $ret 0
110			incr count
111
112		}
113		if { $txnenv == 1 } {
114			error_check_good txn_commit [$t commit] 0
115		}
116		close $did
117		error_check_good db_sync [$db sync] 0
118
119		if { $env != "NULL" } {
120			set testdir [get_home $env]
121			set filename $testdir/$testfile
122		} else {
123			set filename $testfile
124		}
125		set size1 [file size $filename]
126		set free1 [stat_field $db stat "Pages on freelist"]
127
128		puts "\tTest$tnum.b: Delete most entries from database."
129		set did [open $dict]
130		set count [expr $nentries - 1]
131		set n 17
132
133		# Leave every nth item.  Since rrecno renumbers, we
134		# delete starting at nentries and working down to 0.
135		if { $txnenv == 1 } {
136			set t [$env txn]
137			error_check_good txn [is_valid_txn $t $env] TRUE
138			set txn "-txn $t"
139		}
140		while { [gets $did str] != -1 && $count > 0 } {
141			if { [is_record_based $method] == 1 } {
142				set key [expr $count + 1]
143			} else {
144				set key $str
145			}
146
147			if { [expr $count % $n] != 0 } {
148				set ret [eval {$db del} $txn {$key}]
149				error_check_good del $ret 0
150			}
151			incr count -1
152		}
153		if { $txnenv == 1 } {
154			error_check_good t_commit [$t commit] 0
155		}
156		error_check_good db_sync [$db sync] 0
157
158		puts "\tTest$tnum.c: Do a dump_file on contents."
159		if { $txnenv == 1 } {
160			set t [$env txn]
161			error_check_good txn [is_valid_txn $t $env] TRUE
162			set txn "-txn $t"
163		}
164		dump_file $db $txn $t1
165		if { $txnenv == 1 } {
166			error_check_good txn_commit [$t commit] 0
167		}
168
169		# Start by compacting pages filled less than 10% and
170		# work up to 100%.
171		for { set fillpercent 10 } { $fillpercent <= 100 }\
172		    { incr fillpercent 10 } {
173
174			puts "\tTest$tnum.d: Compact and verify database\
175			    with fillpercent $fillpercent."
176			set ret [$db compact -fillpercent $fillpercent]
177			error_check_good db_sync [$db sync] 0
178			set size2 [file size $filename]
179			error_check_good verify_dir \
180			     [verify_dir $testdir "" 0 0 $nodump] 0
181			set free2 [stat_field $db stat "Pages on freelist"]
182
183			# The number of free pages should never decline.
184			error_check_good pages_freed [expr $free2 >= $free1] 1
185			error_check_good file_size [expr $size2 <= $size1] 1
186
187			puts "\tTest$tnum.e:\
188			    Contents are the same after compaction."
189			if { $txnenv == 1 } {
190				set t [$env txn]
191				error_check_good txn [is_valid_txn $t $env] TRUE
192				set txn "-txn $t"
193			}
194			dump_file $db $txn $t2
195			if { $txnenv == 1 } {
196				error_check_good txn_commit [$t commit] 0
197			}
198			error_check_good filecmp [filecmp $t1 $t2] 0
199			set free1 $free2
200			set size1 $size2
201		}
202		error_check_good db_close [$db close] 0
203		close $did
204	}
205}
206