mirror of
https://github.com/berkeleydb/libdb.git
synced 2024-11-16 17:16:25 +00:00
219 lines
6.6 KiB
Tcl
219 lines
6.6 KiB
Tcl
|
# See the file LICENSE for redistribution information.
|
||
|
#
|
||
|
# Copyright (c) 2009, 2011 Oracle and/or its affiliates. All rights reserved.
|
||
|
#
|
||
|
# TEST repmgr105
|
||
|
# TEST Repmgr recognition of peer setting, across processes.
|
||
|
# TEST
|
||
|
# TEST Set up a master and two clients, synchronized with some data.
|
||
|
# TEST Add a new client, configured to use c2c sync with one of the original
|
||
|
# TEST clients. Check stats to make sure the correct c2c peer was used.
|
||
|
|
||
|
proc repmgr105 { } {
|
||
|
repmgr105_sub position_chg
|
||
|
repmgr105_sub chg_site
|
||
|
repmgr105_sub chg_after_open
|
||
|
repmgr105_sub set_peer_after_open
|
||
|
}
|
||
|
|
||
|
proc repmgr105_sub { config } {
|
||
|
source ./include.tcl
|
||
|
|
||
|
set tnum "105"
|
||
|
puts "Repmgr$tnum: Repmgr peer, with \"$config\" configuration."
|
||
|
set site_prog [setup_site_prog]
|
||
|
|
||
|
env_cleanup $testdir
|
||
|
|
||
|
set ports [available_ports 4]
|
||
|
set mport [lindex $ports 0]
|
||
|
set portA [lindex $ports 1]
|
||
|
set portB [lindex $ports 2]
|
||
|
|
||
|
file mkdir [set masterdir $testdir/MASTER]
|
||
|
file mkdir $testdir/A
|
||
|
file mkdir $testdir/B
|
||
|
file mkdir $testdir/C
|
||
|
|
||
|
puts "\tRepmgr$tnum.a: Start master, write some data."
|
||
|
make_dbconfig $masterdir {}
|
||
|
set cmds {
|
||
|
"home $masterdir"
|
||
|
"local $mport"
|
||
|
"output $testdir/moutput"
|
||
|
"open_env"
|
||
|
"start master"
|
||
|
"open_db test.db"
|
||
|
"put key1 value1"
|
||
|
}
|
||
|
set m [open_site_prog [subst $cmds]]
|
||
|
|
||
|
puts "\tRepmgr$tnum.b:\
|
||
|
Start initial two clients; wait for them to synchronize."
|
||
|
# Allowing both A and B to start at the same time, and synchronize
|
||
|
# concurrently would make sense. But it causes very slow performance on
|
||
|
# Windows. Since it's really only client C that's under test here, this
|
||
|
# detail doesn't matter.
|
||
|
#
|
||
|
make_dbconfig $testdir/A {}
|
||
|
set a [open_site_prog [list \
|
||
|
"home $testdir/A" \
|
||
|
"local $portA" \
|
||
|
"output $testdir/aoutput" \
|
||
|
"remote localhost $mport" \
|
||
|
"open_env" \
|
||
|
"start client"]]
|
||
|
set env [berkdb_env -home $testdir/A]
|
||
|
await_startup_done $env
|
||
|
$env close
|
||
|
|
||
|
make_dbconfig $testdir/B {}
|
||
|
set b [open_site_prog [list \
|
||
|
"home $testdir/B" \
|
||
|
"local $portB" \
|
||
|
"output $testdir/boutput" \
|
||
|
"remote localhost $mport" \
|
||
|
"open_env" \
|
||
|
"start client"]]
|
||
|
set env [berkdb_env -home $testdir/B]
|
||
|
await_startup_done $env
|
||
|
$env close
|
||
|
|
||
|
# Client C is the one whose behavior is being tested. It has two
|
||
|
# processes. "c" will be the main replication process, and "c2" the
|
||
|
# subordinate process. The initial configuration commands used to set
|
||
|
# up the two processes vary slightly with each test. The variable
|
||
|
# $config contains the name of the proc which will fill out the
|
||
|
# configuration information appropriately for each test variant.
|
||
|
#
|
||
|
puts "\tRepmgr$tnum.c: Start client under test."
|
||
|
make_dbconfig $testdir/C {}
|
||
|
|
||
|
set c2 [list \
|
||
|
"home $testdir/C" \
|
||
|
"local [lindex $ports 3]" \
|
||
|
"output $testdir/c2output" \
|
||
|
"open_env"]
|
||
|
set c [list \
|
||
|
"home $testdir/C" \
|
||
|
"local [lindex $ports 3]" \
|
||
|
"output $testdir/coutput" \
|
||
|
"open_env"]
|
||
|
set lists [repmgr105_$config $c2 $c]
|
||
|
set c2 [lindex $lists 0]
|
||
|
set c [lindex $lists 1]
|
||
|
|
||
|
# Ugly hack: in this one case, the order of opening the two client
|
||
|
# processes has to be reversed.
|
||
|
#
|
||
|
if {$config == "chg_after_open"} {
|
||
|
set c [open_site_prog $c]
|
||
|
set c2 [open_site_prog $c2]
|
||
|
} else {
|
||
|
set c2 [open_site_prog $c2]
|
||
|
set c [open_site_prog $c]
|
||
|
}
|
||
|
puts $c "start client"
|
||
|
gets $c
|
||
|
|
||
|
puts "\tRepmgr$tnum.d: Wait for startup-done at test client."
|
||
|
set env [berkdb_env -home $testdir/C]
|
||
|
await_startup_done $env 27
|
||
|
$env close
|
||
|
|
||
|
puts "\tRepmgr$tnum.e: Check stats to make sure proper peer was used."
|
||
|
set env [berkdb_env -home $testdir/A]
|
||
|
set reqs [stat_field $env rep_stat "Client service requests"]
|
||
|
error_check_good used_client_A [expr {$reqs > 0}] 1
|
||
|
$env close
|
||
|
set env [berkdb_env -home $testdir/B]
|
||
|
set reqs [stat_field $env rep_stat "Client service requests"]
|
||
|
error_check_good didnt_use_b [expr {$reqs == 0}] 1
|
||
|
$env close
|
||
|
|
||
|
puts "\tRepmgr$tnum.f: Clean up."
|
||
|
close $c2
|
||
|
close $c
|
||
|
close $b
|
||
|
close $a
|
||
|
close $m
|
||
|
}
|
||
|
|
||
|
# Scenario 1: client A is the peer; C2 sets B, A; C sets A. For C, this means
|
||
|
# no peer change, but its position in the list changes, requiring some tricky
|
||
|
# shuffling.
|
||
|
#
|
||
|
proc repmgr105_position_chg { c2 c } {
|
||
|
set remote_config [uplevel 1 {list \
|
||
|
"remote localhost $mport" \
|
||
|
"remote localhost $portB" \
|
||
|
"remote -p localhost $portA"}]
|
||
|
set i [lsearch -exact $c2 "open_env"]
|
||
|
|
||
|
# It should be found, in the middle somewhere, or this will break.
|
||
|
set c2 "[lrange $c2 0 [expr $i - 1]] $remote_config [lrange $c2 $i end]"
|
||
|
|
||
|
set remote_config [uplevel 1 {list \
|
||
|
"remote -p localhost $portA" \
|
||
|
"remote localhost $mport"}]
|
||
|
set i [lsearch -exact $c "open_env"]
|
||
|
set c "[lrange $c 0 [expr $i - 1]] $remote_config [lrange $c $i end]"
|
||
|
|
||
|
return [list $c2 $c]
|
||
|
}
|
||
|
|
||
|
# C2 first sets the peer as B, but then C comes along and changes it to A.
|
||
|
#
|
||
|
proc repmgr105_chg_site { c2 c } {
|
||
|
set remote_config [uplevel 1 {list \
|
||
|
"remote localhost $mport" \
|
||
|
"remote -p localhost $portB"}]
|
||
|
set i [lsearch -exact $c2 "open_env"]
|
||
|
|
||
|
# It should be found, in the middle somewhere, or this will break.
|
||
|
set c2 "[lrange $c2 0 [expr $i - 1]] $remote_config [lrange $c2 $i end]"
|
||
|
|
||
|
set remote_config [uplevel 1 {list \
|
||
|
"remote localhost $portB" \
|
||
|
"remote -p localhost $portA" \
|
||
|
"remote localhost $mport"}]
|
||
|
set i [lsearch -exact $c "open_env"]
|
||
|
set c "[lrange $c 0 [expr $i - 1]] $remote_config [lrange $c $i end]"
|
||
|
|
||
|
return [list $c2 $c]
|
||
|
}
|
||
|
|
||
|
# C first sets B as its peer, and creates the env. Then C2 comes along and
|
||
|
# changes it to A. C will have to learn of the change on the fly, rather than
|
||
|
# at env open/join time. Even though the actual order of process creation will
|
||
|
# be reversed (by the caller), we still conform to the convention of putting C2
|
||
|
# first, and then C, in the ordered list.
|
||
|
#
|
||
|
proc repmgr105_chg_after_open { c2 c } {
|
||
|
set remote_config [uplevel 1 {list \
|
||
|
"remote localhost $mport" \
|
||
|
"remote localhost $portB" \
|
||
|
"remote -p localhost $portA"}]
|
||
|
set i [lsearch -exact $c2 "open_env"]
|
||
|
|
||
|
# It should be found, in the middle somewhere, or this will break.
|
||
|
set c2 "[lrange $c2 0 [expr $i - 1]] $remote_config [lrange $c2 $i end]"
|
||
|
|
||
|
set remote_config [uplevel 1 {list \
|
||
|
"remote -p localhost $portB" \
|
||
|
"remote localhost $mport"}]
|
||
|
set i [lsearch -exact $c "open_env"]
|
||
|
set c "[lrange $c 0 [expr $i - 1]] $remote_config [lrange $c $i end]"
|
||
|
|
||
|
return [list $c2 $c]
|
||
|
}
|
||
|
|
||
|
# Nothing especially exotic here, except this exercises a code path where I
|
||
|
# previously discovered a bug.
|
||
|
#
|
||
|
proc repmgr105_set_peer_after_open { c2 c } {
|
||
|
set remote_config [uplevel 1 {subst "remote -p localhost $portA"}]
|
||
|
lappend c $remote_config
|
||
|
return [list $c2 $c]
|
||
|
}
|