Search in sources :

Example 1 with RepeatedTimer

use of io.dingodb.raft.util.RepeatedTimer 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());
                }
            }
        });
    }
}
Also used : Status(io.dingodb.raft.Status) FSMCallerOptions(io.dingodb.raft.option.FSMCallerOptions) RpcRequestClosure(io.dingodb.raft.rpc.RpcRequestClosure) StringUtils(org.apache.commons.lang.StringUtils) Describer(io.dingodb.raft.util.Describer) LongHeldDetectingReadWriteLock(io.dingodb.raft.util.concurrent.LongHeldDetectingReadWriteLock) ThreadHelper(io.dingodb.raft.util.ThreadHelper) LogManager(io.dingodb.raft.storage.LogManager) RaftClientService(io.dingodb.raft.rpc.RaftClientService) ReadWriteLock(java.util.concurrent.locks.ReadWriteLock) SynchronizedClosure(io.dingodb.raft.closure.SynchronizedClosure) LogManagerOptions(io.dingodb.raft.option.LogManagerOptions) Set(java.util.Set) Configuration(io.dingodb.raft.conf.Configuration) Utils(io.dingodb.raft.util.Utils) RaftOutter(io.dingodb.raft.entity.RaftOutter) EnumOutter(io.dingodb.raft.entity.EnumOutter) CountDownLatch(java.util.concurrent.CountDownLatch) RaftTimerFactory(io.dingodb.raft.util.timer.RaftTimerFactory) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) LogId(io.dingodb.raft.entity.LogId) JRaftServiceLoader(io.dingodb.raft.util.JRaftServiceLoader) SystemPropertyUtil(io.dingodb.raft.util.SystemPropertyUtil) JRaftUtils(io.dingodb.raft.JRaftUtils) LogExceptionHandler(io.dingodb.raft.util.LogExceptionHandler) ArrayList(java.util.ArrayList) JRaftServiceFactory(io.dingodb.raft.JRaftServiceFactory) ReadOnlyOption(io.dingodb.raft.option.ReadOnlyOption) BootstrapOptions(io.dingodb.raft.option.BootstrapOptions) LogStorage(io.dingodb.raft.storage.LogStorage) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) EventHandler(com.lmax.disruptor.EventHandler) LinkedHashSet(java.util.LinkedHashSet) DisruptorMetricSet(io.dingodb.raft.util.DisruptorMetricSet) DefaultRaftClientService(io.dingodb.raft.rpc.impl.core.DefaultRaftClientService) SnapshotExecutorImpl(io.dingodb.raft.storage.snapshot.SnapshotExecutorImpl) NodeManager(io.dingodb.raft.NodeManager) BallotBoxOptions(io.dingodb.raft.option.BallotBoxOptions) Lock(java.util.concurrent.locks.Lock) Ballot(io.dingodb.raft.entity.Ballot) PeerId(io.dingodb.raft.entity.PeerId) ReadOnlyServiceOptions(io.dingodb.raft.option.ReadOnlyServiceOptions) ConfigurationManager(io.dingodb.raft.conf.ConfigurationManager) SnapshotExecutor(io.dingodb.raft.storage.SnapshotExecutor) Disruptor(com.lmax.disruptor.dsl.Disruptor) RaftServerService(io.dingodb.raft.rpc.RaftServerService) ThreadId(io.dingodb.raft.util.ThreadId) ScheduledFuture(java.util.concurrent.ScheduledFuture) LoggerFactory(org.slf4j.LoggerFactory) ClosureQueueImpl(io.dingodb.raft.closure.ClosureQueueImpl) ByteBuffer(java.nio.ByteBuffer) RaftMetaStorageOptions(io.dingodb.raft.option.RaftMetaStorageOptions) SignalHelper(io.dingodb.raft.util.SignalHelper) BlockingWaitStrategy(com.lmax.disruptor.BlockingWaitStrategy) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CatchUpClosure(io.dingodb.raft.closure.CatchUpClosure) Task(io.dingodb.raft.entity.Task) RaftOptions(io.dingodb.raft.option.RaftOptions) Collection(java.util.Collection) Status(io.dingodb.raft.Status) ReplicatorGroupOptions(io.dingodb.raft.option.ReplicatorGroupOptions) Collectors(java.util.stream.Collectors) FSMCaller(io.dingodb.raft.FSMCaller) DisruptorBuilder(io.dingodb.raft.util.DisruptorBuilder) RpcResponseClosureAdapter(io.dingodb.raft.rpc.RpcResponseClosureAdapter) List(java.util.List) NodeId(io.dingodb.raft.entity.NodeId) RpcResponseClosure(io.dingodb.raft.rpc.RpcResponseClosure) RaftException(io.dingodb.raft.error.RaftException) Requires(io.dingodb.raft.util.Requires) RaftError(io.dingodb.raft.error.RaftError) UserLog(io.dingodb.raft.entity.UserLog) LogEntry(io.dingodb.raft.entity.LogEntry) HashSet(java.util.HashSet) RaftMetaStorage(io.dingodb.raft.storage.RaftMetaStorage) SnapshotExecutorOptions(io.dingodb.raft.option.SnapshotExecutorOptions) ConfigurationEntry(io.dingodb.raft.conf.ConfigurationEntry) ReadOnlyService(io.dingodb.raft.ReadOnlyService) OnlyForTest(io.dingodb.raft.util.OnlyForTest) ReadIndexClosure(io.dingodb.raft.closure.ReadIndexClosure) LogIndexOutOfBoundsException(io.dingodb.raft.error.LogIndexOutOfBoundsException) Logger(org.slf4j.Logger) NamedThreadFactory(io.dingodb.raft.util.NamedThreadFactory) ClosureQueue(io.dingodb.raft.closure.ClosureQueue) RingBuffer(com.lmax.disruptor.RingBuffer) Closure(io.dingodb.raft.Closure) ProducerType(com.lmax.disruptor.dsl.ProducerType) Node(io.dingodb.raft.Node) Platform(io.dingodb.raft.util.Platform) NodeOptions(io.dingodb.raft.option.NodeOptions) LogNotFoundException(io.dingodb.raft.error.LogNotFoundException) ReplicatorGroup(io.dingodb.raft.ReplicatorGroup) TimeUnit(java.util.concurrent.TimeUnit) JRaftSignalHandler(io.dingodb.raft.util.JRaftSignalHandler) RpcFactoryHelper(io.dingodb.raft.util.RpcFactoryHelper) EventTranslator(com.lmax.disruptor.EventTranslator) LogManagerImpl(io.dingodb.raft.storage.impl.LogManagerImpl) RepeatedTimer(io.dingodb.raft.util.RepeatedTimer) Message(com.google.protobuf.Message) RpcRequests(io.dingodb.raft.rpc.RpcRequests) LeaderChangeContext(io.dingodb.raft.entity.LeaderChangeContext) EventFactory(com.lmax.disruptor.EventFactory) RpcRequestClosure(io.dingodb.raft.rpc.RpcRequestClosure) SynchronizedClosure(io.dingodb.raft.closure.SynchronizedClosure) CatchUpClosure(io.dingodb.raft.closure.CatchUpClosure) RpcResponseClosure(io.dingodb.raft.rpc.RpcResponseClosure) ReadIndexClosure(io.dingodb.raft.closure.ReadIndexClosure) Closure(io.dingodb.raft.Closure) RepeatedTimer(io.dingodb.raft.util.RepeatedTimer) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 2 with RepeatedTimer

