use of com.alipay.sofa.jraft.Node in project sofa-jraft by sofastack.
the class NodeTest method testSingleNodeWithLearner.
@Test
public void testSingleNodeWithLearner() throws Exception {
final Endpoint addr = new Endpoint(TestUtils.getMyIp(), TestUtils.INIT_PORT);
final PeerId peer = new PeerId(addr, 0);
final Endpoint learnerAddr = new Endpoint(TestUtils.getMyIp(), TestUtils.INIT_PORT + 1);
final PeerId learnerPeer = new PeerId(learnerAddr, 0);
NodeManager.getInstance().addAddress(addr);
NodeManager.getInstance().addAddress(learnerAddr);
MockStateMachine learnerFsm = null;
Node learner = null;
RaftGroupService learnerServer = null;
{
// Start learner
final NodeOptions nodeOptions = createNodeOptionsWithSharedTimer();
learnerFsm = new MockStateMachine(learnerAddr);
nodeOptions.setFsm(learnerFsm);
nodeOptions.setLogUri(this.dataPath + File.separator + "log1");
nodeOptions.setRaftMetaUri(this.dataPath + File.separator + "meta1");
nodeOptions.setSnapshotUri(this.dataPath + File.separator + "snapshot1");
nodeOptions.setInitialConf(new Configuration(Collections.singletonList(peer), Collections.singletonList(learnerPeer)));
final RpcServer rpcServer = RaftRpcServerFactory.createRaftRpcServer(learnerAddr);
learnerServer = new RaftGroupService("unittest", new PeerId(learnerAddr, 0), nodeOptions, rpcServer);
learner = learnerServer.start();
}
{
// Start leader
final NodeOptions nodeOptions = createNodeOptionsWithSharedTimer();
final MockStateMachine fsm = new MockStateMachine(addr);
nodeOptions.setFsm(fsm);
nodeOptions.setLogUri(this.dataPath + File.separator + "log");
nodeOptions.setRaftMetaUri(this.dataPath + File.separator + "meta");
nodeOptions.setSnapshotUri(this.dataPath + File.separator + "snapshot");
nodeOptions.setInitialConf(new Configuration(Collections.singletonList(peer), Collections.singletonList(learnerPeer)));
final Node node = new NodeImpl("unittest", peer);
assertTrue(node.init(nodeOptions));
assertEquals(1, node.listPeers().size());
assertTrue(node.listPeers().contains(peer));
while (!node.isLeader()) {
;
}
sendTestTaskAndWait(node);
assertEquals(10, fsm.getLogs().size());
int i = 0;
for (final ByteBuffer data : fsm.getLogs()) {
assertEquals("hello" + i++, new String(data.array()));
}
// wait for entries to be replicated to learner.
Thread.sleep(1000);
node.shutdown();
node.join();
}
{
// assert learner fsm
assertEquals(10, learnerFsm.getLogs().size());
int i = 0;
for (final ByteBuffer data : learnerFsm.getLogs()) {
assertEquals("hello" + i++, new String(data.array()));
}
learnerServer.shutdown();
learnerServer.join();
}
}
use of com.alipay.sofa.jraft.Node in project sofa-jraft by sofastack.
the class NodeTest method testShuttingDownLeaderTriggerTimeoutNow.
@Test
public void testShuttingDownLeaderTriggerTimeoutNow() throws Exception {
final List<PeerId> peers = TestUtils.generatePeers(3);
final TestCluster cluster = new TestCluster("unitest", this.dataPath, peers, 300);
for (final PeerId peer : peers) {
assertTrue(cluster.start(peer.getEndpoint()));
}
cluster.waitLeader();
Node leader = cluster.getLeader();
assertNotNull(leader);
final Node oldLeader = leader;
LOG.info("Shutdown leader {}", leader);
leader.shutdown();
leader.join();
Thread.sleep(100);
leader = cluster.getLeader();
cluster.waitLeader();
assertNotNull(leader);
assertNotSame(leader, oldLeader);
cluster.stopAll();
}
use of com.alipay.sofa.jraft.Node in project sofa-jraft by sofastack.
the class NodeImpl method shutdown.
@Override
public void shutdown(Closure done) {
List<RepeatedTimer> timers = null;
this.writeLock.lock();
try {
LOG.info("Node {} shutdown, currTerm={} state={}.", getNodeId(), this.currTerm, this.state);
if (this.state.compareTo(State.STATE_SHUTTING) < 0) {
NodeManager.getInstance().remove(this);
// 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 timers
timers = 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.rpcService != null) {
this.rpcService.shutdown();
}
if (this.applyQueue != null) {
final CountDownLatch latch = new CountDownLatch(1);
this.shutdownLatch = latch;
Utils.runInThread(() -> this.applyQueue.publishEvent((event, sequence) -> event.shutdownLatch = latch));
} else {
final int num = GLOBAL_NUM_NODES.decrementAndGet();
LOG.info("The number of active nodes decrement to {}.", num);
}
if (this.timerManager != null) {
this.timerManager.shutdown();
}
}
if (this.state != State.STATE_SHUTDOWN) {
if (done != null) {
this.shutdownContinuations.add(done);
done = null;
}
return;
}
} finally {
this.writeLock.unlock();
// Destroy all timers out of lock
if (timers != null) {
destroyAllTimers(timers);
}
// Call join() asynchronously
final Closure shutdownHook = done;
Utils.runInThread(() -> {
try {
join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// a writeLock which is already held by the caller
if (shutdownHook != null) {
shutdownHook.run(Status.OK());
}
}
});
}
}
use of com.alipay.sofa.jraft.Node in project sofa-jraft by sofastack.
the class NodeImpl method executeApplyingTasks.
private void executeApplyingTasks(final List<LogEntryAndClosure> tasks) {
this.writeLock.lock();
try {
final int size = tasks.size();
if (this.state != State.STATE_LEADER) {
final Status st = new Status();
if (this.state != State.STATE_TRANSFERRING) {
st.setError(RaftError.EPERM, "Is not leader.");
} else {
st.setError(RaftError.EBUSY, "Is transferring leadership.");
}
LOG.debug("Node {} can't apply, status={}.", getNodeId(), st);
final List<Closure> dones = tasks.stream().map(ele -> ele.done).collect(Collectors.toList());
Utils.runInThread(() -> {
for (final Closure done : dones) {
done.run(st);
}
});
return;
}
final List<LogEntry> entries = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
final LogEntryAndClosure task = tasks.get(i);
if (task.expectedTerm != -1 && task.expectedTerm != this.currTerm) {
LOG.debug("Node {} can't apply task whose expectedTerm={} doesn't match currTerm={}.", getNodeId(), task.expectedTerm, this.currTerm);
if (task.done != null) {
final Status st = new Status(RaftError.EPERM, "expected_term=%d doesn't match current_term=%d", task.expectedTerm, this.currTerm);
Utils.runClosureInThread(task.done, st);
task.reset();
}
continue;
}
if (!this.ballotBox.appendPendingTask(this.conf.getConf(), this.conf.isStable() ? null : this.conf.getOldConf(), task.done)) {
Utils.runClosureInThread(task.done, new Status(RaftError.EINTERNAL, "Fail to append task."));
task.reset();
continue;
}
// set task entry info before adding to list.
task.entry.getId().setTerm(this.currTerm);
task.entry.setType(EnumOutter.EntryType.ENTRY_TYPE_DATA);
entries.add(task.entry);
task.reset();
}
this.logManager.appendEntries(entries, new LeaderStableClosure(entries));
// update conf.first
checkAndSetConfiguration(true);
} finally {
this.writeLock.unlock();
}
}
use of com.alipay.sofa.jraft.Node in project sofa-jraft by sofastack.
the class BaseCliRequestProcessor method processRequest.
@Override
public Message processRequest(T request, RpcRequestClosure done) {
String groupId = getGroupId(request);
String peerIdStr = getPeerId(request);
PeerId peerId = null;
if (!StringUtils.isBlank(peerIdStr)) {
peerId = new PeerId();
if (!peerId.parse(peerIdStr)) {
return //
RpcFactoryHelper.responseFactory().newResponse(defaultResp(), RaftError.EINVAL, "Fail to parse peer: %s", peerIdStr);
}
}
Status st = new Status();
Node node = getNode(groupId, peerId, st);
if (!st.isOk()) {
return //
RpcFactoryHelper.responseFactory().newResponse(defaultResp(), st.getCode(), st.getErrorMsg());
} else {
return processRequest0(new CliRequestContext(node, groupId, peerId), request, done);
}
}
Aggregations