Search in sources :

Example 11 with PeerId

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

the class CliServiceImpl method removeLearners.

@Override
public Status removeLearners(final String groupId, final Configuration conf, final List<PeerId> learners) {
    checkLearnersOpParams(groupId, conf, learners);
    final PeerId leaderId = new PeerId();
    final Status st = getLeader(groupId, conf, leaderId);
    if (!st.isOk()) {
        return st;
    }
    if (!this.cliClientService.connect(leaderId.getEndpoint())) {
        return new Status(-1, "Fail to init channel to leader %s", leaderId);
    }
    final CliRequests.RemoveLearnersRequest.Builder rb = // 
    CliRequests.RemoveLearnersRequest.newBuilder().setGroupId(// 
    groupId).setLeaderId(leaderId.toString());
    for (final PeerId peer : learners) {
        rb.addLearners(peer.toString());
    }
    try {
        final Message result = this.cliClientService.removeLearners(leaderId.getEndpoint(), rb.build(), null).get();
        return processLearnersOpResponse(groupId, result, "removing learners: %s", learners);
    } 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 12 with PeerId

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

the class NodeImpl method checkPeers.

private void checkPeers(final List<PeerId> peers) {
    Requires.requireNonNull(peers, "Null peers");
    Requires.requireTrue(!peers.isEmpty(), "Empty peers");
    for (final PeerId peer : peers) {
        Requires.requireNonNull(peer, "Null peer");
    }
}
Also used : PeerId(io.dingodb.raft.entity.PeerId)

Example 13 with PeerId

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

the class NodeImpl method preVote.

// in writeLock
private void preVote() {
    long oldTerm;
    try {
        LOG.info("Node {} term {} start preVote.", getNodeId(), this.currTerm);
        if (this.snapshotExecutor != null && this.snapshotExecutor.isInstallingSnapshot()) {
            LOG.warn("Node {} term {} doesn't do preVote when installing snapshot as the configuration may be out of date.", getNodeId(), this.currTerm);
            return;
        }
        if (!this.conf.contains(this.serverId)) {
            LOG.warn("Node {} can't do preVote as it is not in conf <{}>.", getNodeId(), this.conf);
            return;
        }
        oldTerm = this.currTerm;
    } finally {
        this.writeLock.unlock();
    }
    final LogId lastLogId = this.logManager.getLastLogId(true);
    boolean doUnlock = true;
    this.writeLock.lock();
    try {
        // pre_vote need defense ABA after unlock&writeLock
        if (oldTerm != this.currTerm) {
            LOG.warn("Node {} raise term {} when get lastLogId.", getNodeId(), this.currTerm);
            return;
        }
        this.prevVoteCtx.init(this.conf.getConf(), this.conf.isStable() ? null : this.conf.getOldConf());
        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 OnPreVoteRpcDone done = new OnPreVoteRpcDone(peer, this.currTerm);
            done.request = // 
            RpcRequests.RequestVoteRequest.newBuilder().setPreVote(// it's a pre-vote request.
            true).setGroupId(// 
            this.groupId).setServerId(// 
            this.serverId.toString()).setPeerId(// 
            peer.toString()).setTerm(// next term
            this.currTerm + 1).setLastLogIndex(// 
            lastLogId.getIndex()).setLastLogTerm(// 
            lastLogId.getTerm()).build();
            this.rpcService.preVote(peer.getEndpoint(), done.request, done);
        }
        this.prevVoteCtx.grant(this.serverId);
        if (this.prevVoteCtx.isGranted()) {
            doUnlock = false;
            electSelf();
        }
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
    }
}
Also used : LogId(io.dingodb.raft.entity.LogId) PeerId(io.dingodb.raft.entity.PeerId)

Example 14 with PeerId

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

the class NodeImpl method handleInstallSnapshot.

