use of org.apache.ratis.protocol.RaftClientReply 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);
}
use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class GroupManagementBaseTest method runMultiGroupTest.
public static <T extends Throwable> void runMultiGroupTest(MiniRaftCluster cluster, int[] idIndex, int chosen, CheckedBiConsumer<MiniRaftCluster, RaftGroup, T> checker) throws IOException, InterruptedException, T {
if (chosen < 0) {
chosen = ThreadLocalRandom.current().nextInt(idIndex.length);
}
final String type = JavaUtils.getClassSimpleName(cluster.getClass()) + Arrays.toString(idIndex) + "chosen=" + chosen;
LOG.info("\n\nrunMultiGroupTest with " + type + ": " + cluster.printServers());
// Start server with an empty conf
final RaftGroup emptyGroup = RaftGroup.valueOf(cluster.getGroupId());
final List<RaftPeerId> ids = Arrays.stream(MiniRaftCluster.generateIds(idIndex[idIndex.length - 1], 0)).map(RaftPeerId::valueOf).collect(Collectors.toList());
LOG.info("ids: " + ids);
ids.forEach(id -> cluster.putNewServer(id, emptyGroup, true));
LOG.info("putNewServer: " + cluster.printServers());
TimeUnit.SECONDS.sleep(1);
cluster.start();
// Make sure that there are no leaders.
TimeUnit.SECONDS.sleep(1);
LOG.info("start: " + cluster.printServers());
Assert.assertNull(cluster.getLeader());
// Reinitialize servers to three groups
final List<RaftPeer> allPeers = cluster.getPeers();
Collections.sort(allPeers, Comparator.comparing(p -> p.getId().toString()));
final RaftGroup[] groups = new RaftGroup[idIndex.length];
for (int i = 0; i < idIndex.length; i++) {
final RaftGroupId gid = RaftGroupId.randomId();
final int previous = i == 0 ? 0 : idIndex[i - 1];
final RaftPeer[] peers = allPeers.subList(previous, idIndex[i]).toArray(RaftPeer.emptyArray());
groups[i] = RaftGroup.valueOf(gid, peers);
LOG.info(i + ") starting " + groups[i]);
for (RaftPeer p : peers) {
try (final RaftClient client = cluster.createClient(p.getId(), emptyGroup)) {
client.getGroupManagementApi(p.getId()).add(groups[i]);
}
}
Assert.assertNotNull(RaftTestUtil.waitForLeader(cluster, gid));
checker.accept(cluster, groups[i]);
}
printThreadCount(type, "start groups");
LOG.info("start groups: " + cluster.printServers());
// randomly remove two of the groups
LOG.info("chosen = " + chosen + ", " + groups[chosen]);
for (int i = 0; i < groups.length; i++) {
if (i != chosen) {
final RaftGroup g = groups[i];
LOG.info(i + ") close " + cluster.printServers(g.getGroupId()));
for (RaftPeer p : g.getPeers()) {
final RaftServer.Division d = cluster.getDivision(p.getId(), g.getGroupId());
final File root = d.getRaftStorage().getStorageDir().getRoot();
Assert.assertTrue(root.exists());
Assert.assertTrue(root.isDirectory());
final RaftClientReply r;
try (final RaftClient client = cluster.createClient(p.getId(), g)) {
r = client.getGroupManagementApi(p.getId()).remove(g.getGroupId(), true, false);
}
Assert.assertTrue(r.isSuccess());
Assert.assertFalse(root.exists());
}
}
}
printThreadCount(type, "close groups");
LOG.info("close groups: " + cluster.printServers());
// update chosen group to use all the peers
final RaftGroup newGroup = RaftGroup.valueOf(groups[chosen].getGroupId());
for (int i = 0; i < groups.length; i++) {
if (i != chosen) {
LOG.info(i + ") groupAdd: " + cluster.printServers(groups[i].getGroupId()));
for (RaftPeer p : groups[i].getPeers()) {
try (final RaftClient client = cluster.createClient(p.getId(), groups[i])) {
client.getGroupManagementApi(p.getId()).add(newGroup);
}
}
}
}
LOG.info(chosen + ") setConfiguration: " + cluster.printServers(groups[chosen].getGroupId()));
try (final RaftClient client = cluster.createClient(groups[chosen])) {
client.admin().setConfiguration(allPeers.toArray(RaftPeer.emptyArray()));
}
Assert.assertNotNull(RaftTestUtil.waitForLeader(cluster));
checker.accept(cluster, groups[chosen]);
LOG.info("update groups: " + cluster.printServers());
printThreadCount(type, "update groups");
cluster.shutdown();
printThreadCount(type, "shutdown");
}
use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class MiniRaftCluster method setConfiguration.
public void setConfiguration(RaftPeer... peers) throws IOException {
try (RaftClient client = createClient()) {
LOG.info("Start changing the configuration: {}", Arrays.asList(peers));
final RaftClientReply reply = client.admin().setConfiguration(peers);
Preconditions.assertTrue(reply.isSuccess());
}
}
use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class RaftReconfigurationBaseTest method runTestKillLeaderDuringReconf.
void runTestKillLeaderDuringReconf(CLUSTER cluster) throws Exception {
final AtomicBoolean clientRunning = new AtomicBoolean(true);
Thread clientThread = null;
try {
final RaftPeerId leaderId = RaftTestUtil.waitForLeader(cluster).getId();
PeerChanges c1 = cluster.addNewPeers(1, false);
PeerChanges c2 = cluster.removePeers(1, false, asList(c1.newPeers));
LOG.info("Start setConf: {}", asList(c2.allPeersInNewConf));
LOG.info(cluster.printServers());
final CompletableFuture<Void> setConf = new CompletableFuture<>();
clientThread = new Thread(() -> {
try (final RaftClient client = cluster.createClient(leaderId)) {
for (int i = 0; clientRunning.get() && !setConf.isDone(); i++) {
final RaftClientReply reply = client.admin().setConfiguration(c2.allPeersInNewConf);
if (reply.isSuccess()) {
setConf.complete(null);
}
LOG.info("setConf attempt #{} failed, {}", i, cluster.printServers());
}
} catch (Exception e) {
LOG.error("Failed to setConf", e);
setConf.completeExceptionally(e);
}
});
clientThread.start();
TimeUnit.SECONDS.sleep(1);
// the leader cannot generate the (old, new) conf, and it will keep
// bootstrapping the 2 new peers since they have not started yet
Assert.assertFalse(((RaftConfigurationImpl) cluster.getLeader().getRaftConf()).isTransitional());
// only (0) the first conf entry, (1) the 1st setConf entry and (2) a metadata entry
{
final RaftLog leaderLog = cluster.getLeader().getRaftLog();
for (LogEntryProto e : RaftTestUtil.getLogEntryProtos(leaderLog)) {
LOG.info("{}", LogProtoUtils.toLogEntryString(e));
}
final long commitIndex = leaderLog.getLastCommittedIndex();
Assert.assertTrue("commitIndex = " + commitIndex + " > 2", commitIndex <= 2);
}
final RaftPeerId killed = RaftTestUtil.waitAndKillLeader(cluster);
Assert.assertEquals(leaderId, killed);
final RaftPeerId newLeaderId = RaftTestUtil.waitForLeader(cluster).getId();
LOG.info("newLeaderId: {}", newLeaderId);
LOG.info("start new peers: {}", Arrays.asList(c1.newPeers));
for (RaftPeer np : c1.newPeers) {
cluster.restartServer(np.getId(), false);
}
try {
setConf.get(10, TimeUnit.SECONDS);
} catch (TimeoutException ignored) {
}
// the client fails with the first leader, and then retry the same setConfiguration request
waitAndCheckNewConf(cluster, c2.allPeersInNewConf, 2, Collections.singletonList(leaderId));
setConf.get(1, TimeUnit.SECONDS);
} finally {
if (clientThread != null) {
clientRunning.set(false);
clientThread.interrupt();
}
}
}
use of org.apache.ratis.protocol.RaftClientReply in project incubator-ratis by apache.
the class RaftReconfigurationBaseTest method runTestRevertConfigurationChange.
void runTestRevertConfigurationChange(CLUSTER cluster) throws Exception {
RaftLogBase log2 = null;
try {
RaftTestUtil.waitForLeader(cluster);
final RaftServer.Division leader = cluster.getLeader();
final RaftPeerId leaderId = leader.getId();
final RaftLog log = leader.getRaftLog();
log2 = (RaftLogBase) 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
final TimeDuration sleepTime = TimeDuration.valueOf(500, TimeUnit.MILLISECONDS);
final long confIndex = JavaUtils.attemptRepeatedly(() -> {
final long last = log.getLastEntryTermIndex().getIndex();
for (long i = last; i >= 1; i--) {
if (log.get(i).hasConfigurationEntry()) {
return i;
}
}
throw new Exception("ConfigurationEntry not found: last=" + last);
}, 10, sleepTime, "confIndex", LOG);
// wait till the old leader persist the new conf
JavaUtils.attemptRepeatedly(() -> {
Assert.assertTrue(log.getFlushIndex() >= confIndex);
return null;
}, 10, sleepTime, "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.attemptRepeatedly(() -> {
Assert.assertTrue(log.getLastCommittedIndex() >= confIndex);
return null;
}, 10, ONE_SECOND, "COMMIT", LOG);
Assert.assertTrue(log.get(confIndex).hasConfigurationEntry());
log2 = null;
} finally {
RaftStorageTestUtils.printLog(log2, s -> LOG.info(s));
}
}
Aggregations