Search in sources :

Example 1 with SimpleStateMachine4Testing

use of org.apache.ratis.statemachine.SimpleStateMachine4Testing in project incubator-ratis by apache.

the class ServerRestartTests method runTestRestartCommitIndex.

void runTestRestartCommitIndex(MiniRaftCluster cluster) throws Exception {
    final SimpleMessage[] messages = SimpleMessage.create(100);
    final List<CompletableFuture<Void>> futures = new ArrayList<>(messages.length);
    for (int i = 0; i < messages.length; i++) {
        final CompletableFuture<Void> f = new CompletableFuture<>();
        futures.add(f);
        final SimpleMessage m = messages[i];
        new Thread(() -> {
            try (final RaftClient client = cluster.createClient()) {
                Assert.assertTrue(client.io().send(m).isSuccess());
            } catch (IOException e) {
                throw new IllegalStateException("Failed to send " + m, e);
            }
            f.complete(null);
        }).start();
    }
    JavaUtils.allOf(futures).get();
    final List<RaftPeerId> ids = new ArrayList<>();
    final RaftServer.Division leader = cluster.getLeader();
    final RaftLog leaderLog = leader.getRaftLog();
    final RaftPeerId leaderId = leader.getId();
    ids.add(leaderId);
    RaftTestUtil.getStateMachineLogEntries(leaderLog);
    // check that the last metadata entry is written to the log
    JavaUtils.attempt(() -> assertLastLogEntry(leader), 20, HUNDRED_MILLIS, "leader last metadata entry", LOG);
    final long lastIndex = leaderLog.getLastEntryTermIndex().getIndex();
    LOG.info("{}: leader lastIndex={}", leaderId, lastIndex);
    final LogEntryProto lastEntry = leaderLog.get(lastIndex);
    LOG.info("{}: leader lastEntry entry[{}] = {}", leaderId, lastIndex, LogProtoUtils.toLogEntryString(lastEntry));
    final long loggedCommitIndex = lastEntry.getMetadataEntry().getCommitIndex();
    final LogEntryProto lastCommittedEntry = leaderLog.get(loggedCommitIndex);
    LOG.info("{}: leader lastCommittedEntry = entry[{}] = {}", leaderId, loggedCommitIndex, LogProtoUtils.toLogEntryString(lastCommittedEntry));
    final SimpleStateMachine4Testing leaderStateMachine = SimpleStateMachine4Testing.get(leader);
    final TermIndex lastAppliedTermIndex = leaderStateMachine.getLastAppliedTermIndex();
    LOG.info("{}: leader lastAppliedTermIndex = {}", leaderId, lastAppliedTermIndex);
    // check follower logs
    for (RaftServer.Division s : cluster.iterateDivisions()) {
        if (!s.getId().equals(leaderId)) {
            ids.add(s.getId());
            JavaUtils.attempt(() -> RaftTestUtil.assertSameLog(leaderLog, s.getRaftLog()), 10, HUNDRED_MILLIS, "assertRaftLog-" + s.getId(), LOG);
        }
    }
    // take snapshot and truncate last (metadata) entry
    leaderStateMachine.takeSnapshot();
    leaderLog.truncate(lastIndex);
    // kill all servers
    ids.forEach(cluster::killServer);
    // Restart and kill servers one by one so that they won't talk to each other.
    for (RaftPeerId id : ids) {
        cluster.restartServer(id, false);
        final RaftServer.Division server = cluster.getDivision(id);
        final RaftLog raftLog = server.getRaftLog();
        JavaUtils.attemptRepeatedly(() -> {
            Assert.assertTrue(raftLog.getLastCommittedIndex() >= loggedCommitIndex);
            return null;
        }, 10, HUNDRED_MILLIS, id + "(commitIndex >= loggedCommitIndex)", LOG);
        JavaUtils.attemptRepeatedly(() -> {
            Assert.assertTrue(server.getInfo().getLastAppliedIndex() >= loggedCommitIndex);
            return null;
        }, 10, HUNDRED_MILLIS, id + "(lastAppliedIndex >= loggedCommitIndex)", LOG);
        LOG.info("{}: commitIndex={}, lastAppliedIndex={}", id, raftLog.getLastCommittedIndex(), server.getInfo().getLastAppliedIndex());
        cluster.killServer(id);
    }
}
Also used : SimpleStateMachine4Testing(org.apache.ratis.statemachine.SimpleStateMachine4Testing) SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) ArrayList(java.util.ArrayList) RaftLogIOException(org.apache.ratis.server.raftlog.RaftLogIOException) IOException(java.io.IOException) TermIndex(org.apache.ratis.server.protocol.TermIndex) CompletableFuture(java.util.concurrent.CompletableFuture) LogEntryProto(org.apache.ratis.proto.RaftProtos.LogEntryProto) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) RaftClient(org.apache.ratis.client.RaftClient) RaftLog(org.apache.ratis.server.raftlog.RaftLog) TestSegmentedRaftLog(org.apache.ratis.server.raftlog.segmented.TestSegmentedRaftLog)

