Search in sources :

Example 1 with LogId

use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.

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 // 
            RaftRpcFactory.DEFAULT.newResponse(raftOptions.getRaftMessagesFactory(), RaftError.EINVAL, "Node %s is not in active state, state %s.", getNodeId(), this.state.name());
        }
        final PeerId candidateId = new PeerId();
        if (!candidateId.parse(request.serverId())) {
            LOG.warn("Node {} received PreVoteRequest from {} serverId bad format.", getNodeId(), request.serverId());
            return // 
            RaftRpcFactory.DEFAULT.newResponse(raftOptions.getRaftMessagesFactory(), RaftError.EINVAL, "Parse candidateId failed: %s.", request.serverId());
        }
        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.serverId(), 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.serverId(), request.term(), this.currTerm, this.leaderId);
                break;
            }
            if (request.term() < this.currTerm) {
                LOG.info("Node {} ignore PreVoteRequest from {}, term={}, currTerm={}.", getNodeId(), request.serverId(), request.term(), 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.lastLogIndex(), request.lastLogTerm());
            granted = requestLastLogId.compareTo(lastLogId) >= 0;
            LOG.info("Node {} received PreVoteRequest from {}, term={}, currTerm={}, granted={}, requestLastLogId={}, lastLogId={}.", getNodeId(), request.serverId(), request.term(), this.currTerm, granted, requestLastLogId, lastLogId);
        } while (false);
        return raftOptions.getRaftMessagesFactory().requestVoteResponse().term(this.currTerm).granted(granted).build();
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
    }
}
Also used : LogId(org.apache.ignite.raft.jraft.entity.LogId) PeerId(org.apache.ignite.raft.jraft.entity.PeerId)

Example 2 with LogId

use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.

the class NodeImpl method init.

