Search in sources :

Example 6 with Status

use of io.dingodb.raft.Status in project dingo by dingodb.

the class NodeImpl method handleRequestVoteRequest.

@Override
public Message handleRequestVoteRequest(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 RequestVoteRequest from {} serverId bad format.", getNodeId(), request.getServerId());
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RpcRequests.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 // 
        RpcRequests.RequestVoteResponse.newBuilder().setTerm(// 
        this.currTerm).setGranted(// 
        request.getTerm() == this.currTerm && candidateId.equals(this.votedId)).build();
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
    }
}
Also used : Status(io.dingodb.raft.Status) LogId(io.dingodb.raft.entity.LogId) PeerId(io.dingodb.raft.entity.PeerId)

Example 7 with Status

use of io.dingodb.raft.Status in project dingo by dingodb.

the class NodeImpl method onError.

public void onError(final RaftException error) {
    LOG.warn("Node {} got error: {}.", getNodeId(), error);
    if (this.fsmCaller != null) {
        // onError of fsmCaller is guaranteed to be executed once.
        this.fsmCaller.onError(error);
    }
    if (this.readOnlyService != null) {
        this.readOnlyService.setError(error);
    }
    this.writeLock.lock();
    try {
        // If it is follower, also step down to call on_stop_following.
        if (this.state.compareTo(State.STATE_FOLLOWER) <= 0) {
            stepDown(this.currTerm, this.state == State.STATE_LEADER, new Status(RaftError.EBADNODE, "Raft node(leader or candidate) is in error."));
        }
        if (this.state.compareTo(State.STATE_ERROR) < 0) {
            this.state = State.STATE_ERROR;
        }
    } finally {
        this.writeLock.unlock();
    }
}
Also used : Status(io.dingodb.raft.Status)

Example 8 with Status

use of io.dingodb.raft.Status in project dingo by dingodb.

the class CliServiceImpl method rebalance.

@Override
public Status rebalance(final Set<String> balanceGroupIds, final Configuration conf, final Map<String, PeerId> rebalancedLeaderIds) {
    Requires.requireNonNull(balanceGroupIds, "Null balance group ids");
    Requires.requireTrue(!balanceGroupIds.isEmpty(), "Empty balance group ids");
    Requires.requireNonNull(conf, "Null configuration");
    Requires.requireTrue(!conf.isEmpty(), "No peers of configuration");
    LOG.info("Rebalance start with raft groups={}.", balanceGroupIds);
    final long start = Utils.monotonicMs();
    int transfers = 0;
    Status failedStatus = null;
    final Queue<String> groupDeque = new ArrayDeque<>(balanceGroupIds);
    final LeaderCounter leaderCounter = new LeaderCounter(balanceGroupIds.size(), conf.size());
    for (; ; ) {
        final String groupId = groupDeque.poll();
        if (groupId == null) {
            // well done
            break;
        }
        final PeerId leaderId = new PeerId();
        final Status leaderStatus = getLeader(groupId, conf, leaderId);
        if (!leaderStatus.isOk()) {
            failedStatus = leaderStatus;
            break;
        }
        if (rebalancedLeaderIds != null) {
            rebalancedLeaderIds.put(groupId, leaderId);
        }
        if (leaderCounter.incrementAndGet(leaderId) <= leaderCounter.getExpectedAverage()) {
            // The num of leaders is less than the expected average, we are going to deal with others
            continue;
        }
        // Find the target peer and try to transfer the leader to this peer
        final PeerId targetPeer = findTargetPeer(leaderId, groupId, conf, leaderCounter);
        if (!targetPeer.isEmpty()) {
            final Status transferStatus = transferLeader(groupId, conf, targetPeer);
            transfers++;
            if (!transferStatus.isOk()) {
                // The failure of `transfer leader` usually means the node is busy,
                // so we return failure status and should try `rebalance` again later.
                failedStatus = transferStatus;
                break;
            }
            LOG.info("Group {} transfer leader to {}.", groupId, targetPeer);
            leaderCounter.decrementAndGet(leaderId);
            groupDeque.add(groupId);
            if (rebalancedLeaderIds != null) {
                rebalancedLeaderIds.put(groupId, targetPeer);
            }
        }
    }
    final Status status = failedStatus != null ? failedStatus : Status.OK();
    if (LOG.isInfoEnabled()) {
        LOG.info("Rebalanced raft groups={}, status={}, number of transfers={}, elapsed time={} ms, rebalanced result={}.", balanceGroupIds, status, transfers, Utils.monotonicMs() - start, rebalancedLeaderIds);
    }
    return status;
}
Also used : Status(io.dingodb.raft.Status) ArrayDeque(java.util.ArrayDeque) PeerId(io.dingodb.raft.entity.PeerId)

