Search in sources :

Example 61 with Status

use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.

the class InstructionProcessor method processSplit.

private boolean processSplit(final Instruction instruction) {
    try {
        final Instruction.RangeSplit rangeSplit = instruction.getRangeSplit();
        if (rangeSplit == null) {
            return false;
        }
        final Long newRegionId = rangeSplit.getNewRegionId();
        if (newRegionId == null) {
            LOG.error("RangeSplit#newRegionId must not be null, {}.", instruction);
            return false;
        }
        final Region region = instruction.getRegion();
        final long regionId = region.getId();
        final RegionEngine engine = this.storeEngine.getRegionEngine(regionId);
        if (engine == null) {
            LOG.error("Could not found regionEngine, {}.", instruction);
            return false;
        }
        if (!region.equals(engine.getRegion())) {
            LOG.warn("Instruction [{}] is out of date.", instruction);
            return false;
        }
        final CompletableFuture<Status> future = new CompletableFuture<>();
        this.storeEngine.applySplit(regionId, newRegionId, new BaseKVStoreClosure() {

            @Override
            public void run(Status status) {
                future.complete(status);
            }
        });
        final Status status = future.get(20, TimeUnit.SECONDS);
        final boolean ret = status.isOk();
        if (ret) {
            LOG.info("Range-split succeeded, instruction: {}.", instruction);
        } else {
            LOG.warn("Range-split failed: {}, instruction: {}.", status, instruction);
        }
        return ret;
    } catch (final Throwable t) {
        LOG.error("Caught an exception on #processSplit: {}.", StackTraceUtil.stackTrace(t));
        return false;
    }
}
Also used : Status(com.alipay.sofa.jraft.Status) BaseKVStoreClosure(com.alipay.sofa.jraft.rhea.storage.BaseKVStoreClosure) Instruction(com.alipay.sofa.jraft.rhea.metadata.Instruction) CompletableFuture(java.util.concurrent.CompletableFuture) Region(com.alipay.sofa.jraft.rhea.metadata.Region) RegionEngine(com.alipay.sofa.jraft.rhea.RegionEngine)

Example 62 with Status

use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.

the class KVStoreStateMachine method onApply.

@Override
public void onApply(final Iterator it) {
    int index = 0;
    int applied = 0;
    try {
        KVStateOutputList kvStates = KVStateOutputList.newInstance();
        while (it.hasNext()) {
            KVOperation kvOp;
            final KVClosureAdapter done = (KVClosureAdapter) it.done();
            if (done != null) {
                kvOp = done.getOperation();
            } else {
                final ByteBuffer buf = it.getData();
                try {
                    if (buf.hasArray()) {
                        kvOp = this.serializer.readObject(buf.array(), KVOperation.class);
                    } else {
                        kvOp = this.serializer.readObject(buf, KVOperation.class);
                    }
                } catch (final Throwable t) {
                    ++index;
                    throw new StoreCodecException("Decode operation error", t);
                }
            }
            final KVState first = kvStates.getFirstElement();
            if (first != null && !first.isSameOp(kvOp)) {
                applied += batchApplyAndRecycle(first.getOpByte(), kvStates);
                kvStates = KVStateOutputList.newInstance();
            }
            kvStates.add(KVState.of(kvOp, done));
            ++index;
            it.next();
        }
        if (!kvStates.isEmpty()) {
            final KVState first = kvStates.getFirstElement();
            assert first != null;
            applied += batchApplyAndRecycle(first.getOpByte(), kvStates);
        }
    } catch (final Throwable t) {
        LOG.error("StateMachine meet critical error: {}.", StackTraceUtil.stackTrace(t));
        it.setErrorAndRollback(index - applied, new Status(RaftError.ESTATEMACHINE, "StateMachine meet critical error: %s.", t.getMessage()));
    } finally {
        // metrics: qps
        this.applyMeter.mark(applied);
    }
}
Also used : Status(com.alipay.sofa.jraft.Status) StoreCodecException(com.alipay.sofa.jraft.rhea.errors.StoreCodecException) ByteBuffer(java.nio.ByteBuffer)

Example 63 with Status

use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.

the class BaseRawKVStore method setFailure.

/**
 * Sets failure, if current node is a leader, reply to
 * client failure response.
 *
 * @param closure callback
 * @param message error message
 */
static void setFailure(final KVStoreClosure closure, final String message) {
    if (closure != null) {
        // closure is null on follower node
        closure.setError(Errors.STORAGE_ERROR);
        closure.run(new Status(RaftError.EIO, message));
    }
}
Also used : Status(com.alipay.sofa.jraft.Status)

Example 64 with Status