@Override
public boolean init(final NodeOptions opts) {
    Requires.requireNonNull(opts, "Null node options");
    Requires.requireNonNull(opts.getRaftOptions(), "Null raft options");
    Requires.requireNonNull(opts.getServiceFactory(), "Null jraft service factory");
    this.serviceFactory = opts.getServiceFactory();
    this.options = opts;
    this.raftOptions = opts.getRaftOptions();
    this.metrics = new NodeMetrics(opts.isEnableMetrics());
    this.serverId.setPriority(opts.getElectionPriority());
    this.electionTimeoutCounter = 0;
    if (opts.getReplicationStateListeners() != null)
        this.replicatorStateListeners.addAll(opts.getReplicationStateListeners());
    if (this.serverId.getIp().equals(Utils.IP_ANY)) {
        LOG.error("Node can't start from IP_ANY.");
        return false;
    }
    // Init timers.
    initTimers(opts);
    // Init pools.
    initPools(opts);
    this.configManager = new ConfigurationManager();
    applyDisruptor = opts.getNodeApplyDisruptor();
    applyQueue = applyDisruptor.subscribe(groupId, new LogEntryAndClosureHandler());
    if (this.metrics.getMetricRegistry() != null) {
        this.metrics.getMetricRegistry().register("jraft-node-impl-disruptor", new DisruptorMetricSet(this.applyQueue));
    }
    this.fsmCaller = new FSMCallerImpl();
    if (!initLogStorage()) {
        LOG.error("Node {} initLogStorage failed.", getNodeId());
        return false;
    }
    if (!initMetaStorage()) {
        LOG.error("Node {} initMetaStorage failed.", getNodeId());
        return false;
    }
    if (!initFSMCaller(new LogId(0, 0))) {
        LOG.error("Node {} initFSMCaller failed.", getNodeId());
        return false;
    }
    this.ballotBox = new BallotBox();
    final BallotBoxOptions ballotBoxOpts = new BallotBoxOptions();
    ballotBoxOpts.setWaiter(this.fsmCaller);
    ballotBoxOpts.setClosureQueue(this.closureQueue);
    if (!this.ballotBox.init(ballotBoxOpts)) {
        LOG.error("Node {} init ballotBox failed.", getNodeId());
        return false;
    }
    if (!initSnapshotStorage()) {
        LOG.error("Node {} initSnapshotStorage failed.", getNodeId());
        return false;
    }
    final Status st = this.logManager.checkConsistency();
    if (!st.isOk()) {
        LOG.error("Node {} is initialized with inconsistent log, status={}.", getNodeId(), st);
        return false;
    }
    this.conf = new ConfigurationEntry();
    this.conf.setId(new LogId());
    // if have log using conf in log, else using conf in options
    if (this.logManager.getLastLogIndex() > 0) {
        checkAndSetConfiguration(false);
    } else {
        this.conf.setConf(this.options.getInitialConf());
        // initially set to max(priority of all nodes)
        this.targetPriority = getMaxPriorityOfNodes(this.conf.getConf().getPeers());
    }
    if (!this.conf.isEmpty()) {
        Requires.requireTrue(this.conf.isValid(), "Invalid conf: %s", this.conf);
    } else {
        LOG.info("Init node {} with empty conf.", this.serverId);
    }
    this.replicatorGroup = new ReplicatorGroupImpl();
    this.rpcClientService = new DefaultRaftClientService();
    final ReplicatorGroupOptions rgOpts = new ReplicatorGroupOptions();
    rgOpts.setHeartbeatTimeoutMs(heartbeatTimeout(this.options.getElectionTimeoutMs()));
    rgOpts.setElectionTimeoutMs(this.options.getElectionTimeoutMs());
    rgOpts.setLogManager(this.logManager);
    rgOpts.setBallotBox(this.ballotBox);
    rgOpts.setNode(this);
    rgOpts.setRaftRpcClientService(this.rpcClientService);
    rgOpts.setSnapshotStorage(this.snapshotExecutor != null ? this.snapshotExecutor.getSnapshotStorage() : null);
    rgOpts.setRaftOptions(this.raftOptions);
    rgOpts.setTimerManager(this.options.getScheduler());
    // Adds metric registry to RPC service.
    this.options.setMetricRegistry(this.metrics.getMetricRegistry());
    if (!this.rpcClientService.init(this.options)) {
        LOG.error("Fail to init rpc service.");
        return false;
    }
    this.replicatorGroup.init(new NodeId(this.groupId, this.serverId), rgOpts);
    this.readOnlyService = new ReadOnlyServiceImpl();
    final ReadOnlyServiceOptions rosOpts = new ReadOnlyServiceOptions();
    rosOpts.setGroupId(groupId);
    rosOpts.setFsmCaller(this.fsmCaller);
    rosOpts.setNode(this);
    rosOpts.setRaftOptions(this.raftOptions);
    rosOpts.setReadOnlyServiceDisruptor(opts.getReadOnlyServiceDisruptor());
    if (!this.readOnlyService.init(rosOpts)) {
        LOG.error("Fail to init readOnlyService.");
        return false;
    }
    // set state to follower
    this.state = State.STATE_FOLLOWER;
    if (LOG.isInfoEnabled()) {
        LOG.info("Node {} init, term={}, lastLogId={}, conf={}, oldConf={}.", getNodeId(), this.currTerm, this.logManager.getLastLogId(false), this.conf.getConf(), this.conf.getOldConf());
    }
    if (this.snapshotExecutor != null && this.options.getSnapshotIntervalSecs() > 0) {
        LOG.debug("Node {} start snapshot timer, term={}.", getNodeId(), this.currTerm);
        this.snapshotTimer.start();
    }
    if (!this.conf.isEmpty()) {
        stepDown(this.currTerm, false, new Status());
    }
    // Now the raft node is started , have to acquire the writeLock to avoid race
    // conditions
    this.writeLock.lock();
    if (this.conf.isStable() && this.conf.getConf().size() == 1 && this.conf.getConf().contains(this.serverId)) {
        // The group contains only this server which must be the LEADER, trigger
        // the timer immediately.
        electSelf();
    } else {
        this.writeLock.unlock();
    }
    return true;
}
Also used : Status(org.apache.ignite.raft.jraft.Status) DisruptorMetricSet(org.apache.ignite.raft.jraft.util.DisruptorMetricSet) ReplicatorGroupOptions(org.apache.ignite.raft.jraft.option.ReplicatorGroupOptions) BallotBoxOptions(org.apache.ignite.raft.jraft.option.BallotBoxOptions) ReadOnlyServiceOptions(org.apache.ignite.raft.jraft.option.ReadOnlyServiceOptions) NodeId(org.apache.ignite.raft.jraft.entity.NodeId) DefaultRaftClientService(org.apache.ignite.raft.jraft.rpc.impl.core.DefaultRaftClientService) ConfigurationManager(org.apache.ignite.raft.jraft.conf.ConfigurationManager) LogId(org.apache.ignite.raft.jraft.entity.LogId) ConfigurationEntry(org.apache.ignite.raft.jraft.conf.ConfigurationEntry)

