1 /*-
2  * Copyright (c) 2010, 2020 Oracle and/or its affiliates.  All rights reserved.
3  *
4  * See the file LICENSE for license information.
5  *
6  */
7 
8 package repmgrtests;
9 
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12 
13 import java.io.File;
14 
15 import org.junit.Test;
16 import org.junit.Before;
17 
18 import com.sleepycat.db.Environment;
19 import com.sleepycat.db.EnvironmentConfig;
20 import com.sleepycat.db.ReplicationConfig;
21 import com.sleepycat.db.ReplicationManagerSiteConfig;
22 import com.sleepycat.db.ReplicationManagerStartPolicy;
23 import com.sleepycat.db.ReplicationStats;
24 import com.sleepycat.db.ReplicationTimeoutType;
25 import com.sleepycat.db.StatsConfig;
26 import com.sleepycat.db.VerboseConfig;
27 
28 /**
29  * Tests for repmgr's handling of elections, and the "strict 2-site"
30  * config flag.
31  */
32 public class TestStrictElect {
33     private int[] testPorts;
34     private int masterPort;
35     private int clientPort;
36     private int client2Port;
37 
setUp()38     @Before public void setUp() throws Exception {
39         testPorts = Util.findAvailablePorts(3);
40         masterPort = testPorts[0];
41         clientPort = testPorts[1];
42         client2Port = testPorts[2];
43     }
44 
45     /**
46      * Verifies that by default in a 2-site group, client takes over
47      * when master seems to have failed.
48      */
liberal()49     @Test public void liberal() throws Exception {
50         EnvironmentConfig ec = makeBasicConfig();
51         ReplicationManagerSiteConfig local = new ReplicationManagerSiteConfig("localhost", masterPort);
52         local.setLocalSite(true);
53         ec.addReplicationManagerSite(local);
54         File masterDir = Util.mkdir("master");
55         Environment master = new Environment(masterDir, ec);
56         master.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
57         master.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_MASTER);
58 
59         ec = makeBasicConfig();
60         local = new ReplicationManagerSiteConfig("localhost", clientPort);
61         local.setLocalSite(true);
62         ec.addReplicationManagerSite(local);
63         ReplicationManagerSiteConfig remote = new ReplicationManagerSiteConfig("localhost", masterPort);
64         remote.setBootstrapHelper(true);
65         ec.addReplicationManagerSite(remote);
66         EventHandler mon = new EventHandler();
67         ec.setEventHandler(mon);
68         File clientDir = Util.mkdir("client");
69         Environment client = new Environment(clientDir, ec);
70         client.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
71         client.setReplicationTimeout(ReplicationTimeoutType.ELECTION_RETRY, 500000);
72         client.setReplicationTimeout(ReplicationTimeoutType.ELECTION_TIMEOUT, 500000);
73         client.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_CLIENT);
74 
75         mon.await();
76 
77         // check stats, at this point there should be 0 elections
78         ReplicationStats stats = client.getReplicationStats(StatsConfig.DEFAULT);
79         assertTrue(stats.getElections() == 0);
80 
81         master.close();
82 
83         // wait a little while
84         // there should be a couple of failed elections, and we should
85         // not be master
86         Thread.sleep(5000);
87         stats = client.getReplicationStats(StatsConfig.DEFAULT);
88         assertTrue(stats.getElections() > 2);
89         assertTrue(stats.getEnvId() != stats.getMaster());
90 
91         client.close();
92     }
93 
94     /**
95      * Verifies that when the "strict" setting is on, failures
96      * of a master leaves the group with no master: the client does
97      * not take over.
98      */
strict()99     @Test public void strict() throws Exception {
100         EnvironmentConfig ec = makeBasicConfig();
101         ReplicationManagerSiteConfig local = new ReplicationManagerSiteConfig("localhost", masterPort);
102         local.setLocalSite(true);
103         ec.addReplicationManagerSite(local);
104         File masterDir = Util.mkdir("master");
105         Environment master = new Environment(masterDir, ec);
106         master.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_MASTER);
107 
108         ec = makeBasicConfig();
109         local = new ReplicationManagerSiteConfig("localhost", clientPort);
110         local.setLocalSite(true);
111         ec.addReplicationManagerSite(local);
112         ReplicationManagerSiteConfig remote = new ReplicationManagerSiteConfig("localhost", masterPort);
113         remote.setBootstrapHelper(true);
114         ec.addReplicationManagerSite(remote);
115         EventHandler mon = new EventHandler();
116         ec.setEventHandler(mon);
117         File clientDir = Util.mkdir("client");
118         Environment client = new Environment(clientDir, ec);
119         client.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_CLIENT);
120 
121         mon.await();
122 
123         // check stats, at this point there should be 0 elections
124         ReplicationStats stats = client.getReplicationStats(StatsConfig.DEFAULT);
125         assertTrue(stats.getElections() == 0);
126 
127         master.close();
128 
129         Thread.sleep(3000);
130         stats = client.getReplicationStats(StatsConfig.DEFAULT);
131         assertEquals(1, stats.getElections());
132         assertEquals(ReplicationStats.REP_CLIENT, stats.getStatus());
133 
134         client.close();
135     }
136 
137     /**
138      * Verifies that the usual strict majority rule is observed in a
139      * group with more than two sites, regardless of the config setting.
140      */
threeSite()141     @Test public void threeSite() throws Exception {
142         EnvironmentConfig ec = makeBasicConfig();
143         ReplicationManagerSiteConfig local = new ReplicationManagerSiteConfig("localhost", masterPort);
144         local.setLocalSite(true);
145         ec.addReplicationManagerSite(local);
146         File masterDir = Util.mkdir("master");
147         Environment master = new Environment(masterDir, ec);
148         master.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
149         master.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_MASTER);
150 
151         ec = makeBasicConfig();
152         local = new ReplicationManagerSiteConfig("localhost", clientPort);
153         local.setLocalSite(true);
154         ec.addReplicationManagerSite(local);
155         ReplicationManagerSiteConfig remote = new ReplicationManagerSiteConfig("localhost", masterPort);
156         remote.setBootstrapHelper(true);
157         ec.addReplicationManagerSite(remote);
158         EventHandler mon = new EventHandler();
159         ec.setEventHandler(mon);
160         File clientDir = Util.mkdir("client");
161         Environment client = new Environment(clientDir, ec);
162         client.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
163         client.setReplicationTimeout(ReplicationTimeoutType.ELECTION_RETRY, 500000);
164         client.setReplicationTimeout(ReplicationTimeoutType.ELECTION_TIMEOUT, 500000);
165         client.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_CLIENT);
166 
167         mon.await();
168 
169         // Create, start, and sync the 3rd site, just to establish its
170         // existence (so that the rest of the group recognizes that
171         // the group size is 3); then shut it down so that the later
172         // election will fail for insufficient sites.
173         //
174         ec = makeBasicConfig();
175         local = new ReplicationManagerSiteConfig("localhost", client2Port);
176         local.setLocalSite(true);
177         ec.addReplicationManagerSite(local);
178         remote = new ReplicationManagerSiteConfig("localhost", masterPort);
179         remote.setBootstrapHelper(true);
180         ec.addReplicationManagerSite(remote);
181         mon = new EventHandler();
182         ec.setEventHandler(mon);
183         clientDir = Util.mkdir("client2");
184         Environment client2 = new Environment(clientDir, ec);
185         client2.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
186         client2.setReplicationTimeout(ReplicationTimeoutType.ELECTION_RETRY, 500000);
187         client2.setReplicationTimeout(ReplicationTimeoutType.ELECTION_TIMEOUT, 500000);
188         client2.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_CLIENT);
189 
190         mon.await();
191         client2.close();
192 
193         // check stats, at this point there should be 0 elections
194         ReplicationStats stats = client.getReplicationStats(StatsConfig.DEFAULT);
195         assertTrue(stats.getElections() == 0);
196 
197         master.close();
198 
199         // wait a little while
200         // there should be a couple of failed elections, and we should
201         // not be master
202         Thread.sleep(5000);
203         stats = client.getReplicationStats(StatsConfig.DEFAULT);
204         assertTrue(stats.getElections() > 2);
205         assertTrue(stats.getEnvId() != stats.getMaster());
206 
207         client.close();
208     }
209 
makeBasicConfig()210     private EnvironmentConfig makeBasicConfig() throws Exception {
211         EnvironmentConfig ec = new EnvironmentConfig();
212         ec.setAllowCreate(true);
213         ec.setInitializeCache(true);
214         ec.setInitializeLocking(true);
215         ec.setInitializeLogging(true);
216         ec.setInitializeReplication(true);
217         ec.setTransactional(true);
218         ec.setThreaded(true);
219         if (Boolean.getBoolean("VERB_REPLICATION"))
220             ec.setVerbose(VerboseConfig.REPLICATION, true);
221         return (ec);
222     }
223 }
224