Example 2 with SimpleStateMachine4Testing

use of org.apache.ratis.statemachine.SimpleStateMachine4Testing in project incubator-ratis by apache.

the class ServerRestartTests method assertLastLogEntry.

static void assertLastLogEntry(RaftServer.Division server) throws RaftLogIOException {
    final RaftLog raftLog = server.getRaftLog();
    final long lastIndex = raftLog.getLastEntryTermIndex().getIndex();
    final LogEntryProto lastEntry = raftLog.get(lastIndex);
    Assert.assertTrue(lastEntry.hasMetadataEntry());
    final long loggedCommitIndex = lastEntry.getMetadataEntry().getCommitIndex();
    final LogEntryProto lastCommittedEntry = raftLog.get(loggedCommitIndex);
    Assert.assertTrue(lastCommittedEntry.hasStateMachineLogEntry());
    final SimpleStateMachine4Testing leaderStateMachine = SimpleStateMachine4Testing.get(server);
    final TermIndex lastAppliedTermIndex = leaderStateMachine.getLastAppliedTermIndex();
    Assert.assertEquals(lastCommittedEntry.getTerm(), lastAppliedTermIndex.getTerm());
    Assert.assertTrue(lastCommittedEntry.getIndex() <= lastAppliedTermIndex.getIndex());
}
Also used : SimpleStateMachine4Testing(org.apache.ratis.statemachine.SimpleStateMachine4Testing) LogEntryProto(org.apache.ratis.proto.RaftProtos.LogEntryProto) RaftLog(org.apache.ratis.server.raftlog.RaftLog) TestSegmentedRaftLog(org.apache.ratis.server.raftlog.segmented.TestSegmentedRaftLog) TermIndex(org.apache.ratis.server.protocol.TermIndex)

Example 3 with SimpleStateMachine4Testing

use of org.apache.ratis.statemachine.SimpleStateMachine4Testing in project incubator-ratis by apache.

the class TestRaftServerWithGrpc method runTestLeaderRestart.