Example 3 with LogId

use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.

the class FSMCallerImpl method doSnapshotLoad.

private void doSnapshotLoad(final LoadSnapshotClosure done) {
    Requires.requireNonNull(done, "LoadSnapshotClosure is null");
    final SnapshotReader reader = done.start();
    if (reader == null) {
        done.run(new Status(RaftError.EINVAL, "open SnapshotReader failed"));
        return;
    }
    final RaftOutter.SnapshotMeta meta = reader.load();
    if (meta == null) {
        done.run(new Status(RaftError.EINVAL, "SnapshotReader load meta failed"));
        if (reader.getRaftError() == RaftError.EIO) {
            final RaftException err = new RaftException(ErrorType.ERROR_TYPE_SNAPSHOT, RaftError.EIO, "Fail to load snapshot meta");
            setError(err);
        }
        return;
    }
    final LogId lastAppliedId = new LogId(this.lastAppliedIndex.get(), this.lastAppliedTerm);
    final LogId snapshotId = new LogId(meta.lastIncludedIndex(), meta.lastIncludedTerm());
    if (lastAppliedId.compareTo(snapshotId) > 0) {
        done.run(new Status(RaftError.ESTALE, "Loading a stale snapshot last_applied_index=%d last_applied_term=%d snapshot_index=%d snapshot_term=%d", lastAppliedId.getIndex(), lastAppliedId.getTerm(), snapshotId.getIndex(), snapshotId.getTerm()));
        return;
    }
    if (!this.fsm.onSnapshotLoad(reader)) {
        done.run(new Status(-1, "StateMachine onSnapshotLoad failed"));
        final RaftException e = new RaftException(ErrorType.ERROR_TYPE_STATE_MACHINE, RaftError.ESTATEMACHINE, "StateMachine onSnapshotLoad failed");
        setError(e);
        return;
    }
    if (meta.oldPeersList() == null) {
        // Joint stage is not supposed to be noticeable by end users.
        final Configuration conf = new Configuration();
        if (meta.peersList() != null) {
            for (String metaPeer : meta.peersList()) {
                final PeerId peer = new PeerId();
                Requires.requireTrue(peer.parse(metaPeer), "Parse peer failed");
                conf.addPeer(peer);
            }
        }
        this.fsm.onConfigurationCommitted(conf);
    }
    this.lastAppliedIndex.set(meta.lastIncludedIndex());
    this.lastAppliedTerm = meta.lastIncludedTerm();
    done.run(Status.OK());
}
Also used : Status(org.apache.ignite.raft.jraft.Status) RaftException(org.apache.ignite.raft.jraft.error.RaftException) Configuration(org.apache.ignite.raft.jraft.conf.Configuration) RaftOutter(org.apache.ignite.raft.jraft.entity.RaftOutter) SnapshotReader(org.apache.ignite.raft.jraft.storage.snapshot.SnapshotReader) LogId(org.apache.ignite.raft.jraft.entity.LogId) PeerId(org.apache.ignite.raft.jraft.entity.PeerId)

Example 4 with LogId

use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.

the class NodeImpl method logEntryFromMeta.

private LogEntry logEntryFromMeta(final long index, final ByteBuffer allData, final RaftOutter.EntryMeta entry) {
    if (entry.type() != EnumOutter.EntryType.ENTRY_TYPE_UNKNOWN) {
        final LogEntry logEntry = new LogEntry();
        logEntry.setId(new LogId(index, entry.term()));
        logEntry.setType(entry.type());
        if (entry.hasChecksum())
            // since 1.2.6
            logEntry.setChecksum(entry.checksum());
        final long dataLen = entry.dataLen();
        if (dataLen > 0) {
            final byte[] bs = new byte[(int) dataLen];
            assert allData != null;
            allData.get(bs, 0, bs.length);
            logEntry.setData(ByteBuffer.wrap(bs));
        }
        if (entry.peersList() != null) {
            if (entry.type() != EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION) {
                throw new IllegalStateException("Invalid log entry that contains peers but is not ENTRY_TYPE_CONFIGURATION type: " + entry.type());
            }
            fillLogEntryPeers(entry, logEntry);
        } else if (entry.type() == EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION) {
            throw new IllegalStateException("Invalid log entry that contains zero peers but is ENTRY_TYPE_CONFIGURATION type");
        }
        return logEntry;
    }
    return null;
}
Also used : LogId(org.apache.ignite.raft.jraft.entity.LogId) LogEntry(org.apache.ignite.raft.jraft.entity.LogEntry)

