Search in sources :

Example 16 with SimpleMessage

use of org.apache.ratis.RaftTestUtil.SimpleMessage 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 17 with SimpleMessage

use of org.apache.ratis.RaftTestUtil.SimpleMessage in project incubator-ratis by apache.

the class ServerRestartTests method runTestRestartWithCorruptedLogEntry.

private void runTestRestartWithCorruptedLogEntry(CLUSTER cluster) throws Exception {
    // this is the only server
    final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
    final RaftPeerId id = leader.getId();
    // send a few messages
    final SimpleMessage[] messages = SimpleMessage.create(10);
    final SimpleMessage lastMessage = messages[messages.length - 1];
    try (final RaftClient client = cluster.createClient()) {
        for (SimpleMessage m : messages) {
            Assert.assertTrue(client.io().send(m).isSuccess());
        }
        // assert that the last message exists
        Assert.assertTrue(client.io().sendReadOnly(lastMessage).isSuccess());
    }
    final RaftLog log = leader.getRaftLog();
    final long size = TestSegmentedRaftLog.getOpenSegmentSize(log);
    leader.getRaftServer().close();
    // corrupt the log
    final File openLogFile = JavaUtils.attemptRepeatedly(() -> getOpenLogFile(leader), 10, HUNDRED_MILLIS, id + "-getOpenLogFile", LOG);
    try (final RandomAccessFile raf = new RandomAccessFile(openLogFile, "rw")) {
        final long mid = size / 2;
        raf.seek(mid);
        for (long i = mid; i < size; i++) {
            raf.write(0);
        }
    }
    // after the log is corrupted and the server is restarted, the last entry should no longer exist.
    cluster.restartServer(id, false);
    testFailureCase("last-entry-not-found", () -> {
        try (final RaftClient client = cluster.createClient()) {
            client.io().sendReadOnly(lastMessage);
        }
    }, StateMachineException.class, IndexOutOfBoundsException.class);
}
Also used : RandomAccessFile(java.io.RandomAccessFile) SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) RandomAccessFile(java.io.RandomAccessFile) File(java.io.File) RaftClient(org.apache.ratis.client.RaftClient) RaftLog(org.apache.ratis.server.raftlog.RaftLog) TestSegmentedRaftLog(org.apache.ratis.server.raftlog.segmented.TestSegmentedRaftLog)

Example 18 with SimpleMessage

use of org.apache.ratis.RaftTestUtil.SimpleMessage in project incubator-ratis by apache.

the class RaftAsyncTests method runTestStaleReadAsync.

