Search in sources :

Example 71 with PeerId

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

the class NodeImpl method transferLeadershipTo.

@Override
public Status transferLeadershipTo(final PeerId peer) {
    Requires.requireNonNull(peer, "Null peer");
    this.writeLock.lock();
    try {
        if (this.state != State.STATE_LEADER) {
            LOG.warn("Node {} can't transfer leadership to peer {} as it is in state {}.", getNodeId(), peer, this.state);
            return new Status(this.state == State.STATE_TRANSFERRING ? RaftError.EBUSY : RaftError.EPERM, "Not a leader");
        }
        if (this.confCtx.isBusy()) {
            // It's very messy to deal with the case when the |peer| received
            // TimeoutNowRequest and increase the term while somehow another leader
            // which was not replicated with the newest configuration has been
            // elected. If no add_peer with this very |peer| is to be invoked ever
            // after nor this peer is to be killed, this peer will spin in the voting
            // procedure and make the each new leader stepped down when the peer
            // reached vote timeout and it starts to vote (because it will increase
            // the term of the group)
            // To make things simple, refuse the operation and force users to
            // invoke transfer_leadership_to after configuration changing is
            // completed so that the peer's configuration is up-to-date when it
            // receives the TimeOutNowRequest.
            LOG.warn("Node {} refused to transfer leadership to peer {} when the leader is changing the configuration.", getNodeId(), peer);
            return new Status(RaftError.EBUSY, "Changing the configuration");
        }
        PeerId peerId = peer.copy();
        // last_log_id will be selected.
        if (peerId.equals(PeerId.ANY_PEER)) {
            LOG.info("Node {} starts to transfer leadership to any peer.", getNodeId());
            if ((peerId = this.replicatorGroup.findTheNextCandidate(this.conf)) == null) {
                return new Status(-1, "Candidate not found for any peer");
            }
        }
        if (peerId.equals(this.serverId)) {
            LOG.info("Node {} transferred leadership to self.", this.serverId);
            return Status.OK();
        }
        if (!this.conf.contains(peerId)) {
            LOG.info("Node {} refused to transfer leadership to peer {} as it is not in {}.", getNodeId(), peer, this.conf);
            return new Status(RaftError.EINVAL, "Not in current configuration");
        }
        final long lastLogIndex = this.logManager.getLastLogIndex();
        if (!this.replicatorGroup.transferLeadershipTo(peerId, lastLogIndex)) {
            LOG.warn("No such peer {}.", peer);
            return new Status(RaftError.EINVAL, "No such peer %s", peer);
        }
        this.state = State.STATE_TRANSFERRING;
        final Status status = new Status(RaftError.ETRANSFERLEADERSHIP, "Raft leader is transferring leadership to %s", peerId);
        onLeaderStop(status);
        LOG.info("Node {} starts to transfer leadership to peer {}.", getNodeId(), peer);
        final StopTransferArg stopArg = new StopTransferArg(this, this.currTerm, peerId);
        this.stopTransferArg = stopArg;
        this.transferTimer = this.timerManager.schedule(() -> onTransferTimeout(stopArg), this.options.getElectionTimeoutMs(), TimeUnit.MILLISECONDS);
    } finally {
        this.writeLock.unlock();
    }
    return Status.OK();
}
Also used : Status(com.alipay.sofa.jraft.Status) PeerId(com.alipay.sofa.jraft.entity.PeerId)

Example 72 with PeerId

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

the class NodeImpl method checkDeadNodes.

private boolean checkDeadNodes(final Configuration conf, final long monotonicNowMs, final boolean stepDownOnCheckFail) {
    // Check learner replicators at first.
    for (final PeerId peer : conf.getLearners()) {
        checkReplicator(peer);
    }
    // Ensure quorum nodes alive.
    final List<PeerId> peers = conf.listPeers();
    final Configuration deadNodes = new Configuration();
    if (checkDeadNodes0(peers, monotonicNowMs, true, deadNodes)) {
        return true;
    }
    if (stepDownOnCheckFail) {
        LOG.warn("Node {} steps down when alive nodes don't satisfy quorum, term={}, deadNodes={}, conf={}.", getNodeId(), this.currTerm, deadNodes, conf);
        final Status status = new Status();
        status.setError(RaftError.ERAFTTIMEDOUT, "Majority of the group dies: %d/%d", deadNodes.size(), peers.size());
        stepDown(this.currTerm, false, status);
    }
    return false;
}
Also used : Status(com.alipay.sofa.jraft.Status) Configuration(com.alipay.sofa.jraft.conf.Configuration) PeerId(com.alipay.sofa.jraft.entity.PeerId)

