1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2003-2009 Oracle.  All rights reserved.
4#
5# $Id$
6#
7# TEST	rep018
8# TEST	Replication with dbremove.
9# TEST
10# TEST	Verify that the attempt to remove a database file
11# TEST	on the master hangs while another process holds a
12# TEST	handle on the client.
13# TEST
14proc rep018 { method { niter 10 } { tnum "018" } args } {
15
16	source ./include.tcl
17	global repfiles_in_memory
18
19	if { $is_windows9x_test == 1 } {
20		puts "Skipping replication test on Win 9x platform."
21		return
22	}
23
24	# Run for all access methods.
25	if { $checking_valid_methods } {
26		return "ALL"
27	}
28
29	set args [convert_args $method $args]
30	set logsets [create_logsets 2]
31
32	set msg2 "and on-disk replication files"
33	if { $repfiles_in_memory } {
34		set msg2 "and in-memory replication files"
35	}
36
37	# Run the body of the test with and without recovery.
38	foreach r $test_recopts {
39		foreach l $logsets {
40			set logindex [lsearch -exact $l "in-memory"]
41			if { $r == "-recover" && $logindex != -1 } {
42				puts "Rep$tnum: Skipping\
43				    for in-memory logs with -recover."
44				continue
45			}
46			puts "Rep$tnum ($method $r): Replication with dbremove $msg2."
47			puts "Rep$tnum: Master logs are [lindex $l 0]"
48			puts "Rep$tnum: Client logs are [lindex $l 1]"
49			rep018_sub $method $niter $tnum $l $r $args
50		}
51	}
52}
53
54proc rep018_sub { method niter tnum logset recargs largs } {
55	source ./include.tcl
56	global repfiles_in_memory
57	global rep_verbose
58	global verbose_type
59
60	set verbargs ""
61	if { $rep_verbose == 1 } {
62		set verbargs " -verbose {$verbose_type on} "
63	}
64
65	set repmemargs ""
66	if { $repfiles_in_memory } {
67		set repmemargs "-rep_inmem_files "
68	}
69
70	env_cleanup $testdir
71	set omethod [convert_method $method]
72
73	replsetup $testdir/MSGQUEUEDIR
74
75	set masterdir $testdir/MASTERDIR
76	set clientdir $testdir/CLIENTDIR
77
78	file mkdir $masterdir
79	file mkdir $clientdir
80	set m_logtype [lindex $logset 0]
81	set c_logtype [lindex $logset 1]
82
83	# In-memory logs require a large log buffer, and cannot
84	# be used with -txn nosync.
85	set m_logargs [adjust_logargs $m_logtype]
86	set c_logargs [adjust_logargs $c_logtype]
87	set m_txnargs [adjust_txnargs $m_logtype]
88	set c_txnargs [adjust_txnargs $c_logtype]
89
90	puts "\tRep$tnum.a: Create master and client, bring online."
91	# Open a master.
92	repladd 1
93	set env_cmd(M) "berkdb_env_noerr -create \
94	    -log_max 1000000 -home $masterdir $verbargs $repmemargs \
95	    $m_txnargs $m_logargs -rep_master -errpfx MASTER \
96	    -rep_transport \[list 1 replsend\]"
97	set masterenv [eval $env_cmd(M) $recargs]
98
99	# Open a client
100	repladd 2
101	set env_cmd(C) "berkdb_env_noerr -create -home $clientdir $repmemargs \
102	    $c_txnargs $c_logargs -rep_client $verbargs -errpfx CLIENT \
103	    -rep_transport \[list 2 replsend\]"
104	set clientenv [eval $env_cmd(C) $recargs]
105
106	# Bring the client online.
107	process_msgs "{$masterenv 1} {$clientenv 2}"
108
109	# Clobber replication's 30-second anti-archive timer, which will have
110	# been started by client sync-up internal init, so that we can do a
111	# db_remove in a moment.
112	#
113	$masterenv test force noarchive_timeout
114
115	puts "\tRep$tnum.b: Open database on master, propagate to client."
116	set dbname rep$tnum.db
117	set db [eval "berkdb_open_noerr -create $omethod -auto_commit \
118	    -env $masterenv $largs $dbname"]
119	set t [$masterenv txn]
120	for { set i 1 } { $i <= $niter } { incr i } {
121		error_check_good db_put \
122		    [eval $db put -txn $t $i [chop_data $method data$i]] 0
123	}
124	error_check_good txn_commit [$t commit] 0
125	process_msgs "{$masterenv 1} {$clientenv 2}"
126
127	puts "\tRep$tnum.c: Spawn a child tclsh to do client work."
128	set pid [exec $tclsh_path $test_path/wrap.tcl \
129	    rep018script.tcl $testdir/rep018script.log $clientdir \
130	    $niter $dbname $method $rep_verbose $verbose_type &]
131
132	puts "\tRep$tnum.d: Close and remove database on master."
133	error_check_good close_master_db [$db close] 0
134
135	# Remove database in master env.  First make sure the child
136	# tclsh is done reading the data.
137	while { 1 } {
138		if { [file exists $testdir/marker.db] == 0  } {
139			tclsleep 1
140		} else {
141			set markerenv [berkdb_env -home $testdir -txn]
142			error_check_good markerenv_open \
143			    [is_valid_env $markerenv] TRUE
144			set marker [berkdb_open -unknown -env $markerenv \
145			    -auto_commit marker.db]
146			while { [llength [$marker get CHILDREADY]] == 0 } {
147				tclsleep 1
148			}
149			break
150		}
151	}
152	error_check_good db_remove [$masterenv dbremove -auto_commit $dbname] 0
153
154	puts "\tRep$tnum.e: Create new database on master with the same name."
155	set db [eval "berkdb_open_noerr -create $omethod -auto_commit \
156	    -env $masterenv $largs $dbname"]
157	error_check_good new_db_open [is_valid_db $db] TRUE
158
159	puts "\tRep$tnum.f: Propagate changes to client.  Process should hang."
160	error_check_good timestamp_remove \
161	    [$marker put PARENTREMOVE [timestamp -r]] 0
162	process_msgs "{$masterenv 1} {$clientenv 2}"
163	error_check_good timestamp_done \
164	    [$marker put PARENTDONE [timestamp -r]] 0
165
166	watch_procs $pid 5
167
168	puts "\tRep$tnum.g: Check for failure."
169	# Check marker file for correct timestamp ordering.
170	set ret [$marker get CHILDDONE]
171	set childdone [lindex [lindex [lindex $ret 0] 1] 0]
172	set ret [$marker get PARENTDONE]
173	set parentdone [lindex [lindex [lindex $ret 0] 1] 0]
174	if { [expr $childdone - $parentdone] > 0 } {
175		puts "\tFAIL: parent must complete after child"
176	}
177
178	# Clean up.
179	error_check_good marker_db_close [$marker close] 0
180	error_check_good market_env_close [$markerenv close] 0
181	error_check_good masterdb_close [$db close] 0
182	error_check_good masterenv_close [$masterenv close] 0
183	error_check_good clientenv_close [$clientenv close] 0
184
185	replclose $testdir/MSGQUEUEDIR
186
187	# Check log file for failures.
188	set errstrings [eval findfail $testdir/rep018script.log]
189	foreach str $errstrings {
190		puts "FAIL: error message in rep018 log file: $str"
191	}
192}
193
194