libdb/test/java/rep/tests/repmgrtests/TestStrictElect.java
2011-09-13 13:44:24 -04:00

246 lines
9.6 KiB
Java

/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2010, 2011 Oracle and/or its affiliates. All rights reserved.
*
*/
package repmgrtests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.junit.Test;
import org.junit.Before;
import com.sleepycat.db.Environment;
import com.sleepycat.db.EnvironmentConfig;
import com.sleepycat.db.EventHandlerAdapter;
import com.sleepycat.db.ReplicationConfig;
import com.sleepycat.db.ReplicationManagerSiteConfig;
import com.sleepycat.db.ReplicationManagerStartPolicy;
import com.sleepycat.db.ReplicationStats;
import com.sleepycat.db.ReplicationTimeoutType;
import com.sleepycat.db.StatsConfig;
import com.sleepycat.db.VerboseConfig;
/**
* Tests for repmgr's handling of elections, and the "strict 2-site"
* config flag.
*/
public class TestStrictElect {
private int[] testPorts;
private int masterPort;
private int clientPort;
private int client2Port;
@Before public void setUp() throws Exception {
testPorts = Util.findAvailablePorts(3);
masterPort = testPorts[0];
clientPort = testPorts[1];
client2Port = testPorts[2];
}
/**
* Verifies that by default in a 2-site group, client takes over
* when master seems to have failed.
*/
@Test public void liberal() throws Exception {
EnvironmentConfig ec = makeBasicConfig();
ReplicationManagerSiteConfig local = new ReplicationManagerSiteConfig("localhost", masterPort);
local.setLocalSite(true);
ec.addReplicationManagerSite(local);
File masterDir = Util.mkdir("master");
Environment master = new Environment(masterDir, ec);
master.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
master.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_MASTER);
ec = makeBasicConfig();
local = new ReplicationManagerSiteConfig("localhost", clientPort);
local.setLocalSite(true);
ec.addReplicationManagerSite(local);
ReplicationManagerSiteConfig remote = new ReplicationManagerSiteConfig("localhost", masterPort);
remote.setBootstrapHelper(true);
ec.addReplicationManagerSite(remote);
MyEventHandler mon = new MyEventHandler();
ec.setEventHandler(mon);
File clientDir = Util.mkdir("client");
Environment client = new Environment(clientDir, ec);
client.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
client.setReplicationTimeout(ReplicationTimeoutType.ELECTION_RETRY, 500000);
client.setReplicationTimeout(ReplicationTimeoutType.ELECTION_TIMEOUT, 500000);
client.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_CLIENT);
mon.await();
// check stats, at this point there should be 0 elections
ReplicationStats stats = client.getReplicationStats(StatsConfig.DEFAULT);
assertTrue(stats.getElections() == 0);
master.close();
// wait a little while
// there should be a couple of failed elections, and we should
// not be master
Thread.sleep(5000);
stats = client.getReplicationStats(StatsConfig.DEFAULT);
assertTrue(stats.getElections() > 2);
assertTrue(stats.getEnvId() != stats.getMaster());
client.close();
}
/**
* Verifies that when the "strict" setting is on, failures
* of a master leaves the group with no master: the client does
* not take over.
*/
@Test public void strict() throws Exception {
EnvironmentConfig ec = makeBasicConfig();
ReplicationManagerSiteConfig local = new ReplicationManagerSiteConfig("localhost", masterPort);
local.setLocalSite(true);
ec.addReplicationManagerSite(local);
File masterDir = Util.mkdir("master");
Environment master = new Environment(masterDir, ec);
master.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_MASTER);
ec = makeBasicConfig();
local = new ReplicationManagerSiteConfig("localhost", clientPort);
local.setLocalSite(true);
ec.addReplicationManagerSite(local);
ReplicationManagerSiteConfig remote = new ReplicationManagerSiteConfig("localhost", masterPort);
remote.setBootstrapHelper(true);
ec.addReplicationManagerSite(remote);
MyEventHandler mon = new MyEventHandler();
ec.setEventHandler(mon);
File clientDir = Util.mkdir("client");
Environment client = new Environment(clientDir, ec);
client.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_CLIENT);
mon.await();
// check stats, at this point there should be 0 elections
ReplicationStats stats = client.getReplicationStats(StatsConfig.DEFAULT);
assertTrue(stats.getElections() == 0);
master.close();
Thread.sleep(3000);
stats = client.getReplicationStats(StatsConfig.DEFAULT);
assertEquals(1, stats.getElections());
assertEquals(ReplicationStats.REP_CLIENT, stats.getStatus());
client.close();
}
/**
* Verifies that the usual strict majority rule is observed in a
* group with more than two sites, regardless of the config setting.
*/
@Test public void threeSite() throws Exception {
EnvironmentConfig ec = makeBasicConfig();
ReplicationManagerSiteConfig local = new ReplicationManagerSiteConfig("localhost", masterPort);
local.setLocalSite(true);
ec.addReplicationManagerSite(local);
File masterDir = Util.mkdir("master");
Environment master = new Environment(masterDir, ec);
master.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
master.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_MASTER);
ec = makeBasicConfig();
local = new ReplicationManagerSiteConfig("localhost", clientPort);
local.setLocalSite(true);
ec.addReplicationManagerSite(local);
ReplicationManagerSiteConfig remote = new ReplicationManagerSiteConfig("localhost", masterPort);
remote.setBootstrapHelper(true);
ec.addReplicationManagerSite(remote);
MyEventHandler mon = new MyEventHandler();
ec.setEventHandler(mon);
File clientDir = Util.mkdir("client");
Environment client = new Environment(clientDir, ec);
client.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
client.setReplicationTimeout(ReplicationTimeoutType.ELECTION_RETRY, 500000);
client.setReplicationTimeout(ReplicationTimeoutType.ELECTION_TIMEOUT, 500000);
client.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_CLIENT);
mon.await();
// Create, start, and sync the 3rd site, just to establish its
// existence (so that the rest of the group recognizes that
// the group size is 3); then shut it down so that the later
// election will fail for insufficient sites.
//
ec = makeBasicConfig();
local = new ReplicationManagerSiteConfig("localhost", client2Port);
local.setLocalSite(true);
ec.addReplicationManagerSite(local);
remote = new ReplicationManagerSiteConfig("localhost", masterPort);
remote.setBootstrapHelper(true);
ec.addReplicationManagerSite(remote);
mon = new MyEventHandler();
ec.setEventHandler(mon);
clientDir = Util.mkdir("client2");
Environment client2 = new Environment(clientDir, ec);
client2.setReplicationConfig(ReplicationConfig.STRICT_2SITE, true);
client2.setReplicationTimeout(ReplicationTimeoutType.ELECTION_RETRY, 500000);
client2.setReplicationTimeout(ReplicationTimeoutType.ELECTION_TIMEOUT, 500000);
client2.replicationManagerStart(1, ReplicationManagerStartPolicy.REP_CLIENT);
mon.await();
client2.close();
// check stats, at this point there should be 0 elections
ReplicationStats stats = client.getReplicationStats(StatsConfig.DEFAULT);
assertTrue(stats.getElections() == 0);
master.close();
// wait a little while
// there should be a couple of failed elections, and we should
// not be master
Thread.sleep(5000);
stats = client.getReplicationStats(StatsConfig.DEFAULT);
assertTrue(stats.getElections() > 2);
assertTrue(stats.getEnvId() != stats.getMaster());
client.close();
}
private EnvironmentConfig makeBasicConfig() throws Exception {
EnvironmentConfig ec = new EnvironmentConfig();
ec.setAllowCreate(true);
ec.setInitializeCache(true);
ec.setInitializeLocking(true);
ec.setInitializeLogging(true);
ec.setInitializeReplication(true);
ec.setTransactional(true);
ec.setThreaded(true);
if (Boolean.getBoolean("VERB_REPLICATION"))
ec.setVerbose(VerboseConfig.REPLICATION, true);
return (ec);
}
class MyEventHandler extends EventHandlerAdapter {
private boolean done = false;
private boolean panic = false;
@Override synchronized public void handleRepStartupDoneEvent() {
done = true;
notifyAll();
}
@Override synchronized public void handlePanicEvent() {
done = true;
panic = true;
notifyAll();
}
synchronized void await() throws Exception {
while (!done) { wait(); }
if (panic)
throw new Exception("aborted by panic in DB");
}
}
}