Search in sources :

Example 66 with Status

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

the class NodeImpl method handleRequestVoteRequest.

@Override
public Message handleRequestVoteRequest(final RequestVoteRequest request) {
    boolean doUnlock = true;
    this.writeLock.lock();
    try {
        if (!this.state.isActive()) {
            LOG.warn("Node {} is not in active state, currTerm={}.", getNodeId(), this.currTerm);
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RequestVoteResponse.getDefaultInstance(), RaftError.EINVAL, "Node %s is not in active state, state %s.", getNodeId(), this.state.name());
        }
        final PeerId candidateId = new PeerId();
        if (!candidateId.parse(request.getServerId())) {
            LOG.warn("Node {} received RequestVoteRequest from {} serverId bad format.", getNodeId(), request.getServerId());
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RequestVoteResponse.getDefaultInstance(), RaftError.EINVAL, "Parse candidateId failed: %s.", request.getServerId());
        }
        // noinspection ConstantConditions
        do {
            // check term
            if (request.getTerm() >= this.currTerm) {
                LOG.info("Node {} received RequestVoteRequest from {}, term={}, currTerm={}.", getNodeId(), request.getServerId(), request.getTerm(), this.currTerm);
                // increase current term, change state to follower
                if (request.getTerm() > this.currTerm) {
                    stepDown(request.getTerm(), false, new Status(RaftError.EHIGHERTERMRESPONSE, "Raft node receives higher term RequestVoteRequest."));
                }
            } else {
                // ignore older term
                LOG.info("Node {} ignore RequestVoteRequest from {}, term={}, currTerm={}.", getNodeId(), request.getServerId(), request.getTerm(), this.currTerm);
                break;
            }
            doUnlock = false;
            this.writeLock.unlock();
            final LogId lastLogId = this.logManager.getLastLogId(true);
            doUnlock = true;
            this.writeLock.lock();
            // vote need ABA check after unlock&writeLock
            if (request.getTerm() != this.currTerm) {
                LOG.warn("Node {} raise term {} when get lastLogId.", getNodeId(), this.currTerm);
                break;
            }
            final boolean logIsOk = new LogId(request.getLastLogIndex(), request.getLastLogTerm()).compareTo(lastLogId) >= 0;
            if (logIsOk && (this.votedId == null || this.votedId.isEmpty())) {
                stepDown(request.getTerm(), false, new Status(RaftError.EVOTEFORCANDIDATE, "Raft node votes for some candidate, step down to restart election_timer."));
                this.votedId = candidateId.copy();
                this.metaStorage.setVotedFor(candidateId);
            }
        } while (false);
        return // 
        RequestVoteResponse.newBuilder().setTerm(// 
        this.currTerm).setGranted(// 
        request.getTerm() == this.currTerm && candidateId.equals(this.votedId)).build();
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
    }
}
Also used : Status(com.alipay.sofa.jraft.Status) LogId(com.alipay.sofa.jraft.entity.LogId) PeerId(com.alipay.sofa.jraft.entity.PeerId)

Example 67 with Status

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

Example 68 with Status

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

the class NodeImpl method readLeader.

private void readLeader(final ReadIndexRequest request, final ReadIndexResponse.Builder respBuilder, final RpcResponseClosure<ReadIndexResponse> closure) {
    final int quorum = getQuorum();
    if (quorum <= 1) {
        // Only one peer, fast path.
        // 
        respBuilder.setSuccess(true).setIndex(this.ballotBox.getLastCommittedIndex());
        closure.setResponse(respBuilder.build());
        closure.run(Status.OK());
        return;
    }
    final long lastCommittedIndex = this.ballotBox.getLastCommittedIndex();
    if (this.logManager.getTerm(lastCommittedIndex) != this.currTerm) {
        // Reject read only request when this leader has not committed any log entry at its term
        closure.run(new Status(RaftError.EAGAIN, "ReadIndex request rejected because leader has not committed any log entry at its term, logIndex=%d, currTerm=%d.", lastCommittedIndex, this.currTerm));
        return;
    }
    respBuilder.setIndex(lastCommittedIndex);
    if (request.getPeerId() != null) {
        // request from follower or learner, check if the follower/learner is in current conf.
        final PeerId peer = new PeerId();
        peer.parse(request.getServerId());
        if (!this.conf.contains(peer) && !this.conf.containsLearner(peer)) {
            closure.run(new Status(RaftError.EPERM, "Peer %s is not in current configuration: %s.", peer, this.conf));
            return;
        }
    }
    ReadOnlyOption readOnlyOpt = this.raftOptions.getReadOnlyOptions();
    if (readOnlyOpt == ReadOnlyOption.ReadOnlyLeaseBased && !isLeaderLeaseValid()) {
        // If leader lease timeout, we must change option to ReadOnlySafe
        readOnlyOpt = ReadOnlyOption.ReadOnlySafe;
    }
    switch(readOnlyOpt) {
        case ReadOnlySafe:
            final List<PeerId> peers = this.conf.getConf().getPeers();
            Requires.requireTrue(peers != null && !peers.isEmpty(), "Empty peers");
            final ReadIndexHeartbeatResponseClosure heartbeatDone = new ReadIndexHeartbeatResponseClosure(closure, respBuilder, quorum, peers.size());
            // Send heartbeat requests to followers
            for (final PeerId peer : peers) {
                if (peer.equals(this.serverId)) {
                    continue;
                }
                this.replicatorGroup.sendHeartbeat(peer, heartbeatDone);
            }
            break;
        case ReadOnlyLeaseBased:
            // Responses to followers and local node.
            respBuilder.setSuccess(true);
            closure.setResponse(respBuilder.build());
            closure.run(Status.OK());
            break;
    }
}
Also used : Status(com.alipay.sofa.jraft.Status) ReadOnlyOption(com.alipay.sofa.jraft.option.ReadOnlyOption) PeerId(com.alipay.sofa.jraft.entity.PeerId)

