1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2001,2008 Oracle.  All rights reserved.
4#
5# $Id: rep051.tcl,v 12.18 2008/01/08 20:58:53 bostic Exp $
6#
7# TEST	rep051
8# TEST	Test of compaction with replication.
9# TEST
10# TEST	Run rep_test in a replicated master environment.
11# TEST	Delete a large number of entries and compact with -freespace.
12# TEST	Propagate the changes to the client and make sure client and
13# TEST	master match.
14
15proc rep051 { method { niter 5000 } { tnum "051" } args } {
16	source ./include.tcl
17	if { $is_windows9x_test == 1 } {
18		puts "Skipping replication test on Win9x platform."
19		return
20	}
21
22	# Compaction is an option for btree and recno databases only.
23	if { $checking_valid_methods } {
24		set test_methods {}
25		foreach method $valid_methods {
26			if { [is_btree $method] == 1 || \
27			    [is_recno $method] == 1 } {
28				lappend test_methods $method
29			}
30		}
31		return $test_methods
32	}
33	if { [is_hash $method] == 1 || [is_queue $method] == 1 } {
34		puts "Skipping test$tnum for method $method."
35		return
36	}
37
38	# Run tests with and without recovery.  If we're doing testing
39	# of in-memory logging, skip the combination of recovery
40	# and in-memory logging -- it doesn't make sense.
41	set logsets [create_logsets 2]
42	set saved_args $args
43
44	foreach recopt $test_recopts {
45		foreach l $logsets {
46			set logindex [lsearch -exact $l "in-memory"]
47			if { $recopt == "-recover" && $logindex != -1 } {
48				puts "Skipping test \
49				    with -recover for in-memory logs."
50				continue
51			}
52			set envargs ""
53			set args $saved_args
54			puts "Rep$tnum:\
55			    Replication with compaction ($method $recopt)."
56			puts "Rep$tnum: Master logs are [lindex $l 0]"
57			puts "Rep$tnum: Client logs are [lindex $l 1]"
58			rep051_sub $method \
59			    $niter $tnum $envargs $l $recopt $args
60		}
61	}
62}
63
64proc rep051_sub { method niter tnum envargs logset recargs largs } {
65	source ./include.tcl
66	global rep_verbose
67	global verbose_type
68
69	set verbargs ""
70	if { $rep_verbose == 1 } {
71		set verbargs " -verbose {$verbose_type on} "
72	}
73
74	env_cleanup $testdir
75
76	replsetup $testdir/MSGQUEUEDIR
77
78	set masterdir $testdir/MASTERDIR
79	set clientdir $testdir/CLIENTDIR
80
81	file mkdir $masterdir
82	file mkdir $clientdir
83
84	set m_logtype [lindex $logset 0]
85	set c_logtype [lindex $logset 1]
86
87	set verify_subset \
88	    [expr { $m_logtype == "in-memory" || $c_logtype == "in-memory" }]
89
90	# In-memory logs require a large log buffer, and cannot
91	# be used with -txn nosync.  Adjust the args for master
92	# and client.
93	# This test has a long transaction, allocate a larger log
94	# buffer for in-memory test.
95	set m_logargs [adjust_logargs $m_logtype [expr 2 * [expr 1024 * 1024]]]
96	set c_logargs [adjust_logargs $c_logtype [expr 2 * [expr 1024 * 1024]]]
97	set m_txnargs [adjust_txnargs $m_logtype]
98	set c_txnargs [adjust_txnargs $c_logtype]
99
100	# Open a master.
101	repladd 1
102	set env_cmd(M) "berkdb_env_noerr -create $verbargs \
103	    -log_max 1000000 $envargs $m_logargs $recargs \
104	    -home $masterdir -errpfx MASTER $m_txnargs -rep_master \
105	    -rep_transport \[list 1 replsend\]"
106	set masterenv [eval $env_cmd(M)]
107
108	# Open a client
109	repladd 2
110	set env_cmd(C) "berkdb_env_noerr -create $verbargs \
111	    -log_max 1000000 $envargs $c_logargs $recargs \
112	    -home $clientdir -errpfx CLIENT $c_txnargs -rep_client \
113	    -rep_transport \[list 2 replsend\]"
114	set clientenv [eval $env_cmd(C)]
115
116	# Bring the client online by processing the startup messages.
117	set envlist "{$masterenv 1} {$clientenv 2}"
118	process_msgs $envlist
119
120	# Explicitly create the db handle so we can do deletes,
121	# and also to make the page size small.
122	set testfile "test.db"
123	set omethod [convert_method $method]
124	set db [eval {berkdb_open_noerr -env $masterenv -auto_commit\
125	    -pagesize 512 -create -mode 0644} $largs $omethod $testfile]
126 	error_check_good db_open [is_valid_db $db] TRUE
127
128	# Run rep_test in the master and update client.
129	puts "\tRep$tnum.a:\
130	    Running rep_test in replicated env ($envargs $recargs)."
131	eval rep_test $method $masterenv $db $niter 0 0 0 0 $largs
132	process_msgs $envlist
133
134	# Verify that contents match.
135	puts "\tRep$tnum.b: Verifying client database contents."
136	rep_verify $masterdir $masterenv $clientdir $clientenv $verify_subset
137
138	# Delete most entries.  Since some of our methods renumber,
139	# delete starting at $niter and working down to 0.
140	puts "\tRep$tnum.c: Remove most entries, by cursor."
141	set count [expr $niter - 1]
142	set n 20
143	set t [$masterenv txn]
144	error_check_good txn [is_valid_txn $t $masterenv] TRUE
145	set txn "-txn $t"
146
147	set dbc [eval {$db cursor} $txn]
148
149	# Leave every nth item.
150	set dbt [$dbc get -first]
151	while { $count > 0 } {
152		if { [expr $count % $n] != 0 } {
153			error_check_good dbc_del [$dbc del] 0
154		}
155		set dbt [$dbc get -next]
156		incr count -1
157	}
158
159	error_check_good dbc_close [$dbc close] 0
160	error_check_good t_commit [$t commit] 0
161
162	# Open read-only handle on client, so we can call $db stat.
163	set client_db \
164	    [eval {berkdb_open_noerr} -env $clientenv -rdonly $testfile]
165 	error_check_good client_open [is_valid_db $client_db] TRUE
166
167	# Check database size on both client and master.
168	process_msgs $envlist
169	set master_pages_before [stat_field $db stat "Page count"]
170	set client_pages_before [stat_field $client_db stat "Page count"]
171	error_check_good \
172	    pages_match_before $client_pages_before $master_pages_before
173
174	# Compact database.
175	puts "\tRep$tnum.d: Compact database."
176	set t [$masterenv txn]
177	error_check_good txn [is_valid_txn $t $masterenv] TRUE
178	set txn "-txn $t"
179
180	set ret [eval {$db compact} $txn {-freespace}]
181
182	error_check_good t_commit [$t commit] 0
183	error_check_good db_sync [$db sync] 0
184
185	# There will be fewer pages in use after the compact -freespace call.
186	set master_pages_after [stat_field $db stat "Page count"]
187	set page_reduction [expr $master_pages_before - $master_pages_after]
188	error_check_good page_reduction [expr $page_reduction > 0] 1
189
190	# Process messages so the client sees the reduction in pages used.
191	process_msgs $envlist
192
193	set client_pages_after [stat_field $client_db stat "Page count"]
194	error_check_good \
195	    pages_match_after $client_pages_after $master_pages_after
196
197	# Close client handle.
198	error_check_good client_handle [$client_db close] 0
199
200	# Reverify.
201	puts "\tRep$tnum.b: Verifying client database contents."
202	rep_verify $masterdir $masterenv $clientdir $clientenv $verify_subset
203
204	# Clean up.
205	error_check_good db_close [$db close] 0
206	error_check_good masterenv_close [$masterenv close] 0
207	error_check_good clientenv_close [$clientenv close] 0
208	replclose $testdir/MSGQUEUEDIR
209}
210