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 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
|
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2001, 2013 Oracle and/or its affiliates. All rights reserved.
#
# $Id$
#
# TEST rep079
# TEST Replication leases and invalid usage.
# TEST
# TEST Open a client without leases. Attempt to set leases after rep_start.
# TEST Attempt to declare as master without election.
# TEST Run an election with an nsites parameter value.
# TEST Elect a master with leases. Put some data and send to clients.
# TEST Cleanly shutdown master env. Restart without
# TEST recovery and verify leases are expired and refreshed.
# TEST Add a new client without leases to a group using leases.
# TEST Test errors if we cannot get leases before/after txn_commit.
#
proc rep079 { method { tnum "079" } args } {
source ./include.tcl
global repfiles_in_memory
# Valid for all access methods, but there is no difference
# running it with one method over any other. Just use 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
}
set args [convert_args $method $args]
set logsets [create_logsets 4]
set msg2 "and on-disk replication files"
if { $repfiles_in_memory } {
set msg2 "and in-memory replication files"
}
foreach l $logsets {
#
# Skip the case where the master is in-memory and at least
# one of the clients is on-disk. If the master is in-memory,
# the wrong site gets elected because on-disk envs write a log
# record when they create the env and in-memory ones do not
# and the test wants to control which env gets elected.
#
set master_logs [lindex $l 0]
if { $master_logs == "in-memory" } {
set client_logs [lsearch -exact $l "on-disk"]
if { $client_logs != -1 } {
puts "Skipping for in-memory master\
with on-disk client."
continue
}
}
puts "Rep$tnum: Replication leases and invalid usage $msg2."
puts "Rep$tnum: Master logs are [lindex $l 0]"
puts "Rep$tnum: Client logs are [lindex $l 1]"
puts "Rep$tnum: Client 2 logs are [lindex $l 2]"
puts "Rep$tnum: Client 3 logs are [lindex $l 3]"
rep079_sub $method $tnum $l $args
}
}
proc rep079_sub { method tnum logset largs } {
global testdir
global repfiles_in_memory
global rep_verbose
global verbose_type
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
set qdir $testdir/MSGQUEUEDIR
replsetup $qdir
set masterdir $testdir/MASTERDIR
set clientdir $testdir/CLIENTDIR
set clientdir2 $testdir/CLIENTDIR2
set clientdir3 $testdir/CLIENTDIR3
file mkdir $masterdir
file mkdir $clientdir
file mkdir $clientdir2
file mkdir $clientdir3
set m_logtype [lindex $logset 0]
set c_logtype [lindex $logset 1]
set c2_logtype [lindex $logset 2]
set c3_logtype [lindex $logset 3]
# In-memory logs cannot be used with -txn nosync.
set m_logargs [adjust_logargs $m_logtype]
set c_logargs [adjust_logargs $c_logtype]
set c2_logargs [adjust_logargs $c2_logtype]
set c3_logargs [adjust_logargs $c3_logtype]
set m_txnargs [adjust_txnargs $m_logtype]
set c_txnargs [adjust_txnargs $c_logtype]
set c2_txnargs [adjust_txnargs $c2_logtype]
set c3_txnargs [adjust_txnargs $c3_logtype]
# Set leases for 4 sites, 1 second timeout, 1% clock skew
# [NOTE: We are not adding in client3 until later so don't
# set it in nvotes.]
set nsites 4
set nvotes 3
set lease_to 1000000
set lease_tosec [expr $lease_to / 1000000]
set clock_fast 101
set clock_slow 100
repladd 2
#
# Use a command without setting errpfx, errfile or verbose
# so that error messages can be caught correctly.
#
set envcmd_err "berkdb_env_noerr -create $m_txnargs $m_logargs \
$repmemargs -home $masterdir -rep_transport \[list 2 replsend\]"
#
# This is the real env command, but we won't use it
# quite yet.
set envcmd(0) "berkdb_env_noerr -create $m_txnargs $m_logargs \
$repmemargs $verbargs -errpfx MASTER -home $masterdir \
-event \
-rep_transport \[list 2 replsend\]"
#
# Leases must be configured before rep_start is called.
# Open a repl env without leases. Try to configure leases
# after the open has already called rep_start. Open as a client.
#
puts "\tRep$tnum.a: Try to configure leases after rep_start."
set noleaseenv [eval $envcmd_err -rep_client]
$noleaseenv rep_nsites $nsites
set stat [catch {$noleaseenv rep_lease \
[list $lease_to $clock_fast $clock_slow]} lease]
error_check_bad stat $stat 0
error_check_good menverror [is_substr $lease "timeout must be set"] 1
error_check_good close [$noleaseenv close] 0
env_cleanup $masterdir
#
# If leases are being used, elections must be used. A site
# cannot simply upgrade itself to master. Test that we cannot
# open as a client and then upgrade ourself to a master just
# by calling rep_start.
#
set upgenv [eval $envcmd_err -rep_client -rep_nsites $nsites \
-rep_lease \[list $lease_to $clock_fast $clock_slow\]]
puts "\tRep$tnum.b: Try to upgrade a client without election."
set stat [catch {$upgenv rep_start -master} ret]
error_check_bad upg_stat $stat 0
error_check_good upg_str [is_substr $ret "Cannot become master"] 1
error_check_good close [$upgenv close] 0
env_cleanup $masterdir
#
# Now test inconsistencies dealing with having a group that
# is using lease up and running. For instance, if leases are
# configured, the 'nsites' arg to rep_elect must be 0, etc.
#
# Open the master. Must open as a client and get elected.
#
set err_cmd(0) "none"
set crash(0) 0
set pri(0) 100
set masterenv [eval $envcmd(0) -rep_client -rep_nsites $nsites \
-rep_lease \[list $lease_to $clock_fast $clock_slow\]]
error_check_good master_env [is_valid_env $masterenv] TRUE
# Open two clients.
repladd 3
set err_cmd(1) "none"
set crash(1) 0
set pri(1) 10
set envcmd(1) "berkdb_env -create $c_txnargs $c_logargs \
$repmemargs $verbargs -errpfx CLIENT -home $clientdir \
-event -rep_nsites $nsites \
-rep_lease \[list $lease_to $clock_fast $clock_slow\] \
-rep_client -rep_transport \[list 3 replsend\]"
set clientenv [eval $envcmd(1)]
error_check_good client_env [is_valid_env $clientenv] TRUE
repladd 4
set err_cmd(2) "none"
set crash(2) 0
set pri(2) 10
set envcmd(2) "berkdb_env_noerr -create $c2_txnargs $c2_logargs \
$repmemargs -home $clientdir2 -event -rep_nsites $nsites \
-rep_lease \[list $lease_to $clock_fast $clock_slow\] \
-rep_client -rep_transport \[list 4 replsend\]"
set clientenv2 [eval $envcmd(2)]
error_check_good client_env [is_valid_env $clientenv2] TRUE
# Bring the clients online by processing the startup messages.
set envlist "{$masterenv 2} {$clientenv 3} {$clientenv2 4}"
process_msgs $envlist
#
# Send a non-zero nsites value for an election. That is an error.
#
puts "\tRep$tnum.c: Try to run election with leases and nsites value."
#
# !!! We have not set -errpfx or -errfile in envcmd(2) above
# otherwise the error output won't be set in 'ret' below and
# the test will fail. Set it after this piece of the test.
#
set timeout 5000000
set res [catch {$clientenv2 rep_elect $nsites $nvotes $pri(2) \
$timeout} ret]
error_check_bad catch $res 0
error_check_good ret [is_substr $ret "nsites must be zero"] 1
#
# Now we can set verbose args, errpfx, etc. Set it in the
# command (for elections) and also manually add it to the
# current env handle.
#
set envcmd(2) "$envcmd(2) $verbargs -errpfx CLIENT2"
if { $rep_verbose == 1 } {
$clientenv2 verbose $verbose_type on
$clientenv2 errpfx CLIENT2
}
#
# This next section will test that a replicated env that is master
# can cleanly close and then reopen without recovery and retain
# its master status.
#
set msg "Rep$tnum.d"
set nvotes [expr $nsites - 1]
set winner 0
setpriority pri $nsites $winner
set elector [berkdb random_int 0 2]
puts "\tRep$tnum.d: Run election for real to get master."
#
# Run election for real. Set nsites to 0 for this command.
#
repladd 5
set err_cmd(3) "none"
set crash(3) 0
set pri(3) 0
run_election envlist err_cmd pri crash $qdir $msg \
$elector 0 $nvotes $nsites $winner 0 NULL
puts "\tRep$tnum.e: Write a checkpoint."
#
# Writing a checkpoint forces a PERM record which will cause
# the clients to grant us their leases. Then, while holding
# the lease grants we can do the next part of the test to
# close and cleanly reopen while holding leases.
$masterenv txn_checkpoint -force
process_msgs $envlist
puts "\tRep$tnum.f.0: Close master env."
error_check_good mclose [$masterenv close] 0
set sleep [expr $lease_tosec + 1]
puts "\tRep$tnum.f.1: Sleep $sleep secs to expire lease grants."
tclsleep $sleep
#
# We should be able to reopen the master env without running
# recovery and still retain our mastership.
set masterenv [eval $envcmd(0) -rep_master -rep_nsites $nsites \
-rep_lease \[list $lease_to $clock_fast $clock_slow\]]
error_check_good master_env [is_valid_env $masterenv] TRUE
set envlist "{$masterenv 2} {$clientenv 3} {$clientenv2 4}"
#
# Verify that if a non-lease site tries to join a group that
# is using leases, it gets an error. Configuring leases
# must be all-or-none across all group members.
#
puts "\tRep$tnum.g: Add client3 that does not configure leases."
replclear 5
set envcmd(3) "berkdb_env_noerr -create $c3_txnargs $c3_logargs \
-home $clientdir3 -event \
$repmemargs $verbargs -errpfx CLIENT3 \
-rep_client -rep_transport \[list 5 replsend\]"
set clientenv3 [eval $envcmd(3)]
error_check_good client_env [is_valid_env $clientenv3] TRUE
# Bring the clients online by processing the startup messages.
set origlist $envlist
set envlist "{$masterenv 2} {$clientenv 3} \
{$clientenv2 4} {$clientenv3 5}"
process_msgs $envlist 0 NONE err
puts "\tRep$tnum.g.1: Verify client fatal error."
error_check_good process_msgs_err [is_substr $err DB_RUNRECOVERY] 1
#
# Close to reclaim Tcl resources, but we want to catch/ignore
# the continuing DB_RUNRECOVERY error. The extra env_cleanup is
# necessary on Windows; otherwise region files hang around and
# can cause the next test to fail.
#
catch {$clientenv3 close} ret
env_cleanup $clientdir3
set envlist $origlist
puts "\tRep$tnum.h: Check expired lease error on txn commit."
#
# Leases are already expired, so attempt to commit should fail.
# (And this will be the 'before we commit' check that returns
# an error, not the 'after' check that panics).
#
# We need to create a txn that actually generates log records.
#
set omethod [convert_method $method]
set txn [$masterenv txn]
set db [berkdb_open_noerr -create $omethod -env $masterenv -txn $txn \
-mode 0644 lease.db]
set stat [catch {$txn commit} ret]
error_check_good close [$db close] 0
error_check_good stat $stat 1
error_check_good exp [is_substr $ret REP_LEASE_EXPIRED] 1
#
# Process messages so that we refresh the leases.
# Then attempt a commit. This too should fail but this time
# it will be the "after" check because we're not processing
# messages to get the commit's lease grant from the client.
$masterenv txn_checkpoint -force
process_msgs $envlist 0 NONE err
puts "\tRep$tnum.i: Check panic lease error on txn commit."
set txn [$masterenv txn]
set db [eval berkdb_open_noerr -txn $txn -env $masterenv -create \
-btree -mode 0644 test.db]
set stat [catch {$txn commit} ret]
error_check_good stat $stat 1
error_check_good exp [is_substr $ret DB_RUNRECOVERY] 1
set stat [catch {$db close} ret]
#
# Since we panic'ed the master env, we expect non-zero. But
# we need to close it to clean up the Tcl resources.
#
error_check_good mclose [catch {$masterenv close} ret] 1
error_check_good cclose [$clientenv close] 0
error_check_good c2close [$clientenv2 close] 0
replclose $testdir/MSGQUEUEDIR
}
|