Example 69 with Status

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

the class NodeImpl method handleTimeoutNowRequest.

@Override
public Message handleTimeoutNowRequest(final TimeoutNowRequest request, final RpcRequestClosure done) {
    boolean doUnlock = true;
    this.writeLock.lock();
    try {
        if (request.getTerm() != this.currTerm) {
            final long savedCurrTerm = this.currTerm;
            if (request.getTerm() > this.currTerm) {
                stepDown(request.getTerm(), false, new Status(RaftError.EHIGHERTERMREQUEST, "Raft node receives higher term request"));
            }
            LOG.info("Node {} received TimeoutNowRequest from {} while currTerm={} didn't match requestTerm={}.", getNodeId(), request.getPeerId(), savedCurrTerm, request.getTerm());
            return // 
            TimeoutNowResponse.newBuilder().setTerm(// 
            this.currTerm).setSuccess(// 
            false).build();
        }
        if (this.state != State.STATE_FOLLOWER) {
            LOG.info("Node {} received TimeoutNowRequest from {}, while state={}, term={}.", getNodeId(), request.getServerId(), this.state, this.currTerm);
            return // 
            TimeoutNowResponse.newBuilder().setTerm(// 
            this.currTerm).setSuccess(// 
            false).build();
        }
        final long savedTerm = this.currTerm;
        final TimeoutNowResponse resp = // 
        TimeoutNowResponse.newBuilder().setTerm(// 
        this.currTerm + 1).setSuccess(// 
        true).build();
        // Parallelize response and election
        done.sendResponse(resp);
        doUnlock = false;
        electSelf();
        LOG.info("Node {} received TimeoutNowRequest from {}, term={}.", getNodeId(), request.getServerId(), savedTerm);
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
    }
    return null;
}
Also used : Status(com.alipay.sofa.jraft.Status) TimeoutNowResponse(com.alipay.sofa.jraft.rpc.RpcRequests.TimeoutNowResponse)

Example 70 with Status

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

the class NodeImpl method handleRequestVoteResponse.

public void handleRequestVoteResponse(final PeerId peerId, final long term, final RequestVoteResponse response) {
    this.writeLock.lock();
    try {
        if (this.state != State.STATE_CANDIDATE) {
            LOG.warn("Node {} received invalid RequestVoteResponse from {}, state not in STATE_CANDIDATE but {}.", getNodeId(), peerId, this.state);
            return;
        }
        // check stale term
        if (term != this.currTerm) {
            LOG.warn("Node {} received stale RequestVoteResponse from {}, term={}, currTerm={}.", getNodeId(), peerId, term, this.currTerm);
            return;
        }
        // check response term
        if (response.getTerm() > this.currTerm) {
            LOG.warn("Node {} received invalid RequestVoteResponse from {}, term={}, expect={}.", getNodeId(), peerId, response.getTerm(), this.currTerm);
            stepDown(response.getTerm(), false, new Status(RaftError.EHIGHERTERMRESPONSE, "Raft node receives higher term request_vote_response."));
            return;
        }
        // check granted quorum?
        if (response.getGranted()) {
            this.voteCtx.grant(peerId);
            if (this.voteCtx.isGranted()) {
                becomeLeader();
            }
        }
    } finally {
        this.writeLock.unlock();
    }
}
Also used : Status(com.alipay.sofa.jraft.Status)

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