Search in sources :

Example 16 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class NodeImpl method getMaxPriorityOfNodes.

/**
 * Get max priority value for all nodes in the same Raft group, and update current node's target priority value.
 *
 * @param peerIds peer nodes in the same Raft group
 */
private int getMaxPriorityOfNodes(final List<PeerId> peerIds) {
    Requires.requireNonNull(peerIds, "Null peer list");
    int maxPriority = Integer.MIN_VALUE;
    for (final PeerId peerId : peerIds) {
        final int priorityVal = peerId.getPriority();
        maxPriority = Math.max(priorityVal, maxPriority);
    }
    return maxPriority;
}
Also used : PeerId(io.dingodb.raft.entity.PeerId)

Example 17 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class NodeImpl method becomeLeader.

private void becomeLeader() {
    Requires.requireTrue(this.state == State.STATE_CANDIDATE, "Illegal state: " + this.state);
    LOG.info("Node {} become leader of group, term={}, conf={}, oldConf={}.", getNodeId(), this.currTerm, this.conf.getConf(), this.conf.getOldConf());
    // cancel candidate vote timer
    stopVoteTimer();
    this.state = State.STATE_LEADER;
    this.leaderId = this.serverId.copy();
    this.replicatorGroup.resetTerm(this.currTerm);
    // Start follower's replicators
    for (final PeerId peer : this.conf.listPeers()) {
        if (peer.equals(this.serverId)) {
            continue;
        }
        LOG.debug("Node {} add a replicator, term={}, peer={}.", getNodeId(), this.currTerm, peer);
        if (!this.replicatorGroup.addReplicator(peer)) {
            LOG.error("Fail to add a replicator, peer={}.", peer);
        }
    }
    // Start learner's replicators
    for (final PeerId peer : this.conf.listLearners()) {
        LOG.debug("Node {} add a learner replicator, term={}, peer={}.", getNodeId(), this.currTerm, peer);
        if (!this.replicatorGroup.addReplicator(peer, ReplicatorType.Learner)) {
            LOG.error("Fail to add a learner replicator, peer={}.", peer);
        }
    }
    // init commit manager
    this.ballotBox.resetPendingIndex(this.logManager.getLastLogIndex() + 1);
    // is committed.
    if (this.confCtx.isBusy()) {
        throw new IllegalStateException();
    }
    this.confCtx.flush(this.conf.getConf(), this.conf.getOldConf());
    this.stepDownTimer.start();
}
Also used : PeerId(io.dingodb.raft.entity.PeerId)

Example 18 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class NodeImpl method readLeader.

private void readLeader(final RpcRequests.ReadIndexRequest request, final RpcRequests.ReadIndexResponse.Builder respBuilder, final RpcResponseClosure<RpcRequests.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(io.dingodb.raft.Status) ReadOnlyOption(io.dingodb.raft.option.ReadOnlyOption) PeerId(io.dingodb.raft.entity.PeerId)

Example 19 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class NodeImpl method handlePreVoteRequest.

@Override
public Message handlePreVoteRequest(final RpcRequests.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(RpcRequests.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(RpcRequests.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 // 
        RpcRequests.RequestVoteResponse.newBuilder().setTerm(// 
        this.currTerm).setGranted(// 
        granted).build();
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
    }
}
Also used : LogId(io.dingodb.raft.entity.LogId) PeerId(io.dingodb.raft.entity.PeerId)

Example 20 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class NodeImpl method electSelf.

// should be in writeLock
private void electSelf() {
    long oldTerm;
    try {
        LOG.info("Node {} start vote and grant vote self, term={}.", getNodeId(), this.currTerm);
        if (!this.conf.contains(this.serverId)) {
            LOG.warn("Node {} can't do electSelf as it is not in {}.", getNodeId(), this.conf);
            return;
        }
        if (this.state == State.STATE_FOLLOWER) {
            LOG.debug("Node {} stop election timer, term={}.", getNodeId(), this.currTerm);
            this.electionTimer.stop();
        }
        resetLeaderId(PeerId.emptyPeer(), new Status(RaftError.ERAFTTIMEDOUT, "A follower's leader_id is reset to NULL as it begins to request_vote."));
        this.state = State.STATE_CANDIDATE;
        this.currTerm++;
        this.votedId = this.serverId.copy();
        LOG.debug("Node {} start vote timer, term={} .", getNodeId(), this.currTerm);
        this.voteTimer.start();
        this.voteCtx.init(this.conf.getConf(), this.conf.isStable() ? null : this.conf.getOldConf());
        oldTerm = this.currTerm;
    } finally {
        this.writeLock.unlock();
    }
    final LogId lastLogId = this.logManager.getLastLogId(true);
    this.writeLock.lock();
    try {
        // vote need defense ABA after unlock&writeLock
        if (oldTerm != this.currTerm) {
            LOG.warn("Node {} raise term {} when getLastLogId.", getNodeId(), this.currTerm);
            return;
        }
        for (final PeerId peer : this.conf.listPeers()) {
            if (peer.equals(this.serverId)) {
                continue;
            }
            if (!this.rpcService.connect(peer.getEndpoint())) {
                LOG.warn("Node {} channel init failed, address={}.", getNodeId(), peer.getEndpoint());
                continue;
            }
            final OnRequestVoteRpcDone done = new OnRequestVoteRpcDone(peer, this.currTerm, this);
            done.request = // 
            RpcRequests.RequestVoteRequest.newBuilder().setPreVote(// It's not a pre-vote request.
            false).setGroupId(// 
            this.groupId).setServerId(// 
            this.serverId.toString()).setPeerId(// 
            peer.toString()).setTerm(// 
            this.currTerm).setLastLogIndex(// 
            lastLogId.getIndex()).setLastLogTerm(// 
            lastLogId.getTerm()).build();
            this.rpcService.requestVote(peer.getEndpoint(), done.request, done);
        }
        this.metaStorage.setTermAndVotedFor(this.currTerm, this.serverId);
        this.voteCtx.grant(this.serverId);
        if (this.voteCtx.isGranted()) {
            becomeLeader();
        }
    } finally {
        this.writeLock.unlock();
    }
}
Also used : Status(io.dingodb.raft.Status) LogId(io.dingodb.raft.entity.LogId) PeerId(io.dingodb.raft.entity.PeerId)

Aggregations

PeerId (io.dingodb.raft.entity.PeerId)72 Status (io.dingodb.raft.Status)27 Configuration (io.dingodb.raft.conf.Configuration)15 Message (com.google.protobuf.Message)12 ArrayList (java.util.ArrayList)12 JRaftException (io.dingodb.raft.error.JRaftException)10 LogId (io.dingodb.raft.entity.LogId)9 CliRequests (io.dingodb.raft.rpc.CliRequests)8 Node (io.dingodb.raft.Node)6 RpcRequests (io.dingodb.raft.rpc.RpcRequests)4 Endpoint (io.dingodb.raft.util.Endpoint)4 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)4 LogEntry (io.dingodb.raft.entity.LogEntry)3 NodeOptions (io.dingodb.raft.option.NodeOptions)3 ByteBuffer (java.nio.ByteBuffer)3 TimeoutException (java.util.concurrent.TimeoutException)3 RaftOutter (io.dingodb.raft.entity.RaftOutter)2 RaftException (io.dingodb.raft.error.RaftException)2 ThreadId (io.dingodb.raft.util.ThreadId)2 ExecutionException (java.util.concurrent.ExecutionException)2