Example 9 with Status

use of io.dingodb.raft.Status in project dingo by dingodb.

the class CliServiceImpl method transferLeader.

@Override
public Status transferLeader(final String groupId, final Configuration conf, final PeerId peer) {
    Requires.requireTrue(!StringUtils.isBlank(groupId), "Blank group id");
    Requires.requireNonNull(conf, "Null configuration");
    Requires.requireNonNull(peer, "Null peer");
    final PeerId leaderId = new PeerId();
    final Status st = checkLeaderAndConnect(groupId, conf, leaderId);
    if (!st.isOk()) {
        return st;
    }
    final CliRequests.TransferLeaderRequest.Builder rb = // 
    CliRequests.TransferLeaderRequest.newBuilder().setGroupId(// 
    groupId).setLeaderId(leaderId.toString());
    if (!peer.isEmpty()) {
        rb.setPeerId(peer.toString());
    }
    try {
        final Message result = this.cliClientService.transferLeader(leaderId.getEndpoint(), rb.build(), null).get();
        return statusFromResponse(result);
    } catch (final Exception e) {
        return new Status(-1, e.getMessage());
    }
}
Also used : Status(io.dingodb.raft.Status) Message(com.google.protobuf.Message) JRaftException(io.dingodb.raft.error.JRaftException) PeerId(io.dingodb.raft.entity.PeerId)

Example 10 with Status

use of io.dingodb.raft.Status in project dingo by dingodb.

the class CliServiceImpl method resetPeer.

@Override
public Status resetPeer(final String groupId, final PeerId peerId, final Configuration newPeers) {
    Requires.requireTrue(!StringUtils.isBlank(groupId), "Blank group id");
    Requires.requireNonNull(peerId, "Null peerId");
    Requires.requireNonNull(newPeers, "Null new peers");
    if (!this.cliClientService.connect(peerId.getEndpoint())) {
        return new Status(-1, "Fail to init channel to %s", peerId);
    }
    final CliRequests.ResetPeerRequest.Builder rb = // 
    CliRequests.ResetPeerRequest.newBuilder().setGroupId(// 
    groupId).setPeerId(peerId.toString());
    for (final PeerId peer : newPeers) {
        rb.addNewPeers(peer.toString());
    }
    try {
        final Message result = this.cliClientService.resetPeer(peerId.getEndpoint(), rb.build(), null).get();
        return statusFromResponse(result);
    } catch (final Exception e) {
        return new Status(-1, e.getMessage());
    }
}
Also used : Status(io.dingodb.raft.Status) Message(com.google.protobuf.Message) JRaftException(io.dingodb.raft.error.JRaftException) PeerId(io.dingodb.raft.entity.PeerId)

Aggregations

Status (io.dingodb.raft.Status)112 PeerId (io.dingodb.raft.entity.PeerId)31 BaseKVStoreClosure (io.dingodb.store.row.storage.BaseKVStoreClosure)21 Message (com.google.protobuf.Message)19 Configuration (io.dingodb.raft.conf.Configuration)12 RpcRequests (io.dingodb.raft.rpc.RpcRequests)12 JRaftException (io.dingodb.raft.error.JRaftException)11 LogId (io.dingodb.raft.entity.LogId)10 RaftException (io.dingodb.raft.error.RaftException)9 ArrayList (java.util.ArrayList)9 ConfigurationEntry (io.dingodb.raft.conf.ConfigurationEntry)7 LogEntry (io.dingodb.raft.entity.LogEntry)7 ByteBuffer (java.nio.ByteBuffer)7 RaftOutter (io.dingodb.raft.entity.RaftOutter)6 BlockingWaitStrategy (com.lmax.disruptor.BlockingWaitStrategy)5 Disruptor (com.lmax.disruptor.dsl.Disruptor)5 ProducerType (com.lmax.disruptor.dsl.ProducerType)5 Closure (io.dingodb.raft.Closure)5 FSMCaller (io.dingodb.raft.FSMCaller)5 Node (io.dingodb.raft.Node)5