@Override
public Message handleInstallSnapshot(final RpcRequests.InstallSnapshotRequest request, final RpcRequestClosure done) {
    if (this.snapshotExecutor == null) {
        return // 
        RpcFactoryHelper.responseFactory().newResponse(RpcRequests.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(RpcRequests.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(RpcRequests.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 // 
            RpcRequests.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 // 
            RpcRequests.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, RpcRequests.InstallSnapshotResponse.newBuilder(), done);
        return null;
    } finally {
        this.metrics.recordLatency("install-snapshot", Utils.monotonicMs() - startMs);
    }
}
Also used : Status(io.dingodb.raft.Status) PeerId(io.dingodb.raft.entity.PeerId)

Example 15 with PeerId

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

the class NodeImpl method handleAppendEntriesRequest.

@Override
public Message handleAppendEntriesRequest(final RpcRequests.AppendEntriesRequest request, final RpcRequestClosure done) {
    boolean doUnlock = true;
    final long startMs = Utils.monotonicMs();
    this.writeLock.lock();
    final int entriesCount = request.getEntriesCount();
    try {
        if (!this.state.isActive()) {
            LOG.warn("Node {} is not in active state, currTerm={}.", getNodeId(), this.currTerm);
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RpcRequests.AppendEntriesResponse.getDefaultInstance(), RaftError.EINVAL, "Node %s is not in active state, state %s.", getNodeId(), this.state.name());
        }
        final PeerId serverId = new PeerId();
        if (!serverId.parse(request.getServerId())) {
            LOG.warn("Node {} received AppendEntriesRequest from {} serverId bad format.", getNodeId(), request.getServerId());
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RpcRequests.AppendEntriesResponse.getDefaultInstance(), RaftError.EINVAL, "Parse serverId failed: %s.", request.getServerId());
        }
        // Check stale term
        if (request.getTerm() < this.currTerm) {
            LOG.warn("Node {} ignore stale AppendEntriesRequest from {}, term={}, currTerm={}.", getNodeId(), request.getServerId(), request.getTerm(), this.currTerm);
            return // 
            RpcRequests.AppendEntriesResponse.newBuilder().setSuccess(// 
            false).setTerm(// 
            this.currTerm).build();
        }
        // Check term and state to step down
        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 // 
            RpcRequests.AppendEntriesResponse.newBuilder().setSuccess(// 
            false).setTerm(// 
            request.getTerm() + 1).build();
        }
        updateLastLeaderTimestamp(Utils.monotonicMs());
        if (entriesCount > 0 && this.snapshotExecutor != null && this.snapshotExecutor.isInstallingSnapshot()) {
            LOG.warn("Node {} received AppendEntriesRequest while installing snapshot.", getNodeId());
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RpcRequests.AppendEntriesResponse.getDefaultInstance(), RaftError.EBUSY, "Node %s:%s is installing snapshot.", this.groupId, this.serverId);
        }
        final long prevLogIndex = request.getPrevLogIndex();
        final long prevLogTerm = request.getPrevLogTerm();
        final long localPrevLogTerm = this.logManager.getTerm(prevLogIndex);
        if (localPrevLogTerm != prevLogTerm) {
            final long lastLogIndex = this.logManager.getLastLogIndex();
            LOG.warn("Node {} reject term_unmatched AppendEntriesRequest from {}, term={}, prevLogIndex={}, prevLogTerm={}, localPrevLogTerm={}, lastLogIndex={}, entriesSize={}.", getNodeId(), request.getServerId(), request.getTerm(), prevLogIndex, prevLogTerm, localPrevLogTerm, lastLogIndex, entriesCount);
            return // 
            RpcRequests.AppendEntriesResponse.newBuilder().setSuccess(// 
            false).setTerm(// 
            this.currTerm).setLastLogIndex(// 
            lastLogIndex).build();
        }
        if (entriesCount == 0) {
            // heartbeat or probe request
            final RpcRequests.AppendEntriesResponse.Builder respBuilder = // 
            RpcRequests.AppendEntriesResponse.newBuilder().setSuccess(// 
            true).setTerm(// 
            this.currTerm).setLastLogIndex(this.logManager.getLastLogIndex());
            doUnlock = false;
            this.writeLock.unlock();
            // see the comments at FollowerStableClosure#run()
            this.ballotBox.setLastCommittedIndex(Math.min(request.getCommittedIndex(), prevLogIndex));
            return respBuilder.build();
        }
        // Parse request
        long index = prevLogIndex;
        final List<LogEntry> entries = new ArrayList<>(entriesCount);
        ByteBuffer allData = null;
        if (request.hasData()) {
            allData = request.getData().asReadOnlyByteBuffer();
        }
        final List<RaftOutter.EntryMeta> entriesList = request.getEntriesList();
        for (int i = 0; i < entriesCount; i++) {
            index++;
            final RaftOutter.EntryMeta entry = entriesList.get(i);
            final LogEntry logEntry = logEntryFromMeta(index, allData, entry);
            if (logEntry != null) {
                // Validate checksum
                if (this.raftOptions.isEnableLogEntryChecksum() && logEntry.isCorrupted()) {
                    long realChecksum = logEntry.checksum();
                    LOG.error("Corrupted log entry received from leader, index={}, term={}, expectedChecksum={}, realChecksum={}", logEntry.getId().getIndex(), logEntry.getId().getTerm(), logEntry.getChecksum(), realChecksum);
                    return // 
                    RpcFactoryHelper.responseFactory().newResponse(RpcRequests.AppendEntriesResponse.getDefaultInstance(), RaftError.EINVAL, "The log entry is corrupted, index=%d, term=%d, expectedChecksum=%d, realChecksum=%d", logEntry.getId().getIndex(), logEntry.getId().getTerm(), logEntry.getChecksum(), realChecksum);
                }
                entries.add(logEntry);
            }
        }
        final FollowerStableClosure closure = new FollowerStableClosure(request, RpcRequests.AppendEntriesResponse.newBuilder().setTerm(this.currTerm), this, done, this.currTerm);
        this.logManager.appendEntries(entries, closure);
        // update configuration after _log_manager updated its memory status
        checkAndSetConfiguration(true);
        return null;
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
        this.metrics.recordLatency("handle-append-entries", Utils.monotonicMs() - startMs);
        this.metrics.recordSize("handle-append-entries-count", entriesCount);
    }
}
Also used : Status(io.dingodb.raft.Status) RaftOutter(io.dingodb.raft.entity.RaftOutter) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) ByteBuffer(java.nio.ByteBuffer) LogEntry(io.dingodb.raft.entity.LogEntry) 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