use of org.apache.ignite.raft.jraft.closure.TaskClosure in project ignite-3 by apache.
the class FSMCallerImpl method onTaskCommitted.
private void onTaskCommitted(final List<TaskClosure> closures) {
for (int i = 0, size = closures.size(); i < size; i++) {
final TaskClosure done = closures.get(i);
done.onCommitted();
}
}
use of org.apache.ignite.raft.jraft.closure.TaskClosure in project ignite-3 by apache.
the class FSMCallerImpl method doCommitted.
private void doCommitted(final long committedIndex) {
if (!this.error.getStatus().isOk()) {
return;
}
final long lastAppliedIndex = this.lastAppliedIndex.get();
// We can tolerate the disorder of committed_index
if (lastAppliedIndex >= committedIndex) {
return;
}
final long startMs = Utils.monotonicMs();
try {
final List<Closure> closures = new ArrayList<>();
final List<TaskClosure> taskClosures = new ArrayList<>();
final long firstClosureIndex = this.closureQueue.popClosureUntil(committedIndex, closures, taskClosures);
// Calls TaskClosure#onCommitted if necessary
onTaskCommitted(taskClosures);
Requires.requireTrue(firstClosureIndex >= 0, "Invalid firstClosureIndex");
final IteratorImpl iterImpl = new IteratorImpl(this.fsm, this.logManager, closures, firstClosureIndex, lastAppliedIndex, committedIndex, this.applyingIndex, this.node.getOptions());
while (iterImpl.isGood()) {
final LogEntry logEntry = iterImpl.entry();
if (logEntry.getType() != EnumOutter.EntryType.ENTRY_TYPE_DATA) {
if (logEntry.getType() == EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION) {
if (logEntry.getOldPeers() != null && !logEntry.getOldPeers().isEmpty()) {
// Joint stage is not supposed to be noticeable by end users.
this.fsm.onConfigurationCommitted(new Configuration(iterImpl.entry().getPeers()));
}
}
if (iterImpl.done() != null) {
// For other entries, we have nothing to do besides flush the
// pending tasks and run this closure to notify the caller that the
// entries before this one were successfully committed and applied.
iterImpl.done().run(Status.OK());
}
iterImpl.next();
continue;
}
// Apply data task to user state machine
doApplyTasks(iterImpl);
}
if (iterImpl.hasError()) {
setError(iterImpl.getError());
iterImpl.runTheRestClosureWithError();
}
final long lastIndex = iterImpl.getIndex() - 1;
final long lastTerm = this.logManager.getTerm(lastIndex);
final LogId lastAppliedId = new LogId(lastIndex, lastTerm);
this.lastAppliedIndex.set(lastIndex);
this.lastAppliedTerm = lastTerm;
this.logManager.setAppliedId(lastAppliedId);
notifyLastAppliedIndexUpdated(lastIndex);
} finally {
this.nodeMetrics.recordLatency("fsm-commit", Utils.monotonicMs() - startMs);
}
}
use of org.apache.ignite.raft.jraft.closure.TaskClosure in project ignite-3 by apache.
the class ItNodeTest method testTripleNodesWithLearners.
@Test
public void testTripleNodesWithLearners() throws Exception {
List<PeerId> peers = TestUtils.generatePeers(3);
cluster = new TestCluster("unittest", dataPath, peers, testInfo);
for (PeerId peer : peers) assertTrue(cluster.start(peer.getEndpoint()));
// elect leader
cluster.waitLeader();
// get leader
Node leader = cluster.getLeader();
assertNotNull(leader);
cluster.ensureLeader(leader);
assertEquals(3, leader.listPeers().size());
assertTrue(leader.listLearners().isEmpty());
assertTrue(leader.listAliveLearners().isEmpty());
{
// Adds a learner
SynchronizedClosure done = new SynchronizedClosure();
PeerId learnerPeer = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT + 3);
// Start learner
assertTrue(cluster.startLearner(learnerPeer));
leader.addLearners(Arrays.asList(learnerPeer), done);
assertTrue(done.await().isOk());
assertEquals(1, leader.listAliveLearners().size());
assertEquals(1, leader.listLearners().size());
}
// apply tasks to leader
sendTestTaskAndWait(leader);
{
ByteBuffer data = ByteBuffer.wrap("no closure".getBytes(UTF_8));
Task task = new Task(data, null);
leader.apply(task);
}
{
// task with TaskClosure
ByteBuffer data = ByteBuffer.wrap("task closure".getBytes(UTF_8));
List<String> cbs = synchronizedList(new ArrayList<>());
CountDownLatch latch = new CountDownLatch(1);
Task task = new Task(data, new TaskClosure() {
@Override
public void run(Status status) {
cbs.add("apply");
latch.countDown();
}
@Override
public void onCommitted() {
cbs.add("commit");
}
});
leader.apply(task);
latch.await();
assertEquals(2, cbs.size());
assertEquals("commit", cbs.get(0));
assertEquals("apply", cbs.get(1));
}
assertEquals(4, cluster.getFsms().size());
assertEquals(2, cluster.getFollowers().size());
assertEquals(1, cluster.getLearners().size());
cluster.ensureSame();
{
// Adds another learner
SynchronizedClosure done = new SynchronizedClosure();
PeerId learnerPeer = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT + 4);
// Start learner
assertTrue(cluster.startLearner(learnerPeer));
leader.addLearners(Arrays.asList(learnerPeer), done);
assertTrue(done.await().isOk());
assertEquals(2, leader.listAliveLearners().size());
assertEquals(2, leader.listLearners().size());
cluster.ensureSame();
}
{
// stop two followers
for (Node follower : cluster.getFollowers()) assertTrue(cluster.stop(follower.getNodeId().getPeerId().getEndpoint()));
// send a new task
ByteBuffer data = ByteBuffer.wrap("task closure".getBytes(UTF_8));
SynchronizedClosure done = new SynchronizedClosure();
leader.apply(new Task(data, done));
// should fail
assertFalse(done.await().isOk());
assertEquals(RaftError.EPERM, done.getStatus().getRaftError());
// One peer with two learners.
assertEquals(3, cluster.getFsms().size());
}
}
use of org.apache.ignite.raft.jraft.closure.TaskClosure in project ignite-3 by apache.
the class ItNodeTest method testTripleNodes.
@Test
public void testTripleNodes() throws Exception {
List<PeerId> peers = TestUtils.generatePeers(3);
cluster = new TestCluster("unittest", dataPath, peers, testInfo);
for (PeerId peer : peers) assertTrue(cluster.start(peer.getEndpoint()));
// elect leader
cluster.waitLeader();
// get leader
Node leader = cluster.getLeader();
assertNotNull(leader);
cluster.ensureLeader(leader);
assertEquals(3, leader.listPeers().size());
// apply tasks to leader
sendTestTaskAndWait(leader);
{
ByteBuffer data = ByteBuffer.wrap("no closure".getBytes(UTF_8));
Task task = new Task(data, null);
leader.apply(task);
}
{
// task with TaskClosure
ByteBuffer data = ByteBuffer.wrap("task closure".getBytes(UTF_8));
List<String> cbs = synchronizedList(new ArrayList<>());
CountDownLatch latch = new CountDownLatch(1);
Task task = new Task(data, new TaskClosure() {
@Override
public void run(Status status) {
cbs.add("apply");
latch.countDown();
}
@Override
public void onCommitted() {
cbs.add("commit");
}
});
leader.apply(task);
latch.await();
assertEquals(2, cbs.size());
assertEquals("commit", cbs.get(0));
assertEquals("apply", cbs.get(1));
}
cluster.ensureSame();
assertEquals(2, cluster.getFollowers().size());
}
Aggregations