Example 73 with PeerId

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

the class NodeImpl method handleInstallSnapshot.

@Override
public Message handleInstallSnapshot(final InstallSnapshotRequest request, final RpcRequestClosure done) {
    if (this.snapshotExecutor == null) {
        return // 
        RpcFactoryHelper.responseFactory().newResponse(InstallSnapshotResponse.getDefaultInstance(), RaftError.EINVAL, "Not supported snapshot");
    }
    final PeerId serverId = new PeerId();
    if (!serverId.parse(request.getServerId())) {
        LOG.warn("Node {} ignore InstallSnapshotRequest from {} bad server id.", getNodeId(), request.getServerId());
        return // 
        RpcFactoryHelper.responseFactory().newResponse(InstallSnapshotResponse.getDefaultInstance(), RaftError.EINVAL, "Parse serverId failed: %s", request.getServerId());
    }
    this.writeLock.lock();
    try {
        if (!this.state.isActive()) {
            LOG.warn("Node {} ignore InstallSnapshotRequest as it is not in active state {}.", getNodeId(), this.state);
            return // 
            RpcFactoryHelper.responseFactory().newResponse(InstallSnapshotResponse.getDefaultInstance(), RaftError.EINVAL, "Node %s:%s is not in active state, state %s.", this.groupId, this.serverId, this.state.name());
        }
        if (request.getTerm() < this.currTerm) {
            LOG.warn("Node {} ignore stale InstallSnapshotRequest from {}, term={}, currTerm={}.", getNodeId(), request.getPeerId(), request.getTerm(), this.currTerm);
            return // 
            InstallSnapshotResponse.newBuilder().setTerm(// 
            this.currTerm).setSuccess(// 
            false).build();
        }
        checkStepDown(request.getTerm(), serverId);
        if (!serverId.equals(this.leaderId)) {
            LOG.error("Another peer {} declares that it is the leader at term {} which was occupied by leader {}.", serverId, this.currTerm, this.leaderId);
            // Increase the term by 1 and make both leaders step down to minimize the
            // loss of split brain
            stepDown(request.getTerm() + 1, false, new Status(RaftError.ELEADERCONFLICT, "More than one leader in the same term."));
            return // 
            InstallSnapshotResponse.newBuilder().setTerm(// 
            request.getTerm() + 1).setSuccess(// 
            false).build();
        }
    } finally {
        this.writeLock.unlock();
    }
    final long startMs = Utils.monotonicMs();
    try {
        if (LOG.isInfoEnabled()) {
            LOG.info("Node {} received InstallSnapshotRequest from {}, lastIncludedLogIndex={}, lastIncludedLogTerm={}, lastLogId={}.", getNodeId(), request.getServerId(), request.getMeta().getLastIncludedIndex(), request.getMeta().getLastIncludedTerm(), this.logManager.getLastLogId(false));
        }
        this.snapshotExecutor.installSnapshot(request, InstallSnapshotResponse.newBuilder(), done);
        return null;
    } finally {
        this.metrics.recordLatency("install-snapshot", Utils.monotonicMs() - startMs);
    }
}
Also used : Status(com.alipay.sofa.jraft.Status) PeerId(com.alipay.sofa.jraft.entity.PeerId)

Example 74 with PeerId

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

the class NodeImpl method handlePreVoteRequest.

