Search in sources :

Example 1 with NewConfigNoQuorum

use of org.apache.zookeeper.KeeperException.NewConfigNoQuorum in project zookeeper by apache.

the class ReconfigFailureCasesTest method testObserverToParticipantConversionFails.

/*
     * Converting an observer into a participant may sometimes fail with a
     * NewConfigNoQuorum exception. This test-case demonstrates the scenario.
     * Current configuration is (A, B, C, D), where A, B and C are participant
     * and D is an observer. Suppose that B has crashed (or never booted). If a
     * reconfiguration is submitted where D is said to become a participant, it
     * will fail with NewConfigNoQuorum since in this configuration, a majority
     * of voters in the new configuration (any 3 voters), must be connected and
     * up-to-date with the leader. An observer cannot acknowledge the history
     * prefix sent during reconfiguration, and therefore it does not count towards
     * these 3 required servers and the reconfiguration will be aborted. In case
     * this happens, a client can achieve the same task by two reconfig commands:
     * first invoke a reconfig to remove D from the configuration and then invoke a
     * second command to add it back as a participant (follower). During the
     * intermediate state D is a non-voting follower and can ACK the state
     * transfer performed during the second reconfig command.
     */
@Test
public void testObserverToParticipantConversionFails() throws Exception {
    ClientBase.setupTestEnv();
    final int SERVER_COUNT = 4;
    int[][] ports = ReconfigRecoveryTest.generatePorts(SERVER_COUNT);
    // generate old config string
    Set<Integer> observers = new HashSet<Integer>();
    observers.add(3);
    StringBuilder sb = ReconfigRecoveryTest.generateConfig(SERVER_COUNT, ports, observers);
    String currentQuorumCfgSection = sb.toString();
    String nextQuorumCfgSection = currentQuorumCfgSection.replace("observer", "participant");
    MainThread[] mt = new MainThread[SERVER_COUNT];
    ZooKeeper[] zk = new ZooKeeper[SERVER_COUNT];
    ZooKeeperAdmin[] zkAdmin = new ZooKeeperAdmin[SERVER_COUNT];
    // Server 0 stays down
    for (int i = 1; i < SERVER_COUNT; i++) {
        mt[i] = new MainThread(i, ports[i][2], currentQuorumCfgSection, true, "100000000");
        mt[i].start();
        zk[i] = new ZooKeeper("127.0.0.1:" + ports[i][2], ClientBase.CONNECTION_TIMEOUT, this);
        zkAdmin[i] = new ZooKeeperAdmin("127.0.0.1:" + ports[i][2], ClientBase.CONNECTION_TIMEOUT, this);
        zkAdmin[i].addAuthInfo("digest", "super:test".getBytes());
    }
    for (int i = 1; i < SERVER_COUNT; i++) {
        assertTrue(ClientBase.waitForServerUp("127.0.0.1:" + ports[i][2], CONNECTION_TIMEOUT * 2), "waiting for server " + i + " being up");
    }
    try {
        zkAdmin[1].reconfigure("", "", nextQuorumCfgSection, -1, new Stat());
        fail("Reconfig should have failed with NewConfigNoQuorum");
    } catch (NewConfigNoQuorum e) {
    // This is expected case since server 0 is down and 3 can't vote
    // (observer in current role) and we need 3 votes from 0, 1, 2, 3,
    } catch (Exception e) {
        fail("Reconfig should have failed with NewConfigNoQuorum");
    }
    // In this scenario to change 3's role to participant we need to remove it first
    ArrayList<String> leavingServers = new ArrayList<String>();
    leavingServers.add("3");
    ReconfigTest.reconfig(zkAdmin[1], null, leavingServers, null, -1);
    ReconfigTest.testNormalOperation(zk[2], zk[3]);
    ReconfigTest.testServerHasConfig(zk[3], null, leavingServers);
    // Now we're adding it back as a participant and everything should work.
    List<String> newMembers = Arrays.asList(nextQuorumCfgSection.split("\n"));
    ReconfigTest.reconfig(zkAdmin[1], null, null, newMembers, -1);
    ReconfigTest.testNormalOperation(zk[2], zk[3]);
    for (int i = 1; i < SERVER_COUNT; i++) {
        ReconfigTest.testServerHasConfig(zk[i], newMembers, null);
    }
    for (int i = 1; i < SERVER_COUNT; i++) {
        zk[i].close();
        zkAdmin[i].close();
        mt[i].shutdown();
    }
}
Also used : ArrayList(java.util.ArrayList) ZooKeeperAdmin(org.apache.zookeeper.admin.ZooKeeperAdmin) KeeperException(org.apache.zookeeper.KeeperException) ZooKeeper(org.apache.zookeeper.ZooKeeper) Stat(org.apache.zookeeper.data.Stat) NewConfigNoQuorum(org.apache.zookeeper.KeeperException.NewConfigNoQuorum) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test) ReconfigTest(org.apache.zookeeper.test.ReconfigTest)

Aggregations

ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 KeeperException (org.apache.zookeeper.KeeperException)1 NewConfigNoQuorum (org.apache.zookeeper.KeeperException.NewConfigNoQuorum)1 ZooKeeper (org.apache.zookeeper.ZooKeeper)1 ZooKeeperAdmin (org.apache.zookeeper.admin.ZooKeeperAdmin)1 Stat (org.apache.zookeeper.data.Stat)1 ReconfigTest (org.apache.zookeeper.test.ReconfigTest)1 Test (org.junit.jupiter.api.Test)1