File: rep093.tcl

package info (click to toggle)
db5.3 5.3.28%2Bdfsg2-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 158,500 kB
  • sloc: ansic: 448,411; java: 111,824; tcl: 80,544; sh: 44,264; cs: 33,697; cpp: 21,604; perl: 14,557; xml: 10,799; makefile: 4,077; javascript: 1,998; yacc: 1,003; awk: 965; sql: 801; erlang: 342; python: 216; php: 24; asm: 14
file content (252 lines) | stat: -rw-r--r-- 6,938 bytes parent folder | download | duplicates (8)
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2010, 2013 Oracle and/or its affiliates.  All rights reserved.
#
# TEST	rep093
# TEST	Egen changes during election.
#
proc rep093 { method { niter 20 } { tnum "093" } args } {
	source ./include.tcl

	# Skip for all methods except btree.
	if { $checking_valid_methods } {
		set test_methods { btree }
		return $test_methods
	}
	if { [is_btree $method] == 0 } {
		puts "Rep$tnum: Skipping for method $method."
		return
	}

	rep093_sub $method $niter $tnum yes $args
	rep093_sub $method $niter $tnum no $args
}

# Start an election at site A, at a time when site B already has a higher egen.
# When site B sees the obsolete VOTE1, it responds with an ALIVE, and that causes
# site A recognize an egen update (producing HOLDELECTION, causing us to start
# another election process, and to abandon the first one).
#
# When $lost is true, we discard site A's initial VOTE1 message, and manually
# start an election at site B as well.  In this case it's the VOTE1 message that
# causes site A to realize it needs an egen update.  The result is similar,
# though the code path is completely different.
# 
proc rep093_sub { method niter tnum lost largs } {
	global rep_verbose
	global testdir
	global verbose_type
	global repfiles_in_memory
	global queuedbs
	global elect_serial

	if { $lost } {
		set msg " with lost VOTE1 message"
	} else {
		set msg ""
	}
	puts "Rep$tnum: Egen change during election$msg."

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

	set repmemargs ""
	if { $repfiles_in_memory } {
		set repmemargs "-rep_inmem_files "
	}

	env_cleanup $testdir

	replsetup [set qdir $testdir/MSGQUEUEDIR]

	set dira $testdir/SITEA
	set dirb $testdir/SITEB

	file mkdir $dira
	file mkdir $dirb

	puts "\tRep$tnum.a: Create a small group."
	repladd 1
	set envcmda "berkdb_env_noerr -create -txn -errpfx SITEA \
	    $repmemargs -event \
	    $verbargs -home $dira -rep_transport \[list 1 replsend\]"

	# Site A will be initial master, just so as to create some initial
	# data.
	# 
	set enva [eval $envcmda -rep_master]
	set masterenv $enva

	repladd 2
	set envcmdb "berkdb_env_noerr -create -txn -errpfx SITEB \
	    $repmemargs -event \
	    $verbargs -home $dirb -rep_transport \[list 2 replsend\]"
	set envb [eval $envcmdb -rep_client]

	set envlist "{$enva 1} {$envb 2}"
	process_msgs $envlist

	set start 0
	eval rep_test $method $masterenv NULL $niter $start $start 0 $largs
	incr start $niter

	# Level the playing field, by making site A a client.
	puts "\tRep$tnum.b: Make site A a client."
	$enva rep_start -client
	process_msgs $envlist

	# Arrange for site B to have a higher egen than site A.  We do this by
	# running a couple of quick election attempts from B in which A does not
	# participate.
	# 
	puts "\tRep$tnum.c: Adjust site B's egen."
	set pri 100
	set timeout 10000
	set nsites 2
	set nvotes 2
	error_check_bad solitaire1 [catch {$envb rep_elect \
		$nsites $nvotes $pri $timeout} result] 0
	error_check_good solitaire1a [is_substr $result DB_REP_UNAVAIL] 1
	error_check_bad solitaire2 [catch {$envb rep_elect \
		$nsites $nvotes $pri $timeout} result] 0
	error_check_good solitaire2a [is_substr $result DB_REP_UNAVAIL] 1

	set egena [stat_field $enva rep_stat "Election generation number"]
	set egenb [stat_field $envb rep_stat "Election generation number"]
	error_check_good starting_egen [expr $egenb > $egena] 1
	replclear 1

	# Start an election at site A, using a timeout longer than we should
	# ever need.
	# 
	puts "\tRep$tnum.d: Start an election at site A."
	set envid 1
	set timeout [expr 60 * 1000000]
	set elect_serial 1
	set pfx "A.1"
	start_election $pfx $qdir $dira $envid $nsites $nvotes $pri $timeout
	set elect_pipe($envid) $elect_serial

	set wait_limit 20
	if { $lost } {
		# Wait until the child process has gotten as far as sending its
		# vote1 message to site B (eid 2).  We want to "lose" that
		# message, but it won't do any good to replclear before the
		# message is actually in the message queue.
		#
		set envid 2
		set voted false
		for { set count 0 } { $count < $wait_limit } { incr count } {
			if {[rep093_find_vote1 $envid]} {
				set voted true
				break;
			}
			tclsleep 1
		}
		error_check_good voted $voted true
		replclear $envid
		
		# Start an election at site B.  We expect site A to react to
		# this by indicating that we should start another rep_elect()
		# call immediately.  We'll check this later, when we examine the
		# $got_egenchg flag.
		#
		puts "\tRep$tnum.e: Start election at site B."
		incr elect_serial
		set pfx "B.$elect_serial"
		start_election $pfx $qdir $dirb $envid $nsites $nvotes $pri $timeout
		set elect_pipe($envid) $elect_serial
	}

	set got_egenchg false
	set got_master false
	set done false
	for { set count 0 } { $count < $wait_limit && !$done} { incr count } {
		foreach pair $envlist {
			set env [lindex $pair 0]
			set envid [lindex $pair 1]
			if { [info exists elect_pipe($envid)] } {
				check_election $elect_pipe($envid) \
				    unavail child_elected
			} else {
				set child_elected false
			}
			set parent_elected [is_elected $env]
			if { ( $child_elected || $parent_elected ) && \
				 !$got_master } {
				set got_master true
				puts "\tRep$tnum.f: Env [$env get_errpfx]\
				    won the election."
				$env rep_start -master
				if { $env eq $enva } {
					set client $envb
				} else {
					set client $enva
				}
			}
			replprocessqueue $env $envid 0 he
			if { $he } {
				# In the "lost msg case" the only HOLDELECTION
				# indication we should be getting is at site A
				# (EID 1).
				#
				if { $lost } {
					error_check_good siteA $envid 1
				}
				if { $env eq $enva } {
					set got_egenchg true
				}
				incr elect_serial
				set envpfx [$env get_errpfx]
				set pfx "$envpfx.$elect_serial"
				puts "\tRep$tnum.g: Starting another\
				    election $pfx at $envpfx."
				set dir [$env get_home]
				start_election $pfx $qdir $dir $envid \
				    $nsites $nvotes $pri $timeout
				set elect_pipe($envid) $elect_serial
			}
		}
		if { $got_master && \
		    [stat_field $client rep_stat "Startup complete"] } {
			puts "\tRep$tnum.h: Env [$client get_errpfx]\
			    has STARTUPDONE."
			set done true
		} else {
			tclsleep 1
		}
	}
	error_check_good done $done true
	error_check_good got_egenchg $got_egenchg true
	cleanup_elections

	$enva close
	$envb close
	replclose $qdir
}


proc rep093_find_vote1 { envid } {
	global queuedbs

	set dbc [$queuedbs($envid) cursor]

	set result no
	for { set records [$dbc get -first] } \
	    { [llength $records] > 0 } \
	    { set records [$dbc get -next] } {
		    set dbt_pair [lindex $records 0]
		    set recno [lindex $dbt_pair 0]
		    set msg [lindex $dbt_pair 1]
		    set ctrl [lindex $msg 0]
		    if {[berkdb msgtype $ctrl] eq "vote1"} {
			    set result yes
			    break
		    }
	    }
	
	$dbc close
	return $result
}