1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2006,2008 Oracle.  All rights reserved.
4#
5# $Id: rep062.tcl,v 1.15 2008/01/08 20:58:53 bostic Exp $
6#
7# TEST	rep062
8# TEST	Test of internal initialization where client has a different
9# TEST  kind of database than the master.
10# TEST
11# TEST	Create a master of one type, and let the client catch up.
12# TEST	Close the client.
13# TEST	Remove the database on the master, and create a new
14# TEST	database of the same name but a different type.
15# TEST	Run the master ahead far enough that internal initialization
16# TEST	will be required on the reopen of the client.
17# TEST	Reopen the client and verify.
18
19proc rep062 { method {tnum "062"} args } {
20
21	source ./include.tcl
22	if { $is_windows9x_test == 1 } {
23		puts "Skipping replication test on Win 9x platform."
24		return
25	}
26
27	# This test uses different access methods internally.
28	# Called from outside, accept only btree.
29	if { $checking_valid_methods } {
30		set test_methods { btree }
31		return $test_methods
32	}
33	if { [is_btree $method] != 1 } {
34		puts "Skipping rep$tnum for method $method."
35		return
36	}
37
38	# This test needs to set its own pagesize.
39	set pgindex [lsearch -exact $args "-pagesize"]
40	if { $pgindex != -1 } {
41		puts "Rep$tnum: skipping for specific pagesizes"
42		return
43	}
44
45	set logsets [create_logsets 2]
46
47	# Run the body of the test with and without recovery,
48	# and with and without cleaning.
49	foreach r $test_recopts {
50		foreach l $logsets {
51			set logindex [lsearch -exact $l "in-memory"]
52			if { $r == "-recover" && $logindex != -1 } {
53				puts "Skipping rep$tnum for -recover\
54				    with in-memory logs."
55				continue
56			}
57			puts "Rep$tnum ($method $r):\
58			    Internal initialization with change in\
59			    access method of database."
60			puts "Rep$tnum: Master logs are [lindex $l 0]"
61			puts "Rep$tnum: Client logs are [lindex $l 1]"
62			rep062_sub $method $tnum $l $r $args
63		}
64	}
65}
66
67proc rep062_sub { method tnum logset recargs largs } {
68	global testdir
69	global util_path
70	global passwd
71	global has_crypto
72	global encrypt
73	global rep_verbose
74	global verbose_type
75
76	set verbargs ""
77	if { $rep_verbose == 1 } {
78		set verbargs " -verbose {$verbose_type on} "
79	}
80
81	set masterdir $testdir/MASTERDIR
82	set clientdir $testdir/CLIENTDIR
83
84	# Log size is small so we quickly create more than one.
85	# The documentation says that the log file must be at least
86	# four times the size of the in-memory log buffer.
87	set maxpg 16384
88	set log_max [expr $maxpg * 8]
89	set cache [expr $maxpg * 32]
90
91	set m_logtype [lindex $logset 0]
92	set c_logtype [lindex $logset 1]
93
94	# In-memory logs cannot be used with -txn nosync.
95	set m_logargs [adjust_logargs $m_logtype]
96	set c_logargs [adjust_logargs $c_logtype]
97	set m_txnargs [adjust_txnargs $m_logtype]
98	set c_txnargs [adjust_txnargs $c_logtype]
99
100	# Set up pairs of databases to test.  The first element is whether
101	# to open an encrypted env, the second is the original database
102	# method and flags, the third is the replacement database and flags.
103	set pairlist {
104	    { 0 {btree ""} {hash ""} }
105	    { 0 {queueext "-pagesize 2048"} {queue ""} }
106	    { 0 {queueext ""} {btree ""} }
107	    { 0 {queue ""} {recno ""} }
108	    { 0 {hash ""} {queue ""} }
109	    { 0 {recno ""} {btree ""} }
110	    { 0 {hash ""} {queueext "-pagesize 16384"} }
111	    { 0 {queueext "-pagesize 2048"} {queueext "-pagesize 16384"} }
112	    { 0 {queueext "-pagesize 16384"} {queueext "-pagesize 2048"} }
113	    { 0 {queue ""} {queueext "-pagesize 16384"} }
114	    { 1 {btree ""} {btree "-encrypt"} }
115	    { 1 {btree "-encrypt"} {btree ""} }
116	    { 1 {queue ""} {queue "-encrypt"} }
117	    { 1 {queue "-encrypt"} {queue ""} }
118	}
119
120	foreach p $pairlist {
121		env_cleanup $testdir
122		# Extract values from the list.
123		set encryptenv [lindex [lindex $p 0] 0]
124		set encryptmsg "clear"
125		if { $has_crypto == 0 && $encryptenv == 1 } {
126			continue
127		}
128		if { $encryptenv == 1 } {
129			set encryptmsg "encrypted"
130		}
131		replsetup $testdir/MSGQUEUEDIR
132
133		file mkdir $masterdir
134		file mkdir $clientdir
135
136		set method1 [lindex [lindex $p 1] 0]
137		set method2 [lindex [lindex $p 2] 0]
138		set flags1 [lindex [lindex $p 1] 1]
139		set flags2 [lindex [lindex $p 2] 1]
140
141		puts "Rep$tnum: Testing with $encryptmsg env."
142		puts -nonewline "Rep$tnum: Replace [lindex $p 1] "
143		puts "database with [lindex $p 2] database."
144
145		# Set up flags for encryption if necessary.
146		set envflags ""
147		set enc ""
148		if { $encryptenv == 1 } {
149			set envflags "-encryptaes $passwd"
150			set enc " -P $passwd"
151		}
152
153		# Derive args for specified methods.
154		set args1 [convert_args $method1 ""]
155		set args2 [convert_args $method2 ""]
156
157		# Open a master.
158		repladd 1
159		set ma_envcmd "berkdb_env_noerr -create $m_txnargs \
160		    $m_logargs -log_max $log_max $verbargs -errpfx MASTER \
161		    -cachesize { 0 $cache 1 } $envflags \
162		    -home $masterdir -rep_transport \[list 1 replsend\]"
163		set masterenv [eval $ma_envcmd $recargs -rep_master]
164
165		# Open a client.
166		repladd 2
167		set cl_envcmd "berkdb_env_noerr -create $c_txnargs \
168		    $c_logargs -log_max $log_max $verbargs -errpfx CLIENT \
169		    -cachesize { 0 $cache 1 } $envflags \
170		    -home $clientdir -rep_transport \[list 2 replsend\]"
171		set clientenv [eval $cl_envcmd $recargs -rep_client]
172
173		# Bring the client online by processing the startup messages.
174		set envlist "{$masterenv 1} {$clientenv 2}"
175		process_msgs $envlist
176
177		# Clobber replication's 30-second anti-archive timer, which will have
178		# been started by client sync-up internal init, so that we can do a
179		# log_archive in a moment.
180		#
181		$masterenv test force noarchive_timeout
182
183		# Open two databases on the master - one to test different
184		# methods, one to advance the log, forcing internal
185		# initialization.
186
187		puts "\tRep$tnum.a: Open test database (it will change methods)."
188		set testfile "test.db"
189		set omethod [convert_method $method1]
190		set db1 [eval {berkdb_open} -env $masterenv -auto_commit \
191		    -create $omethod $flags1 $args1 -mode 0644 $testfile]
192		error_check_good db1open [is_valid_db $db1] TRUE
193
194		puts "\tRep$tnum.b: Open log-advance database."
195		set testfile2 "test2.db"
196		set db2 [eval {berkdb_open} -env $masterenv -auto_commit \
197		    -create $omethod $args1 -mode 0644 $flags1 $testfile2]
198		error_check_good db2open [is_valid_db $db2] TRUE
199
200		puts "\tRep$tnum.c: Add a few records to test db."
201		set nentries 10
202		set start 0
203		eval rep_test $method1 \
204		    $masterenv $db1 $nentries $start $start 0 0 $args1
205		incr start $nentries
206		process_msgs $envlist
207
208		puts "\tRep$tnum.d: Close client."
209
210		# First save the log number of the latest client log.
211		set last_client_log [get_logfile $clientenv last]
212		error_check_good client_close [$clientenv close] 0
213
214		# Remove the database on the master, create new database
215		# of different type.
216		puts "\tRep$tnum.e: Remove test database."
217		error_check_good db1_close [$db1 close] 0
218		error_check_good db1_remove [$masterenv dbremove $testfile] 0
219
220		puts "\tRep$tnum.f: \
221		    Create new test database; same name, different method."
222		set omethod [convert_method $method2]
223		set db1 [eval {berkdb_open} -env $masterenv -auto_commit \
224		    -create $omethod $args2 -mode 0644 $flags2 $testfile]
225		error_check_good db1open [is_valid_db $db1] TRUE
226
227		# Run rep_test in the master enough to require internal
228		# initialization upon client reopen.  Use the extra db.
229		set stop 0
230		set niter 100
231		while { $stop == 0 } {
232			# Run rep_test in the master (don't update client).
233			puts "\tRep$tnum.g: \
234			    Run rep_test until internal init is required."
235		 	eval rep_test $method1 $masterenv \
236			    $db2 $niter $start $start 0 0 $largs
237			incr start $niter
238			replclear 2
239
240			puts "\tRep$tnum.h: Run db_archive on master."
241			if { $m_logtype != "in-memory"} {
242				set res [eval exec \
243				    $util_path/db_archive $enc -d -h $masterdir]
244				set res [eval exec \
245				    $util_path/db_archive $enc -l -h $masterdir]
246			}
247			set first_master_log [get_logfile $masterenv first]
248			if { $first_master_log > $last_client_log } {
249				set stop 1
250			}
251		}
252
253		puts "\tRep$tnum.i: Reopen client."
254		set clientenv [eval $cl_envcmd $recargs -rep_client]
255		error_check_good client_env [is_valid_env $clientenv] TRUE
256
257		set envlist "{$masterenv 1} {$clientenv 2}"
258		process_msgs $envlist 0 NONE err
259
260		puts "\tRep$tnum.j: Add a few records to cause initialization."
261		set entries 20
262		eval rep_test $method2 \
263		    $masterenv $db1 $entries $start $start 0 0 $largs
264		incr start $entries
265		process_msgs $envlist 0 NONE err
266
267		puts "\tRep$tnum.k: Verify logs and databases"
268		# Make sure encryption value is correct.
269		if { $encryptenv == 1 } {
270			set encrypt 1
271		}
272		rep_verify $masterdir $masterenv $clientdir $clientenv 1
273
274		check_log_location $masterenv
275		check_log_location $clientenv
276
277		error_check_good db1_close [$db1 close] 0
278		error_check_good db2_close [$db2 close] 0
279		error_check_good masterenv_close [$masterenv close] 0
280		error_check_good clientenv_close [$clientenv close] 0
281		replclose $testdir/MSGQUEUEDIR
282	}
283}
284
285