use of io.dingodb.raft.Node in project dingo by dingodb.
the class CoordinatorServer method start.
public void start(final CoordinatorOptions opts) throws Exception {
this.svrOpts = opts;
log.info("Coordinator all configuration: {}.", this.svrOpts);
log.info("instance configuration: {}.", DingoOptions.instance());
this.context = new CoordinatorContext();
final String raftId = svrOpts.getRaft().getGroup();
final Endpoint endpoint = new Endpoint(svrOpts.getIp(), svrOpts.getRaft().getPort());
final RocksRawKVStore rawKVStore = createRocksDB();
final CoordinatorStateMachine stateMachine = createStateMachine(raftId, rawKVStore, context);
final Node node = RaftServiceFactory.createRaftNode(raftId, new PeerId(endpoint, 0));
final AsyncKeyValueStore keyValueStore = createStore(rawKVStore, node);
final ScheduleMetaAdaptor scheduleMetaAdaptor = createScheduleMetaAdaptor(keyValueStore);
final TableMetaAdaptor tableMetaAdaptor = createTableMetaAdaptor(keyValueStore, scheduleMetaAdaptor);
final CoordinatorMetaService metaService = createMetaService();
final RowStoreMetaAdaptor rowStoreMetaAdaptor = createRowStoreMetaAdaptor(scheduleMetaAdaptor);
context.coordOpts(svrOpts).endpoint(endpoint).netService(createNetService()).rocksKVStore(rawKVStore).stateMachine(stateMachine).keyValueStore(keyValueStore).node(node).scheduleMetaAdaptor(scheduleMetaAdaptor).serviceProvider(createServiceProvider()).tableMetaAdaptor(tableMetaAdaptor).rowStoreMetaAdaptor(rowStoreMetaAdaptor).metaService(metaService);
NodeManager.getInstance().addAddress(endpoint);
stateMachine.init();
final NodeOptions nodeOptions = initNodeOptions(stateMachine);
node.init(nodeOptions);
keyValueStore.init();
}
use of io.dingodb.raft.Node in project dingo by dingodb.
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 io.dingodb.raft.Node in project dingo by dingodb.
the class NodeImpl method apply.
@Override
public void apply(final Task task) {
if (this.shutdownLatch != null) {
Utils.runClosureInThread(task.getDone(), new Status(RaftError.ENODESHUTDOWN, "Node is shutting down."));
throw new IllegalStateException("Node is shutting down");
}
Requires.requireNonNull(task, "Null task");
final LogEntry entry = new LogEntry();
entry.setData(task.getData());
int retryTimes = 0;
try {
final EventTranslator<LogEntryAndClosure> translator = (event, sequence) -> {
event.reset();
event.done = task.getDone();
event.entry = entry;
event.expectedTerm = task.getExpectedTerm();
};
this.applyQueue.publishEvent(translator);
/*
while (true) {
if (this.applyQueue.tryPublishEvent(translator)) {
break;
} else {
retryTimes++;
if (retryTimes > MAX_APPLY_RETRY_TIMES) {
Utils.runClosureInThread(task.getDone(),
new Status(RaftError.EBUSY, "Node is busy, has too many tasks."));
LOG.warn("Node {} applyQueue is overload.", getNodeId());
this.metrics.recordTimes("apply-task-overload-times", 1);
return;
}
ThreadHelper.onSpinWait();
}
}
*/
} catch (final Exception e) {
LOG.error("Fail to apply task.", e);
Utils.runClosureInThread(task.getDone(), new Status(RaftError.EPERM, "Node is down."));
}
}
use of io.dingodb.raft.Node in project dingo by dingodb.
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 io.dingodb.raft.Node in project dingo by dingodb.
the class Replicator method notifyReplicatorStatusListener.
/**
* Notify replicator event(such as created, error, destroyed) to replicatorStateListener which is implemented by users.
*
* @param replicator replicator object
* @param event replicator's state listener event type
* @param status replicator's error detailed status
*/
private static void notifyReplicatorStatusListener(final Replicator replicator, final ReplicatorEvent event, final Status status, final ReplicatorStateListener.ReplicatorState newState) {
final ReplicatorOptions replicatorOpts = Requires.requireNonNull(replicator.getOpts(), "replicatorOptions");
final Node node = Requires.requireNonNull(replicatorOpts.getNode(), "node");
final PeerId peer = Requires.requireNonNull(replicatorOpts.getPeerId(), "peer");
final List<ReplicatorStateListener> listenerList = node.getReplicatorStatueListeners();
for (int i = 0; i < listenerList.size(); i++) {
final ReplicatorStateListener listener = listenerList.get(i);
if (listener != null) {
try {
switch(event) {
case CREATED:
RpcUtils.runInThread(() -> listener.onCreated(peer));
break;
case ERROR:
RpcUtils.runInThread(() -> listener.onError(peer, status));
break;
case DESTROYED:
RpcUtils.runInThread(() -> listener.onDestroyed(peer));
break;
case STATE_CHANGED:
RpcUtils.runInThread(() -> listener.stateChanged(peer, newState));
default:
break;
}
} catch (final Exception e) {
LOG.error("Fail to notify ReplicatorStatusListener, listener={}, event={}.", listener, event);
}
}
}
}
Aggregations