@Override
public Message handlePreVoteRequest(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 PreVoteRequest from {} serverId bad format.", getNodeId(), request.getServerId());
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RequestVoteResponse.getDefaultInstance(), RaftError.EINVAL, "Parse candidateId failed: %s.", request.getServerId());
        }
        boolean granted = false;
        // noinspection ConstantConditions
        do {
            if (!this.conf.contains(candidateId)) {
                LOG.warn("Node {} ignore PreVoteRequest from {} as it is not in conf <{}>.", getNodeId(), request.getServerId(), this.conf);
                break;
            }
            if (this.leaderId != null && !this.leaderId.isEmpty() && isCurrentLeaderValid()) {
                LOG.info("Node {} ignore PreVoteRequest from {}, term={}, currTerm={}, because the leader {}'s lease is still valid.", getNodeId(), request.getServerId(), request.getTerm(), this.currTerm, this.leaderId);
                break;
            }
            if (request.getTerm() < this.currTerm) {
                LOG.info("Node {} ignore PreVoteRequest from {}, term={}, currTerm={}.", getNodeId(), request.getServerId(), request.getTerm(), this.currTerm);
                // A follower replicator may not be started when this node become leader, so we must check it.
                checkReplicator(candidateId);
                break;
            }
            // A follower replicator may not be started when this node become leader, so we must check it.
            // check replicator state
            checkReplicator(candidateId);
            doUnlock = false;
            this.writeLock.unlock();
            final LogId lastLogId = this.logManager.getLastLogId(true);
            doUnlock = true;
            this.writeLock.lock();
            final LogId requestLastLogId = new LogId(request.getLastLogIndex(), request.getLastLogTerm());
            granted = requestLastLogId.compareTo(lastLogId) >= 0;
            LOG.info("Node {} received PreVoteRequest from {}, term={}, currTerm={}, granted={}, requestLastLogId={}, lastLogId={}.", getNodeId(), request.getServerId(), request.getTerm(), this.currTerm, granted, requestLastLogId, lastLogId);
        } while (false);
        return // 
        RequestVoteResponse.newBuilder().setTerm(// 
        this.currTerm).setGranted(// 
        granted).build();
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
    }
}
Also used : LogId(com.alipay.sofa.jraft.entity.LogId) PeerId(com.alipay.sofa.jraft.entity.PeerId)

Example 75 with PeerId

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

the class NodeImpl method fillLogEntryPeers.

private void fillLogEntryPeers(final RaftOutter.EntryMeta entry, final LogEntry logEntry) {
    // TODO refactor
    if (entry.getPeersCount() > 0) {
        final List<PeerId> peers = new ArrayList<>(entry.getPeersCount());
        for (final String peerStr : entry.getPeersList()) {
            final PeerId peer = new PeerId();
            peer.parse(peerStr);
            peers.add(peer);
        }
        logEntry.setPeers(peers);
    }
    if (entry.getOldPeersCount() > 0) {
        final List<PeerId> oldPeers = new ArrayList<>(entry.getOldPeersCount());
        for (final String peerStr : entry.getOldPeersList()) {
            final PeerId peer = new PeerId();
            peer.parse(peerStr);
            oldPeers.add(peer);
        }
        logEntry.setOldPeers(oldPeers);
    }
    if (entry.getLearnersCount() > 0) {
        final List<PeerId> peers = new ArrayList<>(entry.getLearnersCount());
        for (final String peerStr : entry.getLearnersList()) {
            final PeerId peer = new PeerId();
            peer.parse(peerStr);
            peers.add(peer);
        }
        logEntry.setLearners(peers);
    }
    if (entry.getOldLearnersCount() > 0) {
        final List<PeerId> peers = new ArrayList<>(entry.getOldLearnersCount());
        for (final String peerStr : entry.getOldLearnersList()) {
            final PeerId peer = new PeerId();
            peer.parse(peerStr);
            peers.add(peer);
        }
        logEntry.setOldLearners(peers);
    }
}
Also used : CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) PeerId(com.alipay.sofa.jraft.entity.PeerId)

Aggregations

PeerId (com.alipay.sofa.jraft.entity.PeerId)236 Test (org.junit.Test)107 Node (com.alipay.sofa.jraft.Node)70 Configuration (com.alipay.sofa.jraft.conf.Configuration)54 Status (com.alipay.sofa.jraft.Status)49 Endpoint (com.alipay.sofa.jraft.util.Endpoint)43 ArrayList (java.util.ArrayList)32 CountDownLatch (java.util.concurrent.CountDownLatch)28 NodeOptions (com.alipay.sofa.jraft.option.NodeOptions)24 LogId (com.alipay.sofa.jraft.entity.LogId)17 Message (com.google.protobuf.Message)15 ByteBuffer (java.nio.ByteBuffer)15 Task (com.alipay.sofa.jraft.entity.Task)13 File (java.io.File)12 SynchronizedClosure (com.alipay.sofa.jraft.closure.SynchronizedClosure)11 LogEntry (com.alipay.sofa.jraft.entity.LogEntry)11 JRaftException (com.alipay.sofa.jraft.error.JRaftException)10 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)10 RpcServer (com.alipay.sofa.jraft.rpc.RpcServer)9 RaftGroupService (com.alipay.sofa.jraft.RaftGroupService)8