void runTestLeaderRestart(MiniRaftClusterWithGrpc cluster) throws Exception {
    final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
    try (final RaftClient client = cluster.createClient()) {
        // send a request to make sure leader is ready
        final CompletableFuture<RaftClientReply> f = client.async().send(new SimpleMessage("testing"));
        Assert.assertTrue(f.get().isSuccess());
    }
    try (final RaftClient client = cluster.createClient()) {
        final RaftClientRpc rpc = client.getClientRpc();
        final AtomicLong seqNum = new AtomicLong();
        {
            // send a request using rpc directly
            final RaftClientRequest request = newRaftClientRequest(client, leader.getId(), seqNum.incrementAndGet());
            final CompletableFuture<RaftClientReply> f = rpc.sendRequestAsync(request);
            Assert.assertTrue(f.get().isSuccess());
        }
        // send another request which will be blocked
        final SimpleStateMachine4Testing stateMachine = SimpleStateMachine4Testing.get(leader);
        stateMachine.blockStartTransaction();
        final RaftClientRequest requestBlocked = newRaftClientRequest(client, leader.getId(), seqNum.incrementAndGet());
        final CompletableFuture<RaftClientReply> futureBlocked = rpc.sendRequestAsync(requestBlocked);
        // change leader
        RaftTestUtil.changeLeader(cluster, leader.getId());
        Assert.assertNotEquals(RaftPeerRole.LEADER, leader.getInfo().getCurrentRole());
        // the blocked request should fail
        testFailureCase("request should fail", futureBlocked::get, ExecutionException.class, AlreadyClosedException.class);
        stateMachine.unblockStartTransaction();
        // send one more request which should timeout.
        final RaftClientRequest requestTimeout = newRaftClientRequest(client, leader.getId(), seqNum.incrementAndGet());
        rpc.handleException(leader.getId(), new Exception(), true);
        final CompletableFuture<RaftClientReply> f = rpc.sendRequestAsync(requestTimeout);
        testFailureCase("request should timeout", f::get, ExecutionException.class, TimeoutIOException.class);
    }
}
Also used : SimpleStateMachine4Testing(org.apache.ratis.statemachine.SimpleStateMachine4Testing) RaftServer(org.apache.ratis.server.RaftServer) SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) OverlappingFileLockException(java.nio.channels.OverlappingFileLockException) TimeoutIOException(org.apache.ratis.protocol.exceptions.TimeoutIOException) AlreadyClosedException(org.apache.ratis.protocol.exceptions.AlreadyClosedException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) AtomicLong(java.util.concurrent.atomic.AtomicLong) CompletableFuture(java.util.concurrent.CompletableFuture) RaftClientRequest(org.apache.ratis.protocol.RaftClientRequest) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) RaftClient(org.apache.ratis.client.RaftClient) RaftClientRpc(org.apache.ratis.client.RaftClientRpc)

Example 4 with SimpleStateMachine4Testing

use of org.apache.ratis.statemachine.SimpleStateMachine4Testing in project incubator-ratis by apache.

the class RaftAsyncTests method runTestAsyncRequestSemaphore.

void runTestAsyncRequestSemaphore(CLUSTER cluster) throws Exception {
    waitForLeader(cluster);
    int numMessages = RaftClientConfigKeys.Async.outstandingRequestsMax(getProperties());
    CompletableFuture[] futures = new CompletableFuture[numMessages + 1];
    final SimpleMessage[] messages = SimpleMessage.create(numMessages);
    try (final RaftClient client = cluster.createClient()) {
        // Set blockTransaction flag so that transaction blocks
        StreamSupport.stream(cluster.getServers().spliterator(), false).map(cluster::getDivision).map(SimpleStateMachine4Testing::get).forEach(SimpleStateMachine4Testing::blockStartTransaction);
        // Send numMessages which are blocked and do not release the client semaphore permits
        AtomicInteger blockedRequestsCount = new AtomicInteger();
        for (int i = 0; i < numMessages; i++) {
            blockedRequestsCount.getAndIncrement();
            futures[i] = client.async().send(messages[i]);
            blockedRequestsCount.decrementAndGet();
        }
        Assert.assertEquals(0, blockedRequestsCount.get());
        futures[numMessages] = CompletableFuture.supplyAsync(() -> {
            blockedRequestsCount.incrementAndGet();
            client.async().send(new SimpleMessage("n1"));
            blockedRequestsCount.decrementAndGet();
            return null;
        });
        // Allow the last msg to be sent
        while (blockedRequestsCount.get() != 1) {
            Thread.sleep(1000);
        }
        Assert.assertEquals(1, blockedRequestsCount.get());
        // Since all semaphore permits are acquired the last message sent is in queue
        RaftClientTestUtil.assertAsyncRequestSemaphore(client, 0, 1);
        // Unset the blockTransaction flag so that semaphore permits can be released
        StreamSupport.stream(cluster.getServers().spliterator(), false).map(cluster::getDivision).map(SimpleStateMachine4Testing::get).forEach(SimpleStateMachine4Testing::unblockStartTransaction);
        for (int i = 0; i <= numMessages; i++) {
            futures[i].join();
        }
        Assert.assertEquals(0, blockedRequestsCount.get());
    }
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) SimpleStateMachine4Testing(org.apache.ratis.statemachine.SimpleStateMachine4Testing) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) RaftClient(org.apache.ratis.client.RaftClient)