Example 5 with LogId

use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.

the class BaseLogEntryCodecFactoryTest method testEncodeDecodeWithData.

@Test
public void testEncodeDecodeWithData() {
    ByteBuffer buf = ByteBuffer.wrap("hello".getBytes(UTF_8));
    LogEntry entry = new LogEntry(EnumOutter.EntryType.ENTRY_TYPE_NO_OP);
    entry.setId(new LogId(100, 3));
    entry.setChecksum(123456L);
    entry.setData(buf);
    entry.setPeers(Arrays.asList(new PeerId("localhost", 99, 1), new PeerId("localhost", 100, 2)));
    entry.setOldPeers(Arrays.asList(new PeerId("localhost", 99, 1), new PeerId("localhost", 100, 2)));
    entry.setLearners(Arrays.asList(new PeerId("localhost", 99, 1), new PeerId("localhost", 100, 2)));
    entry.setOldLearners(Arrays.asList(new PeerId("localhost", 99, 1), new PeerId("localhost", 100, 2)));
    assertEquals(buf, entry.getData());
    byte[] content = this.encoder.encode(entry);
    assertNotNull(content);
    assertTrue(content.length > 0);
    LogEntry nentry = this.decoder.decode(content);
    assertNotNull(nentry);
    assertEquals(100, nentry.getId().getIndex());
    assertEquals(3, nentry.getId().getTerm());
    assertEquals(123456L, nentry.getChecksum());
    List<PeerId> peers = nentry.getPeers();
    assertEquals(2, peers.size());
    assertEquals("localhost:99:1", peers.get(0).toString());
    assertEquals("localhost:100:2", peers.get(1).toString());
    peers = nentry.getOldPeers();
    assertEquals(2, peers.size());
    assertEquals("localhost:99:1", peers.get(0).toString());
    assertEquals("localhost:100:2", peers.get(1).toString());
    peers = nentry.getLearners();
    assertEquals(2, peers.size());
    assertEquals("localhost:99:1", peers.get(0).toString());
    assertEquals("localhost:100:2", peers.get(1).toString());
    peers = nentry.getOldLearners();
    assertEquals(2, peers.size());
    assertEquals("localhost:99:1", peers.get(0).toString());
    assertEquals("localhost:100:2", peers.get(1).toString());
    assertEquals(buf, nentry.getData());
    assertEquals(0, nentry.getData().position());
    assertEquals(5, nentry.getData().remaining());
}
Also used : ByteBuffer(java.nio.ByteBuffer) LogId(org.apache.ignite.raft.jraft.entity.LogId) LogEntry(org.apache.ignite.raft.jraft.entity.LogEntry) PeerId(org.apache.ignite.raft.jraft.entity.PeerId) Test(org.junit.jupiter.api.Test)

Aggregations

LogId (org.apache.ignite.raft.jraft.entity.LogId)41 LogEntry (org.apache.ignite.raft.jraft.entity.LogEntry)24 Test (org.junit.jupiter.api.Test)15 PeerId (org.apache.ignite.raft.jraft.entity.PeerId)14 ArrayList (java.util.ArrayList)10 Status (org.apache.ignite.raft.jraft.Status)10 BaseStorageTest (org.apache.ignite.raft.jraft.storage.BaseStorageTest)9 ConfigurationEntry (org.apache.ignite.raft.jraft.conf.ConfigurationEntry)7 Configuration (org.apache.ignite.raft.jraft.conf.Configuration)5 ByteBuffer (java.nio.ByteBuffer)4 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 LogManager (org.apache.ignite.raft.jraft.storage.LogManager)4 ConfigurationManager (org.apache.ignite.raft.jraft.conf.ConfigurationManager)3 StripedDisruptor (org.apache.ignite.raft.jraft.disruptor.StripedDisruptor)2 EntryType (org.apache.ignite.raft.jraft.entity.EnumOutter.EntryType)2 RaftException (org.apache.ignite.raft.jraft.error.RaftException)2 LogStorageOptions (org.apache.ignite.raft.jraft.option.LogStorageOptions)2 NodeOptions (org.apache.ignite.raft.jraft.option.NodeOptions)2 RaftOptions (org.apache.ignite.raft.jraft.option.RaftOptions)2