summaryrefslogtreecommitdiff
path: root/storage/bdb/test/rep005.tcl
blob: e0515f1cd629cac6cb44b24774a59aafe37f7556 (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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2002
#	Sleepycat Software.  All rights reserved.
#
# $Id: rep005.tcl,v 11.3 2002/08/08 18:13:13 sue Exp $
#
# TEST  rep005
# TEST	Replication election test with error handling.
# TEST
# TEST	Run a modified version of test001 in a replicated master environment;
# TEST  hold an election among a group of clients to make sure they select
# TEST  a proper master from amongst themselves, forcing errors at various
# TEST	locations in the election path.

proc rep005 { method { niter 10 } { tnum "05" } args } {
	source ./include.tcl

	if { [is_record_based $method] == 1 } {
		puts "Rep005: Skipping for method $method."
		return
	}

	set nclients 3
	env_cleanup $testdir

	set qdir $testdir/MSGQUEUEDIR
	replsetup $qdir

	set masterdir $testdir/MASTERDIR
	file mkdir $masterdir

	for { set i 0 } { $i < $nclients } { incr i } {
		set clientdir($i) $testdir/CLIENTDIR.$i
		file mkdir $clientdir($i)
	}

	puts "Rep0$tnum: Replication election test with $nclients clients."

	# Open a master.
	repladd 1
	set env_cmd(M) "berkdb_env -create -log_max 1000000 -home \
	    $masterdir -txn -rep_master -rep_transport \[list 1 replsend\]"
	set masterenv [eval $env_cmd(M)]
	error_check_good master_env [is_valid_env $masterenv] TRUE

	# Open the clients.
	for { set i 0 } { $i < $nclients } { incr i } {
		set envid [expr $i + 2]
		repladd $envid
		set env_cmd($i) "berkdb_env -create -home $clientdir($i) \
		    -txn -rep_client -rep_transport \[list $envid replsend\]"
		set clientenv($i) [eval $env_cmd($i)]
		error_check_good \
		    client_env($i) [is_valid_env $clientenv($i)] TRUE
	}

	# Run a modified test001 in the master.
	puts "\tRep0$tnum.a: Running test001 in replicated env."
	eval test001 $method $niter 0 $tnum 0 -env $masterenv $args

	# Loop, processing first the master's messages, then the client's,
	# until both queues are empty.
	while { 1 } {
		set nproced 0

		incr nproced [replprocessqueue $masterenv 1]

		for { set i 0 } { $i < $nclients } { incr i } { 	
			set envid [expr $i + 2]
			incr nproced [replprocessqueue $clientenv($i) $envid]
		}

		if { $nproced == 0 } {
			break
		}
	}

	# Verify the database in the client dir.
	for { set i 0 } { $i < $nclients } { incr i } {
		puts "\tRep0$tnum.b: Verifying contents of client database $i."
		set testdir [get_home $masterenv]
		set t1 $testdir/t1
		set t2 $testdir/t2
		set t3 $testdir/t3
		open_and_dump_file test0$tnum.db $clientenv($i) $testdir/t1 \
	    	    test001.check dump_file_direction "-first" "-next"

		if { [string compare [convert_method $method] -recno] != 0 } {
			filesort $t1 $t3
		}
		error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0

		verify_dir $clientdir($i) "\tRep0$tnum.c: " 0 0 1
	}

	# Make sure all the clients are synced up and ready to be good
	# voting citizens.
	error_check_good master_flush [$masterenv rep_flush] 0
	while { 1 } {
		set nproced 0
		incr nproced [replprocessqueue $masterenv 1 0]
		for { set i 0 } { $i < $nclients } { incr i } {
			incr nproced [replprocessqueue $clientenv($i) \
			    [expr $i + 2] 0]
		}

		if { $nproced == 0 } {
			break
		}
	}

	error_check_good masterenv_close [$masterenv close] 0

	for { set i 0 } { $i < $nclients } { incr i } {
		replclear [expr $i + 2]
	}
	#
	# We set up the error list for each client.  We know that the
	# first client is the one calling the election, therefore, add
	# the error location on sending the message (electsend) for that one.
	set m "Rep0$tnum"
	set count 0
	foreach c0 { electinit electsend electvote1 electwait1 electvote2 \
	    electwait2 } {
		foreach c1 { electinit electvote1 electwait1 electvote2 \
		    electwait2 } {
			foreach c2 { electinit electvote1 electwait1 \
			    electvote2 electwait2 } {
				set elist [list $c0 $c1 $c2]
				rep005_elect env_cmd clientenv $qdir $m \
				    $count $elist
				incr count
			}
		}
	}

	for { set i 0 } { $i < $nclients } { incr i } {
		error_check_good clientenv_close($i) [$clientenv($i) close] 0
	}

	replclose $testdir/MSGQUEUEDIR
}

proc rep005_elect { ecmd cenv qdir msg count elist } {
	global elect_timeout
	upvar $ecmd env_cmd
	upvar $cenv clientenv

	set elect_timeout 1000000
	set nclients [llength $elist]

	for { set i 0 } { $i < $nclients } { incr i } { 	
		set err_cmd($i) [lindex $elist $i]
	}
	puts "\t$msg.d.$count: Starting election with errors $elist"
	set elect_pipe(0) [start_election $qdir $env_cmd(0) \
	    [expr $nclients + 1] 20 $elect_timeout $err_cmd(0)]

	tclsleep 1

	# Process messages, and verify that the client with the highest
	# priority--client #1--wins.
	set got_newmaster 0
	set tries 10
	while { 1 } {
		set nproced 0
		set he 0
		set nm 0
		
		for { set i 0 } { $i < $nclients } { incr i } { 	
			set he 0
			set envid [expr $i + 2]
# puts "Processing queue for client $i"
			incr nproced \
			    [replprocessqueue $clientenv($i) $envid 0 he nm]
			if { $he == 1 } {
				# Client #1 has priority 100;  everyone else
				if { $i == 1 } {
					set pri 100
				} else {
					set pri 10
				}
				# error_check_bad client(0)_in_elect $i 0
# puts "Starting election on client $i"
				set elect_pipe($i) [start_election $qdir \
			    	    $env_cmd($i) [expr $nclients + 1] $pri \
				    $elect_timeout $err_cmd($i)]
				set got_hold_elect($i) 1
			}
			if { $nm != 0 } {
				error_check_good newmaster_is_master $nm \
				    [expr 1 + 2]
				set got_newmaster $nm

				# If this env is the new master, it needs to
				# configure itself as such--this is a different
				# env handle from the one that performed the
				# election.
				if { $nm == $envid } {
					error_check_good make_master($i) \
					    [$clientenv($i) rep_start -master] \
					    0
				}
			}
		}

		# We need to wait around to make doubly sure that the
		# election has finished...
		if { $nproced == 0 } {
			incr tries -1
			if { $tries == 0 } {
				break
			} else {
				tclsleep 1
			}
		}
	}

	# Verify that client #1 is actually the winner.
	error_check_good "client 1 wins" $got_newmaster [expr 1 + 2]

	cleanup_elections

}