1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2004-2009 Oracle.  All rights reserved.
4#
5# $Id$
6#
7# TEST	rep052
8# TEST	Test of replication with NOWAIT.
9# TEST
10# TEST	One master, one client.  After initializing
11# TEST	everything normally, close client and let the
12# TEST	master get ahead -- far enough that the master
13# TEST 	no longer has the client's last log file.
14# TEST	Reopen the client and turn on NOWAIT.
15# TEST	Process a few messages to get the client into
16# TEST	recovery mode, and verify that lockout occurs
17# TEST 	on a txn API call (txn_begin) and an env API call.
18# TEST	Process all the messages and verify that lockout
19# TEST 	is over.
20
21proc rep052 { method { niter 200 } { tnum "052" } args } {
22
23	source ./include.tcl
24	global databases_in_memory
25	global repfiles_in_memory
26
27	if { $is_windows9x_test == 1 } {
28		puts "Skipping replication test on Win 9x platform."
29		return
30	}
31
32	# Valid for all access methods.
33	if { $checking_valid_methods } {
34		return "ALL"
35	}
36
37	set args [convert_args $method $args]
38	set saved_args $args
39
40	# This test needs to set its own pagesize.
41	set pgindex [lsearch -exact $args "-pagesize"]
42	if { $pgindex != -1 } {
43		puts "Rep$tnum: skipping for specific pagesizes"
44		return
45	}
46
47	set logsets [create_logsets 2]
48	set saved_args $args
49
50	# Set up for on-disk or in-memory databases.
51	set msg "using on-disk databases"
52	if { $databases_in_memory } {
53		set msg "using named in-memory databases"
54		if { [is_queueext $method] } {
55			puts -nonewline "Skipping rep$tnum for method "
56			puts "$method with named in-memory databases."
57			return
58		}
59	}
60
61	set msg2 "and on-disk replication files"
62	if { $repfiles_in_memory } {
63		set msg2 "and in-memory replication files"
64	}
65
66	# Run the body of the test with and without recovery.  Skip
67	# recovery with in-memory logging - it doesn't make sense.
68	foreach r $test_recopts {
69		foreach l $logsets {
70			set logindex [lsearch -exact $l "in-memory"]
71			if { $r == "-recover" && $logindex != -1 } {
72				puts "Skipping rep$tnum for -recover\
73				    with in-memory logs."
74				continue
75			}
76			set envargs ""
77			set args $saved_args
78			puts "Rep$tnum ($method $envargs $r $args):\
79			    Test lockouts with REP_NOWAIT $msg $msg2."
80			puts "Rep$tnum: Master logs are [lindex $l 0]"
81			puts "Rep$tnum: Client logs are [lindex $l 1]"
82			rep052_sub $method $niter $tnum $envargs \
83			    $l $r $args
84		}
85	}
86}
87
88proc rep052_sub { method niter tnum envargs logset recargs largs } {
89	global testdir
90	global util_path
91	global databases_in_memory
92	global repfiles_in_memory
93	global rep_verbose
94	global verbose_type
95
96	set verbargs ""
97	if { $rep_verbose == 1 } {
98		set verbargs " -verbose {$verbose_type on} "
99	}
100
101	set repmemargs ""
102	if { $repfiles_in_memory } {
103		set repmemargs "-rep_inmem_files "
104	}
105
106	env_cleanup $testdir
107
108	replsetup $testdir/MSGQUEUEDIR
109
110	set masterdir $testdir/MASTERDIR
111	set clientdir $testdir/CLIENTDIR
112
113	file mkdir $masterdir
114	file mkdir $clientdir
115
116	# Log size is small so we quickly create more than one.
117	# The documentation says that the log file must be at least
118	# four times the size of the in-memory log buffer.
119	set pagesize 4096
120	append largs " -pagesize $pagesize "
121	set log_max [expr $pagesize * 8]
122
123	set m_logtype [lindex $logset 0]
124	set c_logtype [lindex $logset 1]
125
126	# In-memory logs cannot be used with -txn nosync.
127	set m_txnargs [adjust_txnargs $m_logtype]
128	set c_txnargs [adjust_txnargs $c_logtype]
129	set m_logargs [adjust_logargs $m_logtype]
130	set c_logargs [adjust_logargs $c_logtype]
131
132	# Open a master.
133	repladd 1
134	set ma_envcmd "berkdb_env_noerr -create $m_txnargs $verbargs \
135	    $repmemargs \
136	    $m_logargs -log_max $log_max $envargs -errpfx MASTER \
137	    -home $masterdir -rep_transport \[list 1 replsend\]"
138	set masterenv [eval $ma_envcmd $recargs -rep_master]
139	$masterenv rep_limit 0 0
140
141	# Open a client
142	repladd 2
143	set cl_envcmd "berkdb_env_noerr -create $c_txnargs $verbargs \
144	    $repmemargs \
145	    $c_logargs -log_max $log_max $envargs -errpfx CLIENT \
146	    -home $clientdir -rep_transport \[list 2 replsend\]"
147	set clientenv [eval $cl_envcmd $recargs -rep_client]
148	$clientenv rep_limit 0 0
149
150	# Bring the clients online by processing the startup messages.
151	set envlist "{$masterenv 1} {$clientenv 2}"
152	process_msgs $envlist
153
154	# Clobber replication's 30-second anti-archive timer, which will have
155	# been started by client sync-up internal init, so that we can do a
156	# log_archive in a moment.
157	#
158	$masterenv test force noarchive_timeout
159
160	# Run rep_test in the master (and update client).
161	puts "\tRep$tnum.a: Running rep_test in replicated env."
162	set start 0
163	eval rep_test $method $masterenv NULL $niter $start $start 0 $largs
164	incr start $niter
165	process_msgs $envlist
166
167	# Find out what exists on the client before closing.  We'll need
168	# to loop until the first master log file > last client log file.
169	set last_client_log [get_logfile $clientenv last]
170
171	puts "\tRep$tnum.b: Close client."
172	error_check_good client_close [$clientenv close] 0
173
174	# Find out what exists on the client.  We need to loop until
175	# the first master log file > last client log file.
176
177	set stop 0
178	while { $stop == 0 } {
179		# Run rep_test in the master (don't update client).
180		puts "\tRep$tnum.c: Running rep_test in replicated env."
181		eval rep_test \
182		    $method $masterenv NULL $niter $start $start 0 $largs
183		incr start $niter
184		replclear 2
185
186		puts "\tRep$tnum.d: Run db_archive on master."
187		if { $m_logtype != "in-memory" } {
188			set res \
189			    [eval exec $util_path/db_archive -d -h $masterdir]
190		}
191		# Make sure we have a gap between the last client log and
192		# the first master log.  This is easy with on-disk logs, since
193		# we archive, but will take longer with in-memory logging.
194		set first_master_log [get_logfile $masterenv first]
195		if { $first_master_log > $last_client_log } {
196			set stop 1
197		}
198	}
199
200	puts "\tRep$tnum.e: Reopen client."
201	env_cleanup $clientdir
202	set clientenv [eval $cl_envcmd $recargs -rep_client]
203	error_check_good client_env [is_valid_env $clientenv] TRUE
204	$clientenv rep_limit 0 0
205	set envlist "{$masterenv 1} {$clientenv 2}"
206
207	# Turn on nowait.
208	$clientenv rep_config {nowait on}
209
210	# Process messages a few times, just enough to get client
211	# into lockout/recovery mode, but not enough to complete recovery.
212	set iter 3
213	for { set i 0 } { $i < $iter } { incr i } {
214		set nproced [proc_msgs_once $envlist NONE err]
215	}
216
217	puts "\tRep$tnum.f: Verify we are locked out of txn API calls."
218	if { [catch { set txn [$clientenv txn] } res] } {
219		error_check_good txn_lockout [is_substr $res "DB_REP_LOCKOUT"] 1
220	} else {
221		error "FAIL:[timestamp] Not locked out of txn API calls."
222	}
223
224	puts "\tRep$tnum.g: Verify we are locked out of env API calls."
225	if { [catch { set stat [$clientenv lock_stat] } res] } {
226		error_check_good env_lockout [is_substr $res "DB_REP_LOCKOUT"] 1
227	} else {
228		error "FAIL:[timestamp] Not locked out of env API calls."
229	}
230
231	# Now catch up and make sure we're not locked out anymore.
232	process_msgs $envlist
233
234	puts "\tRep$tnum.h: No longer locked out of txn API calls."
235	if { [catch { set txn [$clientenv txn] } res] } {
236		puts "FAIL: unable to start txn: $res"
237	} else {
238		error_check_good txn_no_lockout [$txn commit] 0
239	}
240
241	puts "\tRep$tnum.i: No longer locked out of env API calls."
242	if { [catch { set stat [$clientenv rep_stat] } res] } {
243		puts "FAIL: unable to make env call: $res"
244	}
245
246	puts "\tRep$tnum.h: Verify logs and databases"
247	rep_verify $masterdir $masterenv $clientdir $clientenv 1 1 1
248
249	error_check_good masterenv_close [$masterenv close] 0
250	error_check_good clientenv_close [$clientenv close] 0
251	replclose $testdir/MSGQUEUEDIR
252}
253