Example 5 with SimpleStateMachine4Testing

use of org.apache.ratis.statemachine.SimpleStateMachine4Testing in project incubator-ratis by apache.

the class RaftAsyncTests method runTestAppendEntriesTimeout.

void runTestAppendEntriesTimeout(CLUSTER cluster) throws Exception {
    LOG.info("Running testAppendEntriesTimeout");
    final TimeDuration oldExpiryTime = RaftServerConfigKeys.RetryCache.expiryTime(getProperties());
    RaftServerConfigKeys.RetryCache.setExpiryTime(getProperties(), TimeDuration.valueOf(20, TimeUnit.SECONDS));
    waitForLeader(cluster);
    long time = System.currentTimeMillis();
    long waitTime = 5000;
    try (final RaftClient client = cluster.createClient()) {
        // block append requests
        cluster.getServerAliveStream().filter(impl -> !impl.getInfo().isLeader()).map(SimpleStateMachine4Testing::get).forEach(SimpleStateMachine4Testing::blockWriteStateMachineData);
        CompletableFuture<RaftClientReply> replyFuture = client.async().send(new SimpleMessage("abc"));
        Thread.sleep(waitTime);
        // replyFuture should not be completed until append request is unblocked.
        Assert.assertFalse(replyFuture.isDone());
        // unblock append request.
        cluster.getServerAliveStream().filter(impl -> !impl.getInfo().isLeader()).map(SimpleStateMachine4Testing::get).forEach(SimpleStateMachine4Testing::unblockWriteStateMachineData);
        Assert.assertTrue(replyFuture.get().isSuccess());
        Assert.assertTrue(System.currentTimeMillis() - time > waitTime);
    }
    // reset for the other tests
    RaftServerConfigKeys.RetryCache.setExpiryTime(getProperties(), oldExpiryTime);
}
Also used : SimpleStateMachine4Testing(org.apache.ratis.statemachine.SimpleStateMachine4Testing) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) TimeDuration(org.apache.ratis.util.TimeDuration) RaftClient(org.apache.ratis.client.RaftClient)

Aggregations

SimpleStateMachine4Testing (org.apache.ratis.statemachine.SimpleStateMachine4Testing)11 RaftClient (org.apache.ratis.client.RaftClient)8 SimpleMessage (org.apache.ratis.RaftTestUtil.SimpleMessage)6 RaftClientReply (org.apache.ratis.protocol.RaftClientReply)6 CompletableFuture (java.util.concurrent.CompletableFuture)4 IOException (java.io.IOException)3 LogEntryProto (org.apache.ratis.proto.RaftProtos.LogEntryProto)3 RaftLog (org.apache.ratis.server.raftlog.RaftLog)3 Test (org.junit.Test)3 ArrayList (java.util.ArrayList)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 RaftClientRequest (org.apache.ratis.protocol.RaftClientRequest)2 RaftServer (org.apache.ratis.server.RaftServer)2 TermIndex (org.apache.ratis.server.protocol.TermIndex)2 TestSegmentedRaftLog (org.apache.ratis.server.raftlog.segmented.TestSegmentedRaftLog)2 TimeDuration (org.apache.ratis.util.TimeDuration)2 Gauge (com.codahale.metrics.Gauge)1 OverlappingFileLockException (java.nio.channels.OverlappingFileLockException)1 ExecutionException (java.util.concurrent.ExecutionException)1 TimeUnit (java.util.concurrent.TimeUnit)1