Search in sources :

Example 6 with RaftClientRpc

use of org.apache.ratis.client.RaftClientRpc in project incubator-ratis by apache.

the class RaftReconfigurationBaseTest method testOverlappedSetConfRequests.

/**
 * Make sure a setConfiguration request is rejected if a configuration change
 * is still in progress (i.e., has not been committed yet).
 */
@Test
public void testOverlappedSetConfRequests() throws Exception {
    LOG.info("Start testOverlappedSetConfRequests");
    // originally 3 peers
    final MiniRaftCluster cluster = getCluster(3);
    try {
        cluster.start();
        RaftTestUtil.waitForLeader(cluster);
        final RaftPeerId leaderId = cluster.getLeader().getId();
        RaftPeer[] newPeers = cluster.addNewPeers(2, true).allPeersInNewConf;
        // delay every peer's logSync so that the setConf request is delayed
        cluster.getPeers().forEach(peer -> logSyncDelay.setDelayMs(peer.getId().toString(), 1000));
        final CountDownLatch latch = new CountDownLatch(1);
        final RaftPeer[] peersInRequest2 = cluster.getPeers().toArray(new RaftPeer[0]);
        AtomicBoolean caughtException = new AtomicBoolean(false);
        new Thread(() -> {
            try (final RaftClient client2 = cluster.createClient(leaderId)) {
                latch.await();
                LOG.info("client2 starts to change conf");
                final RaftClientRpc sender2 = client2.getClientRpc();
                sender2.sendRequest(cluster.newSetConfigurationRequest(client2.getId(), leaderId, peersInRequest2));
            } catch (ReconfigurationInProgressException e) {
                caughtException.set(true);
            } catch (Exception e) {
                LOG.warn("Got unexpected exception when client2 changes conf", e);
            }
        }).start();
        AtomicBoolean confChanged = new AtomicBoolean(false);
        new Thread(() -> {
            try (final RaftClient client1 = cluster.createClient(leaderId)) {
                LOG.info("client1 starts to change conf");
                confChanged.set(client1.setConfiguration(newPeers).isSuccess());
            } catch (IOException e) {
                LOG.warn("Got unexpected exception when client1 changes conf", e);
            }
        }).start();
        Thread.sleep(100);
        latch.countDown();
        for (int i = 0; i < 10 && !confChanged.get(); i++) {
            Thread.sleep(1000);
        }
        Assert.assertTrue(confChanged.get());
        Assert.assertTrue(caughtException.get());
    } finally {
        logSyncDelay.clear();
        cluster.shutdown();
    }
}
Also used : IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) IOException(java.io.IOException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MiniRaftCluster(org.apache.ratis.MiniRaftCluster) RaftClient(org.apache.ratis.client.RaftClient) RaftClientRpc(org.apache.ratis.client.RaftClientRpc) Test(org.junit.Test) BaseTest(org.apache.ratis.BaseTest)

Example 7 with RaftClientRpc

use of org.apache.ratis.client.RaftClientRpc in project incubator-ratis by apache.

the class RaftReconfigurationBaseTest method testRevertConfigurationChange.

/**
 * Test a scenario where the follower truncates its log entries which causes
 * configuration change.
 */
@Test
public void testRevertConfigurationChange() throws Exception {
    LOG.info("Start testRevertConfigurationChange");
    RaftLog log2 = null;
    final MiniRaftCluster cluster = getCluster(5);
    try {
        cluster.start();
        RaftTestUtil.waitForLeader(cluster);
        final RaftServerImpl leader = cluster.getLeader();
        final RaftPeerId leaderId = leader.getId();
        final RaftLog log = leader.getState().getLog();
        log2 = log;
        Thread.sleep(1000);
        // we block the incoming msg for the leader and block its requests to
        // followers, so that we force the leader change and the old leader will
        // not know
        LOG.info("start blocking the leader");
        BlockRequestHandlingInjection.getInstance().blockReplier(leaderId.toString());
        cluster.setBlockRequestsFrom(leaderId.toString(), true);
        PeerChanges change = cluster.removePeers(1, false, new ArrayList<>());
        AtomicBoolean gotNotLeader = new AtomicBoolean(false);
        final Thread clientThread = new Thread(() -> {
            try (final RaftClient client = cluster.createClient(leaderId)) {
                LOG.info("client starts to change conf");
                final RaftClientRpc sender = client.getClientRpc();
                RaftClientReply reply = sender.sendRequest(cluster.newSetConfigurationRequest(client.getId(), leaderId, change.allPeersInNewConf));
                if (reply.getNotLeaderException() != null) {
                    gotNotLeader.set(true);
                }
            } catch (IOException e) {
                LOG.warn("Got unexpected exception when client1 changes conf", e);
            }
        });
        clientThread.start();
        // find CONFIGURATIONENTRY, there may be NOOP before and after it.
        final long confIndex = JavaUtils.attempt(() -> {
            final long last = log.getLastEntryTermIndex().getIndex();
            for (long i = 1; i <= last; i++) {
                if (log.get(i).getLogEntryBodyCase() == CONFIGURATIONENTRY) {
                    return i;
                }
            }
            throw new Exception("CONFIGURATIONENTRY not found: last=" + last);
        }, 10, 500, "confIndex", LOG);
        // wait till the old leader persist the new conf
        JavaUtils.attempt(() -> log.getLatestFlushedIndex() >= confIndex, 10, 500L, "FLUSH", LOG);
        final long committed = log.getLastCommittedIndex();
        Assert.assertTrue(committed < confIndex);
        // unblock the old leader
        BlockRequestHandlingInjection.getInstance().unblockReplier(leaderId.toString());
        cluster.setBlockRequestsFrom(leaderId.toString(), false);
        // the client should get NotLeaderException
        clientThread.join(5000);
        Assert.assertTrue(gotNotLeader.get());
        // the old leader should have truncated the setConf from the log
        JavaUtils.attempt(() -> log.getLastCommittedIndex() >= confIndex, 10, 500L, "COMMIT", LOG);
        Assert.assertEquals(NOOP, log.get(confIndex).getLogEntryBodyCase());
        log2 = null;
    } finally {
        RaftStorageTestUtils.printLog(log2, s -> LOG.info(s));
        cluster.shutdown();
    }
}
Also used : IOException(java.io.IOException) IOException(java.io.IOException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MiniRaftCluster(org.apache.ratis.MiniRaftCluster) PeerChanges(org.apache.ratis.MiniRaftCluster.PeerChanges) RaftClient(org.apache.ratis.client.RaftClient) RaftLog(org.apache.ratis.server.storage.RaftLog) RaftClientRpc(org.apache.ratis.client.RaftClientRpc) Test(org.junit.Test) BaseTest(org.apache.ratis.BaseTest)

Example 8 with RaftClientRpc

use of org.apache.ratis.client.RaftClientRpc in project incubator-ratis by apache.

the class RaftExceptionBaseTest method testHandleNotLeaderException.

private void testHandleNotLeaderException(boolean killNewLeader) throws Exception {
    RaftTestUtil.waitForLeader(cluster);
    final RaftPeerId leaderId = cluster.getLeader().getId();
    final RaftClient client = cluster.createClient(leaderId);
    RaftClientReply reply = client.send(new SimpleMessage("m1"));
    Assert.assertTrue(reply.isSuccess());
    // enforce leader change
    RaftPeerId newLeader = RaftTestUtil.changeLeader(cluster, leaderId);
    if (killNewLeader) {
        // kill the new leader
        cluster.killServer(newLeader);
    }
    RaftClientRpc rpc = client.getClientRpc();
    reply = null;
    for (int i = 0; reply == null && i < 10; i++) {
        try {
            reply = rpc.sendRequest(cluster.newRaftClientRequest(ClientId.randomId(), leaderId, new SimpleMessage("m2")));
        } catch (IOException ignored) {
            Thread.sleep(1000);
        }
    }
    Assert.assertNotNull(reply);
    Assert.assertFalse(reply.isSuccess());
    final NotLeaderException nle = reply.getNotLeaderException();
    Objects.requireNonNull(nle);
    Assert.assertEquals(newLeader, nle.getSuggestedLeader().getId());
    reply = client.send(new SimpleMessage("m3"));
    Assert.assertTrue(reply.isSuccess());
    client.close();
}
Also used : SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) IOException(java.io.IOException) RaftClient(org.apache.ratis.client.RaftClient) RaftClientRpc(org.apache.ratis.client.RaftClientRpc)

Example 9 with RaftClientRpc

use of org.apache.ratis.client.RaftClientRpc in project incubator-ratis by apache.

the class RaftReconfigurationBaseTest method testLeaderNotReadyException.

/**
 * Delay the commit of the leader placeholder log entry and see if the client
 * can correctly receive and handle the LeaderNotReadyException.
 */
@Test
public void testLeaderNotReadyException() throws Exception {
    LOG.info("Start testLeaderNotReadyException");
    final MiniRaftCluster cluster = getCluster(1).initServers();
    final RaftPeerId leaderId = cluster.getPeers().iterator().next().getId();
    try {
        // delay 1s for each logSync call
        cluster.getPeers().forEach(peer -> leaderPlaceHolderDelay.setDelayMs(peer.getId().toString(), 2000));
        cluster.start();
        AtomicBoolean caughtNotReady = new AtomicBoolean(false);
        AtomicBoolean success = new AtomicBoolean(false);
        new Thread(() -> {
            final RaftClient client = cluster.createClient(leaderId);
            final RaftClientRpc sender = client.getClientRpc();
            final RaftClientRequest request = cluster.newRaftClientRequest(client.getId(), leaderId, new SimpleMessage("test"));
            while (!success.get()) {
                try {
                    RaftClientReply reply = sender.sendRequest(request);
                    success.set(reply.isSuccess());
                } catch (LeaderNotReadyException e) {
                    LOG.info("Hit LeaderNotReadyException", e);
                    caughtNotReady.set(true);
                } catch (IOException e) {
                    LOG.info("Hit other IOException", e);
                }
                if (!success.get()) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException ignored) {
                    }
                }
            }
        }).start();
        RaftTestUtil.waitForLeader(cluster);
        for (int i = 0; !success.get() && i < 5; i++) {
            Thread.sleep(1000);
        }
        Assert.assertTrue(success.get());
        Assert.assertTrue(caughtNotReady.get());
    } finally {
        leaderPlaceHolderDelay.clear();
        cluster.shutdown();
    }
}
Also used : SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) IOException(java.io.IOException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MiniRaftCluster(org.apache.ratis.MiniRaftCluster) RaftClient(org.apache.ratis.client.RaftClient) RaftClientRpc(org.apache.ratis.client.RaftClientRpc) Test(org.junit.Test) BaseTest(org.apache.ratis.BaseTest)

Example 10 with RaftClientRpc

use of org.apache.ratis.client.RaftClientRpc in project incubator-ratis by apache.

the class RaftReconfigurationBaseTest method testReconfTimeout.

@Test
public void testReconfTimeout() throws Exception {
    LOG.info("Start testReconfTimeout");
    // originally 3 peers
    final MiniRaftCluster cluster = getCluster(3);
    cluster.start();
    try {
        RaftTestUtil.waitForLeader(cluster);
        final RaftPeerId leaderId = cluster.getLeader().getId();
        final RaftClient client = cluster.createClient(leaderId);
        PeerChanges c1 = cluster.addNewPeers(2, false);
        LOG.info("Start changing the configuration: {}", asList(c1.allPeersInNewConf));
        Assert.assertFalse(cluster.getLeader().getRaftConf().isTransitional());
        final RaftClientRpc sender = client.getClientRpc();
        final SetConfigurationRequest request = cluster.newSetConfigurationRequest(client.getId(), leaderId, c1.allPeersInNewConf);
        try {
            sender.sendRequest(request);
            Assert.fail("did not get expected exception");
        } catch (IOException e) {
            Assert.assertTrue("Got exception " + e, e instanceof ReconfigurationTimeoutException);
        }
        // the two new peers have not started yet, the bootstrapping must timeout
        LOG.info(cluster.printServers());
        // state so that we still get timeout instead of in-progress exception
        try {
            sender.sendRequest(request);
            Assert.fail("did not get expected exception");
        } catch (IOException e) {
            Assert.assertTrue("Got exception " + e, e instanceof ReconfigurationTimeoutException);
        }
        // start the two new peers
        LOG.info("Start new peers");
        for (RaftPeer np : c1.newPeers) {
            cluster.startServer(np.getId());
        }
        Assert.assertTrue(client.setConfiguration(c1.allPeersInNewConf).isSuccess());
        client.close();
    } finally {
        cluster.shutdown();
    }
}
Also used : MiniRaftCluster(org.apache.ratis.MiniRaftCluster) PeerChanges(org.apache.ratis.MiniRaftCluster.PeerChanges) IOException(java.io.IOException) RaftClient(org.apache.ratis.client.RaftClient) RaftClientRpc(org.apache.ratis.client.RaftClientRpc) Test(org.junit.Test) BaseTest(org.apache.ratis.BaseTest)

Aggregations

RaftClient (org.apache.ratis.client.RaftClient)10 RaftClientRpc (org.apache.ratis.client.RaftClientRpc)10 Test (org.junit.Test)9 IOException (java.io.IOException)7 SimpleMessage (org.apache.ratis.RaftTestUtil.SimpleMessage)7 BaseTest (org.apache.ratis.BaseTest)4 MiniRaftCluster (org.apache.ratis.MiniRaftCluster)4 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)3 PeerChanges (org.apache.ratis.MiniRaftCluster.PeerChanges)3 ParameterizedBaseTest (org.apache.ratis.examples.ParameterizedBaseTest)2 RaftClientReply (org.apache.ratis.protocol.RaftClientReply)2 RaftClientRequest (org.apache.ratis.protocol.RaftClientRequest)2 RaftPeerId (org.apache.ratis.protocol.RaftPeerId)2 RaftServerImpl (org.apache.ratis.server.impl.RaftServerImpl)2 CountDownLatch (java.util.concurrent.CountDownLatch)1 RaftPeer (org.apache.ratis.protocol.RaftPeer)1 RetryCache (org.apache.ratis.server.impl.RetryCache)1 RaftLog (org.apache.ratis.server.storage.RaftLog)1