void runTestStaleReadAsync(CLUSTER cluster) throws Exception {
    final int numMesssages = 10;
    try (RaftClient client = cluster.createClient()) {
        RaftTestUtil.waitForLeader(cluster);
        // submit some messages
        final List<CompletableFuture<RaftClientReply>> futures = new ArrayList<>();
        for (int i = 0; i < numMesssages; i++) {
            final String s = "" + i;
            LOG.info("sendAsync " + s);
            futures.add(client.async().send(new SimpleMessage(s)));
        }
        Assert.assertEquals(numMesssages, futures.size());
        final List<RaftClientReply> replies = new ArrayList<>();
        for (CompletableFuture<RaftClientReply> f : futures) {
            final RaftClientReply r = f.join();
            Assert.assertTrue(r.isSuccess());
            replies.add(r);
        }
        futures.clear();
        // Use a follower with the max commit index
        final RaftClientReply lastWriteReply = replies.get(replies.size() - 1);
        final RaftPeerId leader = lastWriteReply.getServerId();
        LOG.info("leader = " + leader);
        final Collection<CommitInfoProto> commitInfos = lastWriteReply.getCommitInfos();
        LOG.info("commitInfos = " + commitInfos);
        final CommitInfoProto followerCommitInfo = commitInfos.stream().filter(info -> !RaftPeerId.valueOf(info.getServer().getId()).equals(leader)).max(Comparator.comparing(CommitInfoProto::getCommitIndex)).get();
        final RaftPeerId follower = RaftPeerId.valueOf(followerCommitInfo.getServer().getId());
        final long followerCommitIndex = followerCommitInfo.getCommitIndex();
        LOG.info("max follower = {}, commitIndex = {}", follower, followerCommitIndex);
        // test a failure case
        testFailureCaseAsync("sendStaleReadAsync(..) with a larger commit index", () -> client.async().sendStaleRead(new SimpleMessage("" + Long.MAX_VALUE), followerCommitInfo.getCommitIndex(), follower), StateMachineException.class, IndexOutOfBoundsException.class);
        // test sendStaleReadAsync
        for (int i = 0; i < numMesssages; i++) {
            final RaftClientReply reply = replies.get(i);
            final String query = "" + i;
            LOG.info("query=" + query + ", reply=" + reply);
            final Message message = new SimpleMessage(query);
            final CompletableFuture<RaftClientReply> readFuture = client.async().sendReadOnly(message);
            futures.add(readFuture.thenCompose(r -> {
                if (reply.getLogIndex() <= followerCommitIndex) {
                    LOG.info("sendStaleReadAsync, query=" + query);
                    return client.async().sendStaleRead(message, followerCommitIndex, follower);
                } else {
                    return CompletableFuture.completedFuture(null);
                }
            }).thenApply(staleReadReply -> {
                if (staleReadReply == null) {
                    return null;
                }
                final ByteString expected = readFuture.join().getMessage().getContent();
                final ByteString computed = staleReadReply.getMessage().getContent();
                try {
                    LOG.info("query " + query + " returns " + LogEntryProto.parseFrom(expected).getStateMachineLogEntry().getLogData().toStringUtf8());
                } catch (InvalidProtocolBufferException e) {
                    throw new CompletionException(e);
                }
                Assert.assertEquals("log entry mismatch for query=" + query, expected, computed);
                return null;
            }));
        }
        JavaUtils.allOf(futures).join();
    }
}
Also used : RaftGroup(org.apache.ratis.protocol.RaftGroup) RaftRetryFailureException(org.apache.ratis.protocol.exceptions.RaftRetryFailureException) TimeoutException(java.util.concurrent.TimeoutException) CompletableFuture(java.util.concurrent.CompletableFuture) RetryPolicies(org.apache.ratis.retry.RetryPolicies) InvalidProtocolBufferException(org.apache.ratis.thirdparty.com.google.protobuf.InvalidProtocolBufferException) ArrayList(java.util.ArrayList) Log4jUtils(org.apache.ratis.util.Log4jUtils) Message(org.apache.ratis.protocol.Message) RaftServerTestUtil(org.apache.ratis.server.impl.RaftServerTestUtil) CheckedRunnable(org.apache.ratis.util.function.CheckedRunnable) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ByteString(org.apache.ratis.thirdparty.com.google.protobuf.ByteString) Level(org.apache.log4j.Level) AlreadyClosedException(org.apache.ratis.protocol.exceptions.AlreadyClosedException) SimpleStateMachine4Testing(org.apache.ratis.statemachine.SimpleStateMachine4Testing) StreamSupport(java.util.stream.StreamSupport) JavaUtils(org.apache.ratis.util.JavaUtils) StateMachineException(org.apache.ratis.protocol.exceptions.StateMachineException) RaftTestUtil.waitForLeader(org.apache.ratis.RaftTestUtil.waitForLeader) StateMachine(org.apache.ratis.statemachine.StateMachine) LogEntryProto(org.apache.ratis.proto.RaftProtos.LogEntryProto) RetryPolicy(org.apache.ratis.retry.RetryPolicy) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) RaftServerConfigKeys(org.apache.ratis.server.RaftServerConfigKeys) Collection(java.util.Collection) RaftClientTestUtil(org.apache.ratis.client.impl.RaftClientTestUtil) Test(org.junit.Test) IOException(java.io.IOException) CompletionException(java.util.concurrent.CompletionException) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) CommitInfoProto(org.apache.ratis.proto.RaftProtos.CommitInfoProto) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) RaftProperties(org.apache.ratis.conf.RaftProperties) RetryLimited(org.apache.ratis.retry.RetryPolicies.RetryLimited) RaftServer(org.apache.ratis.server.RaftServer) SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) RaftClient(org.apache.ratis.client.RaftClient) Assert(org.junit.Assert) Comparator(java.util.Comparator) RaftClientConfigKeys(org.apache.ratis.client.RaftClientConfigKeys) DelayLocalExecutionInjection(org.apache.ratis.server.impl.DelayLocalExecutionInjection) MiniRaftCluster(org.apache.ratis.server.impl.MiniRaftCluster) TimeDuration(org.apache.ratis.util.TimeDuration) CommitInfoProto(org.apache.ratis.proto.RaftProtos.CommitInfoProto) Message(org.apache.ratis.protocol.Message) SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) ByteString(org.apache.ratis.thirdparty.com.google.protobuf.ByteString) SimpleMessage(org.apache.ratis.RaftTestUtil.SimpleMessage) ArrayList(java.util.ArrayList) InvalidProtocolBufferException(org.apache.ratis.thirdparty.com.google.protobuf.InvalidProtocolBufferException) ByteString(org.apache.ratis.thirdparty.com.google.protobuf.ByteString) CompletableFuture(java.util.concurrent.CompletableFuture) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) CompletionException(java.util.concurrent.CompletionException) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) RaftClient(org.apache.ratis.client.RaftClient)

Example 19 with SimpleMessage

use of org.apache.ratis.RaftTestUtil.SimpleMessage 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 20 with SimpleMessage

use of org.apache.ratis.RaftTestUtil.SimpleMessage 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

SimpleMessage (org.apache.ratis.RaftTestUtil.SimpleMessage)52 RaftClient (org.apache.ratis.client.RaftClient)46 RaftClientReply (org.apache.ratis.protocol.RaftClientReply)27 RaftPeerId (org.apache.ratis.protocol.RaftPeerId)20 Test (org.junit.Test)20 RaftServer (org.apache.ratis.server.RaftServer)19 IOException (java.io.IOException)15 RaftClientRpc (org.apache.ratis.client.RaftClientRpc)12 CompletableFuture (java.util.concurrent.CompletableFuture)11 RaftLog (org.apache.ratis.server.raftlog.RaftLog)10 LogEntryProto (org.apache.ratis.proto.RaftProtos.LogEntryProto)9 SimpleStateMachine4Testing (org.apache.ratis.statemachine.SimpleStateMachine4Testing)9 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)8 ArrayList (java.util.ArrayList)7 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)7 BaseTest (org.apache.ratis.BaseTest)7 MiniRaftCluster (org.apache.ratis.server.impl.MiniRaftCluster)7 AtomicReference (java.util.concurrent.atomic.AtomicReference)6 RaftClientRequest (org.apache.ratis.protocol.RaftClientRequest)6 File (java.io.File)5