use of io.dingodb.raft.util.RepeatedTimer in project dingo by dingodb.

the class NodeImpl method init.

@Override
public boolean init(final NodeOptions opts) {
    Requires.requireNonNull(opts, "Null node options");
    Requires.requireNonNull(opts.getRaftOptions(), "Null raft options");
    Requires.requireNonNull(opts.getServiceFactory(), "Null jraft service factory");
    this.serviceFactory = opts.getServiceFactory();
    this.options = opts;
    this.raftOptions = opts.getRaftOptions();
    this.metrics = new NodeMetrics(opts.isEnableMetrics());
    this.serverId.setPriority(opts.getElectionPriority());
    this.electionTimeoutCounter = 0;
    if (this.serverId.getIp().equals(Utils.IP_ANY)) {
        LOG.error("Node can't started from IP_ANY.");
        return false;
    }
    if (!NodeManager.getInstance().serverExists(this.serverId.getEndpoint())) {
        LOG.error("No RPC server attached to, did you forget to call addService?");
        return false;
    }
    this.timerManager = TIMER_FACTORY.getRaftScheduler(this.options.isSharedTimerPool(), this.options.getTimerPoolSize(), "JRaft-Node-ScheduleThreadPool");
    // Init timers
    final String suffix = getNodeId().toString();
    String name = "JRaft-VoteTimer-" + suffix;
    this.voteTimer = new RepeatedTimer(name, this.options.getElectionTimeoutMs(), TIMER_FACTORY.getVoteTimer(this.options.isSharedVoteTimer(), name)) {

        @Override
        protected void onTrigger() {
            handleVoteTimeout();
        }

        @Override
        protected int adjustTimeout(final int timeoutMs) {
            return randomTimeout(timeoutMs);
        }
    };
    name = "JRaft-ElectionTimer-" + suffix;
    this.electionTimer = new RepeatedTimer(name, this.options.getElectionTimeoutMs(), TIMER_FACTORY.getElectionTimer(this.options.isSharedElectionTimer(), name)) {

        @Override
        protected void onTrigger() {
            handleElectionTimeout();
        }

        @Override
        protected int adjustTimeout(final int timeoutMs) {
            return randomTimeout(timeoutMs);
        }
    };
    name = "JRaft-StepDownTimer-" + suffix;
    this.stepDownTimer = new RepeatedTimer(name, this.options.getElectionTimeoutMs() >> 1, TIMER_FACTORY.getStepDownTimer(this.options.isSharedStepDownTimer(), name)) {

        @Override
        protected void onTrigger() {
            handleStepDownTimeout();
        }
    };
    name = "JRaft-SnapshotTimer-" + suffix;
    this.snapshotTimer = new RepeatedTimer(name, this.options.getSnapshotIntervalSecs() * 1000, TIMER_FACTORY.getSnapshotTimer(this.options.isSharedSnapshotTimer(), name)) {

        private volatile boolean firstSchedule = true;

        @Override
        protected void onTrigger() {
            handleSnapshotTimeout();
        }

        @Override
        protected int adjustTimeout(final int timeoutMs) {
            if (!this.firstSchedule) {
                return timeoutMs;
            }
            // Randomize the first snapshot trigger timeout
            this.firstSchedule = false;
            if (timeoutMs > 0) {
                int half = timeoutMs / 2;
                return half + ThreadLocalRandom.current().nextInt(half);
            } else {
                return timeoutMs;
            }
        }
    };
    this.configManager = new ConfigurationManager();
    this.applyDisruptor = // 
    DisruptorBuilder.<LogEntryAndClosure>newInstance().setRingBufferSize(// 
    this.raftOptions.getDisruptorBufferSize()).setEventFactory(// 
    new LogEntryAndClosureFactory()).setThreadFactory(// 
    new NamedThreadFactory("JRaft-NodeImpl-Disruptor-", true)).setProducerType(// 
    ProducerType.MULTI).setWaitStrategy(// 
    new BlockingWaitStrategy()).build();
    this.applyDisruptor.handleEventsWith(new LogEntryAndClosureHandler());
    this.applyDisruptor.setDefaultExceptionHandler(new LogExceptionHandler<Object>(getClass().getSimpleName()));
    this.applyQueue = this.applyDisruptor.start();
    if (this.metrics.getMetricRegistry() != null) {
        this.metrics.getMetricRegistry().register("jraft-node-impl-disruptor", new DisruptorMetricSet(this.applyQueue));
    }
    this.fsmCaller = new FSMCallerImpl();
    if (!initLogStorage()) {
        LOG.error("Node {} initLogStorage failed.", getNodeId());
        return false;
    }
    if (!initMetaStorage()) {
        LOG.error("Node {} initMetaStorage failed.", getNodeId());
        return false;
    }
    if (!initFSMCaller(new LogId(0, 0))) {
        LOG.error("Node {} initFSMCaller failed.", getNodeId());
        return false;
    }
    this.ballotBox = new BallotBox();
    final BallotBoxOptions ballotBoxOpts = new BallotBoxOptions();
    ballotBoxOpts.setWaiter(this.fsmCaller);
    ballotBoxOpts.setClosureQueue(this.closureQueue);
    if (!this.ballotBox.init(ballotBoxOpts)) {
        LOG.error("Node {} init ballotBox failed.", getNodeId());
        return false;
    }
    if (!initSnapshotStorage()) {
        LOG.error("Node {} initSnapshotStorage failed.", getNodeId());
        return false;
    }
    final Status st = this.logManager.checkConsistency();
    if (!st.isOk()) {
        LOG.error("Node {} is initialized with inconsistent log, status={}.", getNodeId(), st);
        return false;
    }
    this.conf = new ConfigurationEntry();
    this.conf.setId(new LogId());
    // if have log using conf in log, else using conf in options
    if (this.logManager.getLastLogIndex() > 0) {
        checkAndSetConfiguration(false);
    } else {
        this.conf.setConf(this.options.getInitialConf());
        // initially set to max(priority of all nodes)
        this.targetPriority = getMaxPriorityOfNodes(this.conf.getConf().getPeers());
    }
    if (!this.conf.isEmpty()) {
        Requires.requireTrue(this.conf.isValid(), "Invalid conf: %s", this.conf);
    } else {
        LOG.info("Init node {} with empty conf.", this.serverId);
    }
    // TODO RPC service and ReplicatorGroup is in cycle dependent, refactor it
    this.replicatorGroup = new ReplicatorGroupImpl();
    this.rpcService = new DefaultRaftClientService(this.replicatorGroup);
    final ReplicatorGroupOptions rgOpts = new ReplicatorGroupOptions();
    rgOpts.setHeartbeatTimeoutMs(heartbeatTimeout(this.options.getElectionTimeoutMs()));
    rgOpts.setElectionTimeoutMs(this.options.getElectionTimeoutMs());
    rgOpts.setLogManager(this.logManager);
    rgOpts.setBallotBox(this.ballotBox);
    rgOpts.setNode(this);
    rgOpts.setRaftRpcClientService(this.rpcService);
    rgOpts.setSnapshotStorage(this.snapshotExecutor != null ? this.snapshotExecutor.getSnapshotStorage() : null);
    rgOpts.setRaftOptions(this.raftOptions);
    rgOpts.setTimerManager(this.timerManager);
    // Adds metric registry to RPC service.
    this.options.setMetricRegistry(this.metrics.getMetricRegistry());
    if (!this.rpcService.init(this.options)) {
        LOG.error("Fail to init rpc service.");
        return false;
    }
    this.replicatorGroup.init(new NodeId(this.groupId, this.serverId), rgOpts);
    this.readOnlyService = new ReadOnlyServiceImpl();
    final ReadOnlyServiceOptions rosOpts = new ReadOnlyServiceOptions();
    rosOpts.setFsmCaller(this.fsmCaller);
    rosOpts.setNode(this);
    rosOpts.setRaftOptions(this.raftOptions);
    if (!this.readOnlyService.init(rosOpts)) {
        LOG.error("Fail to init readOnlyService.");
        return false;
    }
    // set state to follower
    this.state = State.STATE_FOLLOWER;
    if (LOG.isInfoEnabled()) {
        LOG.info("Node {} init, term={}, lastLogId={}, conf={}, oldConf={}.", getNodeId(), this.currTerm, this.logManager.getLastLogId(false), this.conf.getConf(), this.conf.getOldConf());
    }
    if (this.snapshotExecutor != null && this.options.getSnapshotIntervalSecs() > 0) {
        LOG.debug("Node {} start snapshot timer, term={}.", getNodeId(), this.currTerm);
        this.snapshotTimer.start();
    }
    if (!this.conf.isEmpty()) {
        stepDown(this.currTerm, false, new Status());
    }
    if (!NodeManager.getInstance().add(this)) {
        LOG.error("NodeManager add {} failed.", getNodeId());
        return false;
    }
    // Now the raft node is started , have to acquire the writeLock to avoid race
    // conditions
    this.writeLock.lock();
    if (this.conf.isStable() && this.conf.getConf().size() == 1 && this.conf.getConf().contains(this.serverId)) {
        // The group contains only this server which must be the LEADER, trigger
        // the timer immediately.
        electSelf();
    } else {
        this.writeLock.unlock();
    }
    return true;
}
Also used : BallotBoxOptions(io.dingodb.raft.option.BallotBoxOptions) ReadOnlyServiceOptions(io.dingodb.raft.option.ReadOnlyServiceOptions) RepeatedTimer(io.dingodb.raft.util.RepeatedTimer) ConfigurationManager(io.dingodb.raft.conf.ConfigurationManager) ConfigurationEntry(io.dingodb.raft.conf.ConfigurationEntry) Status(io.dingodb.raft.Status) BlockingWaitStrategy(com.lmax.disruptor.BlockingWaitStrategy) NamedThreadFactory(io.dingodb.raft.util.NamedThreadFactory) DisruptorMetricSet(io.dingodb.raft.util.DisruptorMetricSet) ReplicatorGroupOptions(io.dingodb.raft.option.ReplicatorGroupOptions) NodeId(io.dingodb.raft.entity.NodeId) DefaultRaftClientService(io.dingodb.raft.rpc.impl.core.DefaultRaftClientService) LogId(io.dingodb.raft.entity.LogId)