use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.

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(com.alipay.sofa.jraft.option.BallotBoxOptions) ReadOnlyServiceOptions(com.alipay.sofa.jraft.option.ReadOnlyServiceOptions) RepeatedTimer(com.alipay.sofa.jraft.util.RepeatedTimer) ConfigurationManager(com.alipay.sofa.jraft.conf.ConfigurationManager) ConfigurationEntry(com.alipay.sofa.jraft.conf.ConfigurationEntry) Status(com.alipay.sofa.jraft.Status) BlockingWaitStrategy(com.lmax.disruptor.BlockingWaitStrategy) NamedThreadFactory(com.alipay.sofa.jraft.util.NamedThreadFactory) DisruptorMetricSet(com.alipay.sofa.jraft.util.DisruptorMetricSet) ReplicatorGroupOptions(com.alipay.sofa.jraft.option.ReplicatorGroupOptions) NodeId(com.alipay.sofa.jraft.entity.NodeId) DefaultRaftClientService(com.alipay.sofa.jraft.rpc.impl.core.DefaultRaftClientService) LogId(com.alipay.sofa.jraft.entity.LogId)

Example 65 with Status

use of com.alipay.sofa.jraft.Status in project sofa-jraft by sofastack.

the class NodeImpl method resetPeers.

@Override
public Status resetPeers(final Configuration newPeers) {
    Requires.requireNonNull(newPeers, "Null new peers");
    Requires.requireTrue(!newPeers.isEmpty(), "Empty new peers");
    Requires.requireTrue(newPeers.isValid(), "Invalid new peers: %s", newPeers);
    this.writeLock.lock();
    try {
        if (newPeers.isEmpty()) {
            LOG.warn("Node {} set empty peers.", getNodeId());
            return new Status(RaftError.EINVAL, "newPeers is empty");
        }
        if (!this.state.isActive()) {
            LOG.warn("Node {} is in state {}, can't set peers.", getNodeId(), this.state);
            return new Status(RaftError.EPERM, "Bad state: %s", this.state);
        }
        // bootstrap?
        if (this.conf.getConf().isEmpty()) {
            LOG.info("Node {} set peers to {} from empty.", getNodeId(), newPeers);
            this.conf.setConf(newPeers);
            stepDown(this.currTerm + 1, false, new Status(RaftError.ESETPEER, "Set peer from empty configuration"));
            return Status.OK();
        }
        if (this.state == State.STATE_LEADER && this.confCtx.isBusy()) {
            LOG.warn("Node {} set peers need wait current conf changing.", getNodeId());
            return new Status(RaftError.EBUSY, "Changing to another configuration");
        }
        // check equal, maybe retry direct return
        if (this.conf.getConf().equals(newPeers)) {
            return Status.OK();
        }
        final Configuration newConf = new Configuration(newPeers);
        LOG.info("Node {} set peers from {} to {}.", getNodeId(), this.conf.getConf(), newPeers);
        this.conf.setConf(newConf);
        this.conf.getOldConf().reset();
        stepDown(this.currTerm + 1, false, new Status(RaftError.ESETPEER, "Raft node set peer normally"));
        return Status.OK();
    } finally {
        this.writeLock.unlock();
    }
}
Also used : Status(com.alipay.sofa.jraft.Status) Configuration(com.alipay.sofa.jraft.conf.Configuration)

Aggregations

Status (com.alipay.sofa.jraft.Status)213 Test (org.junit.Test)63 PeerId (com.alipay.sofa.jraft.entity.PeerId)55 CountDownLatch (java.util.concurrent.CountDownLatch)36 BaseKVStoreClosure (com.alipay.sofa.jraft.rhea.storage.BaseKVStoreClosure)33 Configuration (com.alipay.sofa.jraft.conf.Configuration)25 Message (com.google.protobuf.Message)24 ReadIndexClosure (com.alipay.sofa.jraft.closure.ReadIndexClosure)22 ArrayList (java.util.ArrayList)22 Node (com.alipay.sofa.jraft.Node)21 Closure (com.alipay.sofa.jraft.Closure)17 Task (com.alipay.sofa.jraft.entity.Task)17 ByteBuffer (java.nio.ByteBuffer)16 Endpoint (com.alipay.sofa.jraft.util.Endpoint)15 List (java.util.List)15 RaftException (com.alipay.sofa.jraft.error.RaftException)14 LogEntry (com.alipay.sofa.jraft.entity.LogEntry)12 LogId (com.alipay.sofa.jraft.entity.LogId)12 KVStoreClosure (com.alipay.sofa.jraft.rhea.storage.KVStoreClosure)12 JRaftException (com.alipay.sofa.jraft.error.JRaftException)11