Search in sources :

Example 46 with LogEntry

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

the class NodeImpl method unsafeApplyConfiguration.

private void unsafeApplyConfiguration(final Configuration newConf, final Configuration oldConf, final boolean leaderStart) {
    Requires.requireTrue(this.confCtx.isBusy(), "ConfigurationContext is not busy");
    final LogEntry entry = new LogEntry(EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION);
    entry.setId(new LogId(0, this.currTerm));
    entry.setPeers(newConf.listPeers());
    entry.setLearners(newConf.listLearners());
    if (oldConf != null) {
        entry.setOldPeers(oldConf.listPeers());
        entry.setOldLearners(oldConf.listLearners());
    }
    final ConfigurationChangeDone configurationChangeDone = new ConfigurationChangeDone(this.currTerm, leaderStart);
    // Use the new_conf to deal the quorum of this very log
    if (!this.ballotBox.appendPendingTask(newConf, oldConf, configurationChangeDone)) {
        Utils.runClosureInThread(configurationChangeDone, new Status(RaftError.EINTERNAL, "Fail to append task."));
        return;
    }
    final List<LogEntry> entries = new ArrayList<>();
    entries.add(entry);
    this.logManager.appendEntries(entries, new LeaderStableClosure(entries));
    checkAndSetConfiguration(false);
}
Also used : Status(com.alipay.sofa.jraft.Status) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) LogId(com.alipay.sofa.jraft.entity.LogId) LogEntry(com.alipay.sofa.jraft.entity.LogEntry)

Example 47 with LogEntry

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

the class Replicator method prepareEntry.

boolean prepareEntry(final long nextSendingIndex, final int offset, final RaftOutter.EntryMeta.Builder emb, final RecyclableByteBufferList dateBuffer) {
    if (dateBuffer.getCapacity() >= this.raftOptions.getMaxBodySize()) {
        return false;
    }
    final long logIndex = nextSendingIndex + offset;
    final LogEntry entry = this.options.getLogManager().getEntry(logIndex);
    if (entry == null) {
        return false;
    }
    emb.setTerm(entry.getId().getTerm());
    if (entry.hasChecksum()) {
        // since 1.2.6
        emb.setChecksum(entry.getChecksum());
    }
    emb.setType(entry.getType());
    if (entry.getPeers() != null) {
        Requires.requireTrue(!entry.getPeers().isEmpty(), "Empty peers at logIndex=%d", logIndex);
        fillMetaPeers(emb, entry);
    } else {
        Requires.requireTrue(entry.getType() != EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION, "Empty peers but is ENTRY_TYPE_CONFIGURATION type at logIndex=%d", logIndex);
    }
    final int remaining = entry.getData() != null ? entry.getData().remaining() : 0;
    emb.setDataLen(remaining);
    if (entry.getData() != null) {
        // should slice entry data
        dateBuffer.add(entry.getData().slice());
    }
    return true;
}
Also used : LogEntry(com.alipay.sofa.jraft.entity.LogEntry)

Example 48 with LogEntry

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

the class NodeImpl method readCommittedUserLog.

@Override
public UserLog readCommittedUserLog(final long index) {
    if (index <= 0) {
        throw new LogIndexOutOfBoundsException("Request index is invalid: " + index);
    }
    final long savedLastAppliedIndex = this.fsmCaller.getLastAppliedIndex();
    if (index > savedLastAppliedIndex) {
        throw new LogIndexOutOfBoundsException("Request index " + index + " is greater than lastAppliedIndex: " + savedLastAppliedIndex);
    }
    long curIndex = index;
    LogEntry entry = this.logManager.getEntry(curIndex);
    if (entry == null) {
        throw new LogNotFoundException("User log is deleted at index: " + index);
    }
    do {
        if (entry.getType() == EnumOutter.EntryType.ENTRY_TYPE_DATA) {
            return new UserLog(curIndex, entry.getData());
        } else {
            curIndex++;
        }
        if (curIndex > savedLastAppliedIndex) {
            throw new IllegalStateException("No user log between index:" + index + " and last_applied_index:" + savedLastAppliedIndex);
        }
        entry = this.logManager.getEntry(curIndex);
    } while (entry != null);
    throw new LogNotFoundException("User log is deleted at index: " + curIndex);
}
Also used : UserLog(com.alipay.sofa.jraft.entity.UserLog) LogIndexOutOfBoundsException(com.alipay.sofa.jraft.error.LogIndexOutOfBoundsException) LogNotFoundException(com.alipay.sofa.jraft.error.LogNotFoundException) LogEntry(com.alipay.sofa.jraft.entity.LogEntry)

