1# See the file LICENSE for redistribution information.
2#
3# Copyright (c)-2009 Oracle.  All rights reserved.
4#
5# TEST repmgr027
6# TEST Repmgr recognition of peer setting, across processes.
7# TEST
8# TEST Set up a master and two clients, synchronized with some data.
9# TEST Add a new client, configured to use c2c sync with one of the original
10# TEST clients.  Check stats to make sure the correct c2c peer was used.
11
12proc repmgr027 { } {
13	repmgr027_sub position_chg
14	repmgr027_sub chg_site
15	repmgr027_sub chg_after_open
16	repmgr027_sub set_peer_after_open
17}
18
19proc repmgr027_sub { config } {
20	source ./include.tcl
21
22	set tnum "027"
23	puts "Repmgr$tnum: Repmgr peer, with \"$config\" configuration."
24	set site_prog [setup_site_prog]
25
26	env_cleanup $testdir
27
28	set ports [available_ports 4]
29	set mport [lindex $ports 0]
30	set portA [lindex $ports 1]
31	set portB [lindex $ports 2]
32
33	file mkdir [set masterdir $testdir/MASTER]
34	file mkdir $testdir/A
35	file mkdir $testdir/B
36	file mkdir $testdir/C
37
38	puts "\tRepmgr$tnum.a: Start master, write some data."
39	make_dbconfig $masterdir {{rep_set_nsites 4}}
40	set cmds {
41		"home $masterdir"
42		"local $mport"
43		"output $testdir/moutput"
44		"open_env"
45		"start master"
46		"open_db test.db"
47		"put key1 value1"
48	}
49	set m [open_site_prog [subst $cmds]]
50
51	puts "\tRepmgr$tnum.b:\
52	    Start initial two clients; wait for them to synchronize."
53	# Allowing both A and B to start at the same time, and synchronize
54	# concurrently would make sense.  But it causes very slow performance on
55	# Windows.  Since it's really only client C that's under test here, this
56	# detail doesn't matter.
57	#
58	make_dbconfig $testdir/A {{rep_set_nsites 4}}
59	set a [open_site_prog [list \
60			       "home $testdir/A" \
61			       "local $portA" \
62			       "output $testdir/aoutput" \
63			       "remote localhost $mport" \
64			       "open_env" \
65			       "start client"]]
66	set env [berkdb_env -home $testdir/A]
67	await_startup_done $env
68	$env close
69
70	make_dbconfig $testdir/B {{rep_set_nsites 4}}
71	set b [open_site_prog [list  \
72			       "home $testdir/B" \
73			       "local $portB" \
74			       "output $testdir/boutput" \
75			       "remote localhost $mport" \
76			       "open_env" \
77			       "start client"]]
78	set env [berkdb_env -home $testdir/B]
79	await_startup_done $env
80	$env close
81
82	# Client C is the one whose behavior is being tested.  It has two
83	# processes.  "c" will be the main replication process, and "c2" the
84	# subordinate process.  The initial configuration commands used to set
85	# up the two processes vary slightly with each test.  The variable
86	# $config contains the name of the proc which will fill out the
87	# configuration information appropriately for each test variant.
88	#
89	puts "\tRepmgr$tnum.c: Start client under test."
90	make_dbconfig $testdir/C {{rep_set_nsites 4}}
91
92	set c2 [list \
93		    "home $testdir/C" \
94		    "local [lindex $ports 3]" \
95		    "output $testdir/c2output" \
96		    "open_env"]
97	set c [list \
98		   "home $testdir/C" \
99		   "local [lindex $ports 3]" \
100		   "output $testdir/coutput" \
101		   "open_env"]
102	set lists [repmgr027_$config $c2 $c]
103	set c2 [lindex $lists 0]
104	set c [lindex $lists 1]
105
106	# Ugly hack: in this one case, the order of opening the two client
107	# processes has to be reversed.
108	#
109	if {$config == "chg_after_open"} {
110		set c [open_site_prog $c]
111		set c2 [open_site_prog $c2]
112	} else {
113		set c2 [open_site_prog $c2]
114		set c [open_site_prog $c]
115	}
116	puts $c "start client"
117	gets $c
118
119	puts "\tRepmgr$tnum.d: Wait for startup-done at test client."
120	set env [berkdb_env -home $testdir/C]
121	await_startup_done $env 27
122	$env close
123
124	puts "\tRepmgr$tnum.e: Check stats to make sure proper peer was used."
125	set env [berkdb_env -home $testdir/A]
126	set reqs [stat_field $env rep_stat "Client service requests"]
127	error_check_good used_client_A [expr {$reqs > 0}] 1
128	$env close
129	set env [berkdb_env -home $testdir/B]
130	set reqs [stat_field $env rep_stat "Client service requests"]
131	error_check_good didnt_use_b [expr {$reqs == 0}] 1
132	$env close
133
134	puts "\tRepmgr$tnum.f: Clean up."
135	close $c2
136	close $c
137	close $b
138	close $a
139	close $m
140}
141
142# Scenario 1: client A is the peer; C2 sets B, A; C sets A.  For C, this means
143# no peer change, but its position in the list changes, requiring some tricky
144# shuffling.
145#
146proc repmgr027_position_chg { c2 c } {
147	set remote_config [uplevel 1 {list \
148			   "remote localhost $mport" \
149			   "remote localhost $portB" \
150			   "remote -p localhost $portA"}]
151	set i [lsearch -exact $c2 "open_env"]
152
153	# It should be found, in the middle somewhere, or this will break.
154	set c2 "[lrange $c2 0 [expr $i - 1]] $remote_config [lrange $c2 $i end]"
155
156	set remote_config [uplevel 1 {list \
157			       "remote -p localhost $portA" \
158					  "remote localhost $mport"}]
159	set i [lsearch -exact $c "open_env"]
160	set c "[lrange $c 0 [expr $i - 1]] $remote_config [lrange $c $i end]"
161
162	return [list $c2 $c]
163}
164
165# C2 first sets the peer as B, but then C comes along and changes it to A.
166#
167proc repmgr027_chg_site { c2 c } {
168	set remote_config [uplevel 1 {list \
169			   "remote localhost $mport" \
170			   "remote -p localhost $portB"}]
171	set i [lsearch -exact $c2 "open_env"]
172
173	# It should be found, in the middle somewhere, or this will break.
174	set c2 "[lrange $c2 0 [expr $i - 1]] $remote_config [lrange $c2 $i end]"
175
176	set remote_config [uplevel 1 {list \
177			       "remote -p localhost $portA" \
178					  "remote localhost $mport"}]
179	set i [lsearch -exact $c "open_env"]
180	set c "[lrange $c 0 [expr $i - 1]] $remote_config [lrange $c $i end]"
181
182	return [list $c2 $c]
183}
184
185# C first sets B as its peer, and creates the env.  Then C2 comes along and
186# changes it to A.  C will have to learn of the change on the fly, rather than
187# at env open/join time.  Even though the actual order of process creation will
188# be reversed (by the caller), we still conform to the convention of putting C2
189# first, and then C, in the ordered list.
190#
191proc repmgr027_chg_after_open { c2 c } {
192	set remote_config [uplevel 1 {list \
193			   "remote localhost $mport" \
194			   "remote -p localhost $portA"}]
195	set i [lsearch -exact $c2 "open_env"]
196
197	# It should be found, in the middle somewhere, or this will break.
198	set c2 "[lrange $c2 0 [expr $i - 1]] $remote_config [lrange $c2 $i end]"
199
200	set remote_config [uplevel 1 {list \
201			       "remote -p localhost $portB" \
202					  "remote localhost $mport"}]
203	set i [lsearch -exact $c "open_env"]
204	set c "[lrange $c 0 [expr $i - 1]] $remote_config [lrange $c $i end]"
205
206	return [list $c2 $c]
207}
208
209# Nothing especially exotic here, except this exercises a code path where I
210# previously discovered a bug.
211#
212proc repmgr027_set_peer_after_open { c2 c } {
213	set remote_config [uplevel 1 {subst "remote -p localhost $portA"}]
214	lappend c $remote_config
215	return [list $c2 $c]
216}
217