summaryrefslogtreecommitdiff
path: root/db/test/rep018.tcl
blob: 1f58552774649fbc8d127616232528dedf2b393c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2003,2007 Oracle.  All rights reserved.
#
# $Id: rep018.tcl,v 12.14 2007/05/17 18:17:21 bostic Exp $
#
# TEST	rep018
# TEST	Replication with dbremove.
# TEST
# TEST	Verify that the attempt to remove a database file
# TEST	on the master hangs while another process holds a
# TEST	handle on the client.
# TEST
proc rep018 { method { niter 10 } { tnum "018" } args } {

	source ./include.tcl
	if { $is_windows9x_test == 1 } {
		puts "Skipping replication test on Win 9x platform."
		return
	}

	# Run for all access methods.
	if { $checking_valid_methods } {
		return "ALL"
	}

	set args [convert_args $method $args]
	set logsets [create_logsets 2]

	# Run the body of the test with and without recovery.
	foreach r $test_recopts {
		foreach l $logsets {
			set logindex [lsearch -exact $l "in-memory"]
			if { $r == "-recover" && $logindex != -1 } {
				puts "Rep$tnum: Skipping\
				    for in-memory logs with -recover."
				continue
			}
			puts "Rep$tnum ($method $r): Replication with dbremove."
			puts "Rep$tnum: Master logs are [lindex $l 0]"
			puts "Rep$tnum: Client logs are [lindex $l 1]"
			rep018_sub $method $niter $tnum $l $r $args
		}
	}
}

proc rep018_sub { method niter tnum logset recargs largs } {
	source ./include.tcl
	global rep_verbose

	set verbargs ""
	if { $rep_verbose == 1 } {
		set verbargs " -verbose {rep on} "
	}

	env_cleanup $testdir
	set omethod [convert_method $method]

	replsetup $testdir/MSGQUEUEDIR

	set masterdir $testdir/MASTERDIR
	set clientdir $testdir/CLIENTDIR

	file mkdir $masterdir
	file mkdir $clientdir
	set m_logtype [lindex $logset 0]
	set c_logtype [lindex $logset 1]

	# In-memory logs require a large log buffer, and cannot
	# be used with -txn nosync.
	set m_logargs [adjust_logargs $m_logtype]
	set c_logargs [adjust_logargs $c_logtype]
	set m_txnargs [adjust_txnargs $m_logtype]
	set c_txnargs [adjust_txnargs $c_logtype]

	puts "\tRep$tnum.a: Create master and client, bring online."
	# Open a master.
	repladd 1
	set env_cmd(M) "berkdb_env_noerr -create \
	    -log_max 1000000 -home $masterdir $verbargs \
	    $m_txnargs $m_logargs -rep_master -errpfx MASTER \
	    -rep_transport \[list 1 replsend\]"
	set masterenv [eval $env_cmd(M) $recargs]

	# Open a client
	repladd 2
	set env_cmd(C) "berkdb_env_noerr -create -home $clientdir \
	    $c_txnargs $c_logargs -rep_client $verbargs -errpfx CLIENT \
	    -rep_transport \[list 2 replsend\]"
	set clientenv [eval $env_cmd(C) $recargs]

	# Bring the client online.
	process_msgs "{$masterenv 1} {$clientenv 2}"

	# Clobber replication's 30-second anti-archive timer, which will have
	# been started by client sync-up internal init, so that we can do a
	# db_remove in a moment.
	#
	$masterenv test force noarchive_timeout

	puts "\tRep$tnum.b: Open database on master, propagate to client."
	set dbname rep$tnum.db
	set db [eval "berkdb_open -create $omethod -auto_commit \
	    -env $masterenv $largs $dbname"]
	set t [$masterenv txn]
	for { set i 1 } { $i <= $niter } { incr i } {
		error_check_good db_put \
		    [eval $db put -txn $t $i [chop_data $method data$i]] 0
	}
	error_check_good txn_commit [$t commit] 0
	process_msgs "{$masterenv 1} {$clientenv 2}"

	puts "\tRep$tnum.c: Spawn a child tclsh to do client work."
	set pid [exec $tclsh_path $test_path/wrap.tcl \
	    rep018script.tcl $testdir/rep018script.log \
		   $clientdir $niter $dbname $method &]

	puts "\tRep$tnum.d: Close and remove database on master."
	error_check_good close_master_db [$db close] 0

	# Remove database in master env.  First make sure the child
	# tclsh is done reading the data.
	while { 1 } {
		if { [file exists $testdir/marker.db] == 0  } {
			tclsleep 1
		} else {
			set markerenv [berkdb_env -home $testdir -txn]
			error_check_good markerenv_open \
			    [is_valid_env $markerenv] TRUE
			set marker [berkdb_open -unknown -env $markerenv \
			    -auto_commit marker.db]
			while { [llength [$marker get CHILDREADY]] == 0 } {
				tclsleep 1
			}
			break
		}
	}
	error_check_good db_remove [$masterenv dbremove -auto_commit $dbname] 0

	puts "\tRep$tnum.e: Create new database on master with the same name."
	set db [eval "berkdb_open -create $omethod -auto_commit \
	    -env $masterenv $largs $dbname"]
	error_check_good new_db_open [is_valid_db $db] TRUE

	puts "\tRep$tnum.f: Propagate changes to client.  Process should hang."
	error_check_good timestamp_remove \
	    [$marker put PARENTREMOVE [timestamp -r]] 0
	process_msgs "{$masterenv 1} {$clientenv 2}"
	error_check_good timestamp_done \
	    [$marker put PARENTDONE [timestamp -r]] 0

	watch_procs $pid 5

	puts "\tRep$tnum.g: Check for failure."
	# Check marker file for correct timestamp ordering.
	set ret [$marker get CHILDDONE]
	set childdone [lindex [lindex [lindex $ret 0] 1] 0]
	set ret [$marker get PARENTDONE]
	set parentdone [lindex [lindex [lindex $ret 0] 1] 0]
	if { [expr $childdone - $parentdone] > 0 } {
		puts "\tFAIL: parent must complete after child"
	}

	# Clean up.
	error_check_good marker_db_close [$marker close] 0
	error_check_good market_env_close [$markerenv close] 0
	error_check_good masterdb_close [$db close] 0
	error_check_good masterenv_close [$masterenv close] 0
	error_check_good clientenv_close [$clientenv close] 0

	replclose $testdir/MSGQUEUEDIR

	# Check log file for failures.
	set errstrings [eval findfail $testdir/rep018script.log]
	foreach str $errstrings {
		puts "FAIL: error message in rep018 log file: $str"
	}
}