Example 49 with LogEntry

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

the class NodeImpl method handleAppendEntriesRequest.

@Override
public Message handleAppendEntriesRequest(final AppendEntriesRequest request, final RpcRequestClosure done) {
    boolean doUnlock = true;
    final long startMs = Utils.monotonicMs();
    this.writeLock.lock();
    final int entriesCount = request.getEntriesCount();
    boolean success = false;
    try {
        if (!this.state.isActive()) {
            LOG.warn("Node {} is not in active state, currTerm={}.", getNodeId(), this.currTerm);
            return // 
            RpcFactoryHelper.responseFactory().newResponse(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(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 // 
            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 // 
            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(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 // 
            AppendEntriesResponse.newBuilder().setSuccess(// 
            false).setTerm(// 
            this.currTerm).setLastLogIndex(// 
            lastLogIndex).build();
        }
        if (entriesCount == 0) {
            // heartbeat or probe request
            final AppendEntriesResponse.Builder respBuilder = // 
            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();
        }
        // fast checking if log manager is overloaded
        if (!this.logManager.hasAvailableCapacityToAppendEntries(1)) {
            LOG.warn("Node {} received AppendEntriesRequest but log manager is busy.", getNodeId());
            return // 
            RpcFactoryHelper.responseFactory().newResponse(AppendEntriesResponse.getDefaultInstance(), RaftError.EBUSY, "Node %s:%s log manager is busy.", this.groupId, this.serverId);
        }
        // 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(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, 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);
        success = true;
        return null;
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
        final long processLatency = Utils.monotonicMs() - startMs;
        if (entriesCount == 0) {
            this.metrics.recordLatency("handle-heartbeat-requests", processLatency);
        } else {
            this.metrics.recordLatency("handle-append-entries", processLatency);
        }
        if (success) {
            // Don't stats heartbeat requests.
            this.metrics.recordSize("handle-append-entries-count", entriesCount);
        }
    }
}
Also used : Status(com.alipay.sofa.jraft.Status) AppendEntriesResponse(com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesResponse) RaftOutter(com.alipay.sofa.jraft.entity.RaftOutter) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) ByteBuffer(java.nio.ByteBuffer) LogEntry(com.alipay.sofa.jraft.entity.LogEntry) PeerId(com.alipay.sofa.jraft.entity.PeerId)

Example 50 with LogEntry

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

the class V1Decoder method decode.

@Override
public LogEntry decode(final byte[] content) {
    if (content == null || content.length == 0) {
        return null;
    }
    if (content[0] != LogEntryV1CodecFactory.MAGIC) {
        // Corrupted log
        return null;
    }
    LogEntry log = new LogEntry();
    decode(log, content);
    return log;
}
Also used : LogEntry(com.alipay.sofa.jraft.entity.LogEntry)

Aggregations

LogEntry (com.alipay.sofa.jraft.entity.LogEntry)50 LogId (com.alipay.sofa.jraft.entity.LogId)27 Test (org.junit.Test)19 PeerId (com.alipay.sofa.jraft.entity.PeerId)13 Status (com.alipay.sofa.jraft.Status)11 BaseStorageTest (com.alipay.sofa.jraft.storage.BaseStorageTest)11 ArrayList (java.util.ArrayList)10 LogManager (com.alipay.sofa.jraft.storage.LogManager)7 CountDownLatch (java.util.concurrent.CountDownLatch)7 ConfigurationEntry (com.alipay.sofa.jraft.conf.ConfigurationEntry)6 ByteBuffer (java.nio.ByteBuffer)6 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)6 Configuration (com.alipay.sofa.jraft.conf.Configuration)5 Closure (com.alipay.sofa.jraft.Closure)3 SynchronizedClosure (com.alipay.sofa.jraft.closure.SynchronizedClosure)3 ConfigurationManager (com.alipay.sofa.jraft.conf.ConfigurationManager)3 RaftOutter (com.alipay.sofa.jraft.entity.RaftOutter)3 UserLog (com.alipay.sofa.jraft.entity.UserLog)3 FSMCaller (com.alipay.sofa.jraft.FSMCaller)2 JRaftServiceFactory (com.alipay.sofa.jraft.JRaftServiceFactory)2