Aggregations

BlockingWaitStrategy (com.lmax.disruptor.BlockingWaitStrategy)2 Status (io.dingodb.raft.Status)2 ConfigurationEntry (io.dingodb.raft.conf.ConfigurationEntry)2 ConfigurationManager (io.dingodb.raft.conf.ConfigurationManager)2 LogId (io.dingodb.raft.entity.LogId)2 NodeId (io.dingodb.raft.entity.NodeId)2 BallotBoxOptions (io.dingodb.raft.option.BallotBoxOptions)2 ReadOnlyServiceOptions (io.dingodb.raft.option.ReadOnlyServiceOptions)2 ReplicatorGroupOptions (io.dingodb.raft.option.ReplicatorGroupOptions)2 DefaultRaftClientService (io.dingodb.raft.rpc.impl.core.DefaultRaftClientService)2 DisruptorMetricSet (io.dingodb.raft.util.DisruptorMetricSet)2 NamedThreadFactory (io.dingodb.raft.util.NamedThreadFactory)2 RepeatedTimer (io.dingodb.raft.util.RepeatedTimer)2 Message (com.google.protobuf.Message)1 EventFactory (com.lmax.disruptor.EventFactory)1 EventHandler (com.lmax.disruptor.EventHandler)1 EventTranslator (com.lmax.disruptor.EventTranslator)1 RingBuffer (com.lmax.disruptor.RingBuffer)1 Disruptor (com.lmax.disruptor.dsl.Disruptor)1 ProducerType (com.lmax.disruptor.dsl.ProducerType)1