use of org.apache.ignite.raft.jraft.Node in project ignite-3 by apache.
the class ItNodeTest method testChangePeers.
@Test
public void testChangePeers() throws Exception {
PeerId peer0 = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT);
cluster = new TestCluster("testChangePeers", dataPath, Collections.singletonList(peer0), testInfo);
assertTrue(cluster.start(peer0.getEndpoint()));
cluster.waitLeader();
Node leader = cluster.getLeader();
sendTestTaskAndWait(leader);
for (int i = 1; i < 10; i++) {
PeerId peer = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT + i);
assertTrue(cluster.start(peer.getEndpoint(), false, 300));
}
for (int i = 0; i < 9; i++) {
cluster.waitLeader();
leader = cluster.getLeader();
assertNotNull(leader);
PeerId peer = new PeerId(TestUtils.getLocalAddress(), peer0.getEndpoint().getPort() + i);
assertEquals(peer, leader.getNodeId().getPeerId());
peer = new PeerId(TestUtils.getLocalAddress(), peer0.getEndpoint().getPort() + i + 1);
SynchronizedClosure done = new SynchronizedClosure();
leader.changePeers(new Configuration(Collections.singletonList(peer)), done);
Status status = done.await();
assertTrue(status.isOk(), status.getRaftError().toString());
}
cluster.waitLeader();
for (MockStateMachine fsm : cluster.getFsms()) {
assertEquals(10, fsm.getLogs().size());
}
}
use of org.apache.ignite.raft.jraft.Node in project ignite-3 by apache.
the class ItNodeTest method testChangePeersStepsDownInJointConsensus.
@Test
public void testChangePeersStepsDownInJointConsensus() throws Exception {
List<PeerId> peers = new ArrayList<>();
PeerId peer0 = JRaftUtils.getPeerId(TestUtils.getLocalAddress() + ":5006");
PeerId peer1 = JRaftUtils.getPeerId(TestUtils.getLocalAddress() + ":5007");
PeerId peer2 = JRaftUtils.getPeerId(TestUtils.getLocalAddress() + ":5008");
PeerId peer3 = JRaftUtils.getPeerId(TestUtils.getLocalAddress() + ":5009");
// start single cluster
peers.add(peer0);
cluster = new TestCluster("testChangePeersStepsDownInJointConsensus", dataPath, peers, testInfo);
assertTrue(cluster.start(peer0.getEndpoint()));
cluster.waitLeader();
Node leader = cluster.getLeader();
assertNotNull(leader);
sendTestTaskAndWait(leader);
// start peer1-3
assertTrue(cluster.start(peer1.getEndpoint()));
assertTrue(cluster.start(peer2.getEndpoint()));
assertTrue(cluster.start(peer3.getEndpoint()));
// Make sure the topology is ready before adding peers.
assertTrue(waitForTopology(cluster, leader.getNodeId().getPeerId().getEndpoint(), 4, 3_000));
Configuration conf = new Configuration();
conf.addPeer(peer0);
conf.addPeer(peer1);
conf.addPeer(peer2);
conf.addPeer(peer3);
// change peers
SynchronizedClosure done = new SynchronizedClosure();
leader.changePeers(conf, done);
assertTrue(done.await().isOk());
// stop peer3
assertTrue(cluster.stop(peer3.getEndpoint()));
conf.removePeer(peer0);
conf.removePeer(peer1);
// Change peers to [peer2, peer3], which must fail since peer3 is stopped
done.reset();
leader.changePeers(conf, done);
assertEquals(RaftError.EPERM, done.await().getRaftError());
LOG.info(done.getStatus().toString());
assertFalse(((NodeImpl) leader).getConf().isStable());
leader = cluster.getLeader();
assertNull(leader);
assertTrue(cluster.start(peer3.getEndpoint()));
Thread.sleep(1000);
cluster.waitLeader();
leader = cluster.getLeader();
List<PeerId> thePeers = leader.listPeers();
assertTrue(!thePeers.isEmpty());
assertEquals(conf.getPeerSet(), new HashSet<>(thePeers));
}
use of org.apache.ignite.raft.jraft.Node in project ignite-3 by apache.
the class ItNodeTest method readCommittedUserLog.
@Test
public void readCommittedUserLog() throws Exception {
// setup cluster
List<PeerId> peers = TestUtils.generatePeers(3);
cluster = new TestCluster("unitest", dataPath, peers, ELECTION_TIMEOUT_MILLIS, testInfo);
for (PeerId peer : peers) assertTrue(cluster.start(peer.getEndpoint()));
cluster.waitLeader();
Node leader = cluster.getLeader();
assertNotNull(leader);
cluster.ensureLeader(leader);
int amount = 10;
sendTestTaskAndWait(leader, amount);
assertTrue(waitForCondition(() -> {
try {
// index == 1 is a CONFIGURATION log
UserLog userLog = leader.readCommittedUserLog(1 + amount);
return userLog != null;
} catch (Exception ignore) {
// is updated, so we need to wait.
return false;
}
}, 10_000));
// index == 1 is a CONFIGURATION log, so real_index will be 2 when returned.
UserLog userLog = leader.readCommittedUserLog(1);
assertNotNull(userLog);
assertEquals(2, userLog.getIndex());
assertEquals("hello0", stringFromBytes(userLog.getData().array()));
// index == 5 is a DATA log(a user log)
userLog = leader.readCommittedUserLog(5);
assertNotNull(userLog);
assertEquals(5, userLog.getIndex());
assertEquals("hello3", stringFromBytes(userLog.getData().array()));
// index == 15 is greater than last_committed_index
try {
assertNull(leader.readCommittedUserLog(15));
fail();
} catch (LogIndexOutOfBoundsException e) {
assertEquals("Request index 15 is greater than lastAppliedIndex: 11", e.getMessage());
}
// index == 0 invalid request
try {
assertNull(leader.readCommittedUserLog(0));
fail();
} catch (LogIndexOutOfBoundsException e) {
assertEquals("Request index is invalid: 0", e.getMessage());
}
LOG.info("Trigger leader snapshot");
CountDownLatch latch = new CountDownLatch(1);
leader.snapshot(new ExpectClosure(latch));
waitLatch(latch);
// remove and add a peer to add two CONFIGURATION logs
List<Node> followers = cluster.getFollowers();
assertEquals(2, followers.size());
Node testFollower = followers.get(0);
latch = new CountDownLatch(1);
leader.removePeer(testFollower.getNodeId().getPeerId(), new ExpectClosure(latch));
waitLatch(latch);
latch = new CountDownLatch(1);
leader.addPeer(testFollower.getNodeId().getPeerId(), new ExpectClosure(latch));
waitLatch(latch);
sendTestTaskAndWait(leader, amount, RaftError.SUCCESS);
// trigger leader snapshot for the second time, after this the log of index 1~11 will be deleted.
LOG.info("Trigger leader snapshot");
latch = new CountDownLatch(1);
leader.snapshot(new ExpectClosure(latch));
waitLatch(latch);
Thread.sleep(100);
// index == 5 log has been deleted in log_storage.
try {
leader.readCommittedUserLog(5);
fail();
} catch (LogNotFoundException e) {
assertEquals("User log is deleted at index: 5", e.getMessage());
}
// index == 12、index == 13、index=14、index=15 are 4 CONFIGURATION logs(joint consensus), so real_index will be 16 when returned.
userLog = leader.readCommittedUserLog(12);
assertNotNull(userLog);
assertEquals(16, userLog.getIndex());
assertEquals("hello10", stringFromBytes(userLog.getData().array()));
// now index == 17 is a user log
userLog = leader.readCommittedUserLog(17);
assertNotNull(userLog);
assertEquals(17, userLog.getIndex());
assertEquals("hello11", stringFromBytes(userLog.getData().array()));
cluster.ensureSame();
assertEquals(3, cluster.getFsms().size());
for (MockStateMachine fsm : cluster.getFsms()) {
assertEquals(20, fsm.getLogs().size());
for (int i = 0; i < 20; i++) assertEquals("hello" + i, stringFromBytes(fsm.getLogs().get(i).array()));
}
}
use of org.apache.ignite.raft.jraft.Node in project ignite-3 by apache.
the class ItNodeTest method testRestoreSnapshotWithDelta.
/**
* @throws Exception
*/
@Test
public void testRestoreSnapshotWithDelta() throws Exception {
List<PeerId> peers = TestUtils.generatePeers(3);
cluster = new TestCluster("unitest", dataPath, peers, testInfo);
for (PeerId peer : peers) assertTrue(cluster.start(peer.getEndpoint()));
cluster.waitLeader();
// get leader
Node leader = cluster.getLeader();
LOG.info("Leader: " + leader);
assertNotNull(leader);
// apply tasks to leader
sendTestTaskAndWait(leader);
cluster.ensureSame();
triggerLeaderSnapshot(cluster, leader);
// stop leader
Endpoint leaderAddr = leader.getNodeId().getPeerId().getEndpoint().copy();
assertTrue(cluster.stop(leaderAddr));
// restart leader
cluster.waitLeader();
sendTestTaskAndWait(cluster.getLeader(), 10, RaftError.SUCCESS);
assertEquals(0, cluster.getLeaderFsm().getLoadSnapshotTimes());
assertTrue(cluster.start(leaderAddr));
Node oldLeader = cluster.getNode(leaderAddr);
cluster.ensureSame();
assertEquals(0, cluster.getLeaderFsm().getLoadSnapshotTimes());
MockStateMachine fsm = (MockStateMachine) oldLeader.getOptions().getFsm();
assertEquals(1, fsm.getLoadSnapshotTimes());
}
use of org.apache.ignite.raft.jraft.Node in project ignite-3 by apache.
the class NodeImpl method shutdown.
@Override
public void shutdown(final Closure done) {
this.writeLock.lock();
try {
LOG.info("Node {} shutdown, currTerm={} state={}.", getNodeId(), this.currTerm, this.state);
if (this.state.compareTo(State.STATE_SHUTTING) < 0) {
// If it is follower, call on_stop_following in step_down
if (this.state.compareTo(State.STATE_FOLLOWER) <= 0) {
stepDown(this.currTerm, this.state == State.STATE_LEADER, new Status(RaftError.ESHUTDOWN, "Raft node is going to quit."));
}
this.state = State.STATE_SHUTTING;
// Stop all pending timer callbacks.
stopAllTimers();
if (this.readOnlyService != null) {
this.readOnlyService.shutdown();
}
if (this.logManager != null) {
this.logManager.shutdown();
}
if (this.metaStorage != null) {
this.metaStorage.shutdown();
}
if (this.snapshotExecutor != null) {
this.snapshotExecutor.shutdown();
}
if (this.wakingCandidate != null) {
Replicator.stop(this.wakingCandidate);
}
if (this.fsmCaller != null) {
this.fsmCaller.shutdown();
}
if (this.rpcClientService != null) {
this.rpcClientService.shutdown();
}
if (this.applyQueue != null) {
final CountDownLatch latch = new CountDownLatch(1);
this.shutdownLatch = latch;
Utils.runInThread(this.getOptions().getCommonExecutor(), () -> this.applyQueue.publishEvent((event, sequence) -> {
event.groupId = groupId;
event.shutdownLatch = latch;
}));
}
}
if (this.state != State.STATE_SHUTDOWN) {
if (done != null) {
this.shutdownContinuations.add(done);
}
return;
}
// a writeLock which is already held by the caller
if (done != null) {
Utils.runClosureInThread(this.getOptions().getCommonExecutor(), done);
}
} finally {
this.writeLock.unlock();
}
}
Aggregations