Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / test / tcl / rep016.tcl
1 # See the file LICENSE for redistribution information.
2 #
3 # Copyright (c) 2002, 2012 Oracle and/or its affiliates.  All rights reserved.
4 #
5 # $Id$
6 #
7 # TEST  rep016
8 # TEST  Replication election test with varying required nvotes.
9 # TEST
10 # TEST  Run a modified version of test001 in a replicated master environment;
11 # TEST  hold an election among a group of clients to make sure they select
12 # TEST  the master with varying required participants.
13
14 proc rep016 { method args } {
15         global errorInfo
16         global databases_in_memory
17         global repfiles_in_memory
18
19         source ./include.tcl
20         set tnum "016"
21
22         # Skip for all methods except btree.
23         if { $checking_valid_methods } {
24                 set test_methods { btree }
25                 return $test_methods
26         }
27         if { [is_btree $method] == 0 } {
28                 puts "Rep$tnum: Skipping for method $method."
29                 return
30         }
31
32         set nclients 5
33         set logsets [create_logsets [expr $nclients + 1]]
34
35         # Set up for on-disk or in-memory databases.
36         set msg "using on-disk databases"
37         if { $databases_in_memory } {
38                 set msg "using named in-memory databases"
39                 if { [is_queueext $method] } { 
40                         puts -nonewline "Skipping rep$tnum for method "
41                         puts "$method with named in-memory databases"
42                         return
43                 }
44         }
45
46         set msg2 "and on-disk replication files"
47         if { $repfiles_in_memory } {
48                 set msg2 "and in-memory replication files"
49         }
50
51         # Run the body of the test with and without recovery.
52         foreach r $test_recopts {
53                 foreach l $logsets {
54                         set logindex [lsearch -exact $l "in-memory"]
55                         if { $r == "-recover" && $logindex != -1 } {
56                                 puts "Rep$tnum: Skipping\
57                                     for in-memory logs with -recover."
58                                 continue
59                         }
60                         puts "Rep$tnum ($method $r): Replication\
61                             elections with varying nvotes $msg $msg2."
62                         puts "Rep$tnum: Master logs are [lindex $l 0]"
63                         for { set i 0 } { $i < $nclients } { incr i } {
64                                 puts "Rep$tnum: Client $i logs are\
65                                     [lindex $l [expr $i + 1]]"
66                         }
67                         rep016_sub $method $nclients $tnum $l $r $args
68                 }
69         }
70 }
71
72 proc rep016_sub { method nclients tnum logset recargs largs } {
73         source ./include.tcl
74         global databases_in_memory
75         global repfiles_in_memory
76         global rep_verbose
77         global verbose_type
78
79         set verbargs ""
80         if { $rep_verbose == 1 } {
81                 set verbargs " -verbose {$verbose_type on} "
82         }
83
84         set repmemargs ""
85         if { $repfiles_in_memory } {
86                 set repmemargs "-rep_inmem_files "
87         }
88
89         env_cleanup $testdir
90
91         set niter 5
92         set qdir $testdir/MSGQUEUEDIR
93         replsetup $qdir
94
95         set masterdir $testdir/MASTERDIR
96         file mkdir $masterdir
97
98         set m_logtype [lindex $logset 0]
99         set m_logargs [adjust_logargs $m_logtype]
100         set m_txnargs [adjust_txnargs $m_logtype]
101
102         for { set i 0 } { $i < $nclients } { incr i } {
103                 set clientdir($i) $testdir/CLIENTDIR.$i
104                 file mkdir $clientdir($i)
105                 set c_logtype($i) [lindex $logset [expr $i + 1]]
106                 set c_logargs($i) [adjust_logargs $c_logtype($i)]
107                 set c_txnargs($i) [adjust_txnargs $c_logtype($i)]
108         }
109
110         # Open a master.
111         set envlist {}
112         repladd 1
113         set env_cmd(M) "berkdb_env_noerr -create -log_max 1000000 \
114             -event $repmemargs \
115             -home $masterdir $m_txnargs $m_logargs -rep_master $verbargs \
116             -errpfx MASTER -rep_transport \[list 1 replsend\]"
117         set masterenv [eval $env_cmd(M) $recargs]
118         lappend envlist "$masterenv 1"
119
120         # Open the clients.
121         # Don't set -errfile now -- wait until the error catching
122         # portion of the test is complete.
123         for { set i 0 } { $i < $nclients } { incr i } {
124                 set envid [expr $i + 2]
125                 repladd $envid
126                 set env_cmd($i) "berkdb_env_noerr -create -home $clientdir($i) \
127                     -event $repmemargs \
128                     $c_txnargs($i) $c_logargs($i) -rep_client $verbargs \
129                     -rep_transport \[list $envid replsend\]"
130                 set clientenv($i) [eval $env_cmd($i) $recargs]
131                 lappend envlist "$clientenv($i) $envid"
132         }
133         # Bring the clients online by processing the startup messages.
134         process_msgs $envlist
135
136         # Run a modified test001 in the master.
137         puts "\tRep$tnum.a: Running rep_test in replicated env."
138         eval rep_test $method $masterenv NULL $niter 0 0 0 $largs
139         process_msgs $envlist
140
141         # Check that databases are in-memory or on-disk as expected.
142         if { $databases_in_memory } {
143                 set dbname { "" "test.db" }
144         } else { 
145                 set dbname "test.db"
146         } 
147         check_db_location $masterenv
148         for { set i 0 } { $i < $nclients } { incr i } { 
149                 check_db_location $clientenv($i)
150         }
151         
152         error_check_good masterenv_close [$masterenv close] 0
153         set envlist [lreplace $envlist 0 0]
154
155         puts "\tRep$tnum.b: Error values for rep_elect"
156         #
157         # Do all the error catching in client0.  We do not need to call
158         # start_election here to fork a process because we never get
159         # far enough to send/receive any messages.  We just want to
160         # check the error message.
161         #
162         # !!!
163         # We cannot set -errpfx or -errfile or anything in the
164         # env_cmd above.  Otherwise the correct output won't be set
165         # in 'ret' below and the test will fail.
166         #
167         # First check negative nvotes.
168         #
169         set nsites [expr $nclients + 1]
170         set priority 2
171         set timeout 5000000
172         #
173         # Setting nsites to 0 acts as a signal for rep_elect to use
174         # the configured nsites, but since we haven't set that yet,
175         # this should still fail.  TODO: need another test verifying
176         # the proper operation when we *have* configured nsites.
177         #
178         set nsites 0
179         set nvotes 2
180         set res [catch {$clientenv(0) rep_elect $nsites $nvotes $priority \
181             $timeout} ret]
182         error_check_bad catch $res 0
183         error_check_good ret [is_substr $ret "is larger than nsites"] 1
184
185         #
186         # Check nvotes > nsites.
187         #
188         set nsites $nclients
189         set nvotes [expr $nsites + 1]
190         set res [catch {$clientenv(0) rep_elect $nsites $nvotes $priority \
191             $timeout} ret]
192         error_check_bad catch $res 0
193         error_check_good ret [is_substr $ret "is larger than nsites"] 1
194
195         for { set i 0 } { $i < $nclients } { incr i } {
196                 replclear [expr $i + 2]
197                 #
198                 # This test doesn't use the testing hooks, so
199                 # initialize err_cmd and crash appropriately.
200                 #
201                 set err_cmd($i) "none"
202                 set crash($i) 0
203                 #
204                 # Initialize the array pri.  We'll set it to
205                 # appropriate values when the winner is determined.
206                 #
207                 set pri($i) 0
208                 #
209                 if { $rep_verbose == 1 } {
210                         $clientenv($i) errpfx CLIENT.$i
211                         $clientenv($i) verbose $verbose_type on
212                         $clientenv($i) errfile /dev/stderr
213                         set env_cmd($i) [concat $env_cmd($i) \
214                             "-errpfx CLIENT.$i -errfile /dev/stderr "]
215                 }
216         }
217         set m "Rep$tnum.c"
218         puts "\t$m: Check single master/client can elect itself"
219         #
220         # 2 sites: 1 master, 1 client.  Allow lone client to elect itself.
221         # Adjust client env list to reflect the single client.
222         #
223         set oldenvlist $envlist
224         set envlist [lreplace $envlist 1 end]
225         set nsites 2
226         set nvotes 1
227         set orig_ncl $nclients
228         set nclients 1
229         set elector 0
230         set winner 0
231         setpriority pri $nclients $winner
232         run_election envlist err_cmd pri crash\
233             $qdir $m $elector $nsites $nvotes $nclients $winner 1 $dbname
234
235         #
236         # Now run with all clients.  Client0 should always get elected
237         # because it became master and should have a bigger LSN.
238         #
239         set nclients $orig_ncl
240         set envlist [lreplace $oldenvlist 0 0 [lindex $envlist 0]]
241
242         set m "Rep$tnum.d"
243         puts "\t$m: Elect with 100% client participation"
244         set nsites $nclients
245         set nvotes $nclients
246         set winner [rep016_selectwinner $nsites $nvotes $nclients]
247         setpriority pri $nclients $winner
248         run_election envlist err_cmd pri crash\
249             $qdir $m $elector $nsites $nvotes $nclients $winner 1 $dbname
250
251         #
252         # Elect with varying levels of participation.  Start with nsites
253         # as nclients+1 (simulating a down master) and require nclients,
254         # and fewer (by 1) until we get down to 2 clients.
255         #
256         set m "Rep$tnum.e"
257         puts "\t$m: Elect with varying participation"
258         set nsites [expr $nclients + 1]
259         set count 0
260         for {set n $nclients} {$n > 1} {incr n -1} {
261                 set m "Rep$tnum.e.$count"
262                 set winner [rep016_selectwinner $nsites $n $n]
263                 setpriority pri $nclients $winner
264                 run_election envlist err_cmd pri crash\
265                     $qdir $m $elector $nsites $n $n $winner 1 $dbname
266                 incr count
267         }
268
269         foreach pair $envlist {
270                 set cenv [lindex $pair 0]
271                 error_check_good cenv_close [$cenv close] 0
272         }
273         replclose $testdir/MSGQUEUEDIR
274 }
275
276 proc rep016_selectwinner { nsites nvotes nclients } {
277         #
278         # Special case:  When we test with 100% participation, we expect
279         # client 0 to always win because it has a bigger LSN than the
280         # rest due to earlier part of the test.  This special case is
281         # kinda gross.
282         #
283         if { $nsites != $nvotes } {
284                 set win [berkdb random_int 0 [expr $nclients - 1]]
285         } else {
286                 set win 0
287         }
288         return $win
289 }