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