Search in sources :

Example 6 with SynchronizedClosure

use of org.apache.ignite.raft.jraft.closure.SynchronizedClosure in project ignite-3 by apache.

the class ItNodeTest method testChangePeers.

@Test
public void testChangePeers() throws Exception {
    PeerId peer0 = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT);
    cluster = new TestCluster("testChangePeers", dataPath, Collections.singletonList(peer0), testInfo);
    assertTrue(cluster.start(peer0.getEndpoint()));
    cluster.waitLeader();
    Node leader = cluster.getLeader();
    sendTestTaskAndWait(leader);
    for (int i = 1; i < 10; i++) {
        PeerId peer = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT + i);
        assertTrue(cluster.start(peer.getEndpoint(), false, 300));
    }
    for (int i = 0; i < 9; i++) {
        cluster.waitLeader();
        leader = cluster.getLeader();
        assertNotNull(leader);
        PeerId peer = new PeerId(TestUtils.getLocalAddress(), peer0.getEndpoint().getPort() + i);
        assertEquals(peer, leader.getNodeId().getPeerId());
        peer = new PeerId(TestUtils.getLocalAddress(), peer0.getEndpoint().getPort() + i + 1);
        SynchronizedClosure done = new SynchronizedClosure();
        leader.changePeers(new Configuration(Collections.singletonList(peer)), done);
        Status status = done.await();
        assertTrue(status.isOk(), status.getRaftError().toString());
    }
    cluster.waitLeader();
    for (MockStateMachine fsm : cluster.getFsms()) {
        assertEquals(10, fsm.getLogs().size());
    }
}
Also used : Status(org.apache.ignite.raft.jraft.Status) SynchronizedClosure(org.apache.ignite.raft.jraft.closure.SynchronizedClosure) Configuration(org.apache.ignite.raft.jraft.conf.Configuration) Node(org.apache.ignite.raft.jraft.Node) Endpoint(org.apache.ignite.raft.jraft.util.Endpoint) PeerId(org.apache.ignite.raft.jraft.entity.PeerId) Test(org.junit.jupiter.api.Test)

Example 7 with SynchronizedClosure

use of org.apache.ignite.raft.jraft.closure.SynchronizedClosure in project ignite-3 by apache.

the class ItNodeTest method testChangePeersStepsDownInJointConsensus.

@Test
public void testChangePeersStepsDownInJointConsensus() throws Exception {
    List<PeerId> peers = new ArrayList<>();
    PeerId peer0 = JRaftUtils.getPeerId(TestUtils.getLocalAddress() + ":5006");
    PeerId peer1 = JRaftUtils.getPeerId(TestUtils.getLocalAddress() + ":5007");
    PeerId peer2 = JRaftUtils.getPeerId(TestUtils.getLocalAddress() + ":5008");
    PeerId peer3 = JRaftUtils.getPeerId(TestUtils.getLocalAddress() + ":5009");
    // start single cluster
    peers.add(peer0);
    cluster = new TestCluster("testChangePeersStepsDownInJointConsensus", dataPath, peers, testInfo);
    assertTrue(cluster.start(peer0.getEndpoint()));
    cluster.waitLeader();
    Node leader = cluster.getLeader();
    assertNotNull(leader);
    sendTestTaskAndWait(leader);
    // start peer1-3
    assertTrue(cluster.start(peer1.getEndpoint()));
    assertTrue(cluster.start(peer2.getEndpoint()));
    assertTrue(cluster.start(peer3.getEndpoint()));
    // Make sure the topology is ready before adding peers.
    assertTrue(waitForTopology(cluster, leader.getNodeId().getPeerId().getEndpoint(), 4, 3_000));
    Configuration conf = new Configuration();
    conf.addPeer(peer0);
    conf.addPeer(peer1);
    conf.addPeer(peer2);
    conf.addPeer(peer3);
    // change peers
    SynchronizedClosure done = new SynchronizedClosure();
    leader.changePeers(conf, done);
    assertTrue(done.await().isOk());
    // stop peer3
    assertTrue(cluster.stop(peer3.getEndpoint()));
    conf.removePeer(peer0);
    conf.removePeer(peer1);
    // Change peers to [peer2, peer3], which must fail since peer3 is stopped
    done.reset();
    leader.changePeers(conf, done);
    assertEquals(RaftError.EPERM, done.await().getRaftError());
    LOG.info(done.getStatus().toString());
    assertFalse(((NodeImpl) leader).getConf().isStable());
    leader = cluster.getLeader();
    assertNull(leader);
    assertTrue(cluster.start(peer3.getEndpoint()));
    Thread.sleep(1000);
    cluster.waitLeader();
    leader = cluster.getLeader();
    List<PeerId> thePeers = leader.listPeers();
    assertTrue(!thePeers.isEmpty());
    assertEquals(conf.getPeerSet(), new HashSet<>(thePeers));
}
Also used : SynchronizedClosure(org.apache.ignite.raft.jraft.closure.SynchronizedClosure) Configuration(org.apache.ignite.raft.jraft.conf.Configuration) Node(org.apache.ignite.raft.jraft.Node) ArrayList(java.util.ArrayList) PeerId(org.apache.ignite.raft.jraft.entity.PeerId) Test(org.junit.jupiter.api.Test)

Example 8 with SynchronizedClosure

use of org.apache.ignite.raft.jraft.closure.SynchronizedClosure in project ignite-3 by apache.

the class NodeImpl method bootstrap.

public boolean bootstrap(final BootstrapOptions opts) throws InterruptedException {
    if (opts.getLastLogIndex() > 0 && (opts.getGroupConf().isEmpty() || opts.getFsm() == null)) {
        LOG.error("Invalid arguments for bootstrap, groupConf={}, fsm={}, lastLogIndex={}.", opts.getGroupConf(), opts.getFsm(), opts.getLastLogIndex());
        return false;
    }
    if (opts.getGroupConf().isEmpty()) {
        LOG.error("Bootstrapping an empty node makes no sense.");
        return false;
    }
    Requires.requireNonNull(opts.getServiceFactory(), "Null jraft service factory");
    this.serviceFactory = opts.getServiceFactory();
    // Term is not an option since changing it is very dangerous
    final long bootstrapLogTerm = opts.getLastLogIndex() > 0 ? 1 : 0;
    final LogId bootstrapId = new LogId(opts.getLastLogIndex(), bootstrapLogTerm);
    this.options = opts.getNodeOptions() == null ? new NodeOptions() : opts.getNodeOptions();
    this.raftOptions = this.options.getRaftOptions();
    this.metrics = new NodeMetrics(opts.isEnableMetrics());
    this.options.setFsm(opts.getFsm());
    this.options.setLogUri(opts.getLogUri());
    this.options.setRaftMetaUri(opts.getRaftMetaUri());
    this.options.setSnapshotUri(opts.getSnapshotUri());
    this.configManager = new ConfigurationManager();
    // Create fsmCaller at first as logManager needs it to report error
    this.fsmCaller = new FSMCallerImpl();
    initPools(opts.getNodeOptions());
    if (!initLogStorage()) {
        LOG.error("Fail to init log storage.");
        return false;
    }
    if (!initMetaStorage()) {
        LOG.error("Fail to init meta storage.");
        return false;
    }
    if (this.currTerm == 0) {
        this.currTerm = 1;
        if (!this.metaStorage.setTermAndVotedFor(1, new PeerId())) {
            LOG.error("Fail to set term.");
            return false;
        }
    }
    if (opts.getFsm() != null && !initFSMCaller(bootstrapId)) {
        LOG.error("Fail to init fsm caller.");
        return false;
    }
    final LogEntry entry = new LogEntry(EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION);
    entry.getId().setTerm(this.currTerm);
    entry.setPeers(opts.getGroupConf().listPeers());
    entry.setLearners(opts.getGroupConf().listLearners());
    final List<LogEntry> entries = new ArrayList<>();
    entries.add(entry);
    final BootstrapStableClosure bootstrapDone = new BootstrapStableClosure();
    this.logManager.appendEntries(entries, bootstrapDone);
    if (!bootstrapDone.await().isOk()) {
        LOG.error("Fail to append configuration.");
        return false;
    }
    if (opts.getLastLogIndex() > 0) {
        if (!initSnapshotStorage()) {
            LOG.error("Fail to init snapshot storage.");
            return false;
        }
        final SynchronizedClosure snapshotDone = new SynchronizedClosure();
        this.snapshotExecutor.doSnapshot(snapshotDone);
        if (!snapshotDone.await().isOk()) {
            LOG.error("Fail to save snapshot, status={}.", snapshotDone.getStatus());
            return false;
        }
    }
    if (this.logManager.getFirstLogIndex() != opts.getLastLogIndex() + 1) {
        throw new IllegalStateException("First and last log index mismatch");
    }
    if (opts.getLastLogIndex() > 0) {
        if (this.logManager.getLastLogIndex() != opts.getLastLogIndex()) {
            throw new IllegalStateException("Last log index mismatch");
        }
    } else {
        if (this.logManager.getLastLogIndex() != opts.getLastLogIndex() + 1) {
            throw new IllegalStateException("Last log index mismatch");
        }
    }
    return true;
}
Also used : SynchronizedClosure(org.apache.ignite.raft.jraft.closure.SynchronizedClosure) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) NodeOptions(org.apache.ignite.raft.jraft.option.NodeOptions) LogId(org.apache.ignite.raft.jraft.entity.LogId) ConfigurationManager(org.apache.ignite.raft.jraft.conf.ConfigurationManager) LogEntry(org.apache.ignite.raft.jraft.entity.LogEntry) PeerId(org.apache.ignite.raft.jraft.entity.PeerId)

Example 9 with SynchronizedClosure

use of org.apache.ignite.raft.jraft.closure.SynchronizedClosure in project ignite-3 by apache.

the class ItNodeTest method testChangePeersChaosWithoutSnapshot.

@Test
public void testChangePeersChaosWithoutSnapshot() throws Exception {
    // start cluster
    List<PeerId> peers = new ArrayList<>();
    peers.add(new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT));
    cluster = new TestCluster("unittest", dataPath, peers, ELECTION_TIMEOUT_MILLIS, testInfo);
    assertTrue(cluster.start(peers.get(0).getEndpoint(), false, 100000));
    // start other peers
    for (int i = 1; i < 10; i++) {
        PeerId peer = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT + i);
        peers.add(peer);
        assertTrue(cluster.start(peer.getEndpoint(), false, 10000));
    }
    ChangeArg arg = new ChangeArg(cluster, peers, false, true);
    Future<?> future = startChangePeersThread(arg);
    final int tasks = 5000;
    for (int i = 0; i < tasks; ) {
        cluster.waitLeader();
        Node leader = cluster.getLeader();
        if (leader == null)
            continue;
        SynchronizedClosure done = new SynchronizedClosure();
        Task task = new Task(ByteBuffer.wrap(("hello" + i).getBytes(UTF_8)), done);
        leader.apply(task);
        Status status = done.await();
        if (status.isOk()) {
            if (++i % 100 == 0)
                System.out.println("Progress:" + i);
        } else
            assertEquals(RaftError.EPERM, status.getRaftError());
    }
    arg.stop = true;
    future.get();
    cluster.waitLeader();
    SynchronizedClosure done = new SynchronizedClosure();
    Node leader = cluster.getLeader();
    leader.changePeers(new Configuration(peers), done);
    assertTrue(done.await().isOk());
    cluster.ensureSame();
    assertEquals(10, cluster.getFsms().size());
    for (MockStateMachine fsm : cluster.getFsms()) {
        assertTrue(fsm.getLogs().size() >= tasks);
        assertTrue(fsm.getLogs().size() - tasks < 100);
    }
}
Also used : Status(org.apache.ignite.raft.jraft.Status) SynchronizedClosure(org.apache.ignite.raft.jraft.closure.SynchronizedClosure) Task(org.apache.ignite.raft.jraft.entity.Task) Configuration(org.apache.ignite.raft.jraft.conf.Configuration) Node(org.apache.ignite.raft.jraft.Node) ArrayList(java.util.ArrayList) Endpoint(org.apache.ignite.raft.jraft.util.Endpoint) PeerId(org.apache.ignite.raft.jraft.entity.PeerId) Test(org.junit.jupiter.api.Test)

Example 10 with SynchronizedClosure

use of org.apache.ignite.raft.jraft.closure.SynchronizedClosure in project ignite-3 by apache.

the class ItNodeTest method testTripleNodesWithLearners.

@Test
public void testTripleNodesWithLearners() throws Exception {
    List<PeerId> peers = TestUtils.generatePeers(3);
    cluster = new TestCluster("unittest", dataPath, peers, testInfo);
    for (PeerId peer : peers) assertTrue(cluster.start(peer.getEndpoint()));
    // elect leader
    cluster.waitLeader();
    // get leader
    Node leader = cluster.getLeader();
    assertNotNull(leader);
    cluster.ensureLeader(leader);
    assertEquals(3, leader.listPeers().size());
    assertTrue(leader.listLearners().isEmpty());
    assertTrue(leader.listAliveLearners().isEmpty());
    {
        // Adds a learner
        SynchronizedClosure done = new SynchronizedClosure();
        PeerId learnerPeer = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT + 3);
        // Start learner
        assertTrue(cluster.startLearner(learnerPeer));
        leader.addLearners(Arrays.asList(learnerPeer), done);
        assertTrue(done.await().isOk());
        assertEquals(1, leader.listAliveLearners().size());
        assertEquals(1, leader.listLearners().size());
    }
    // apply tasks to leader
    sendTestTaskAndWait(leader);
    {
        ByteBuffer data = ByteBuffer.wrap("no closure".getBytes(UTF_8));
        Task task = new Task(data, null);
        leader.apply(task);
    }
    {
        // task with TaskClosure
        ByteBuffer data = ByteBuffer.wrap("task closure".getBytes(UTF_8));
        List<String> cbs = synchronizedList(new ArrayList<>());
        CountDownLatch latch = new CountDownLatch(1);
        Task task = new Task(data, new TaskClosure() {

            @Override
            public void run(Status status) {
                cbs.add("apply");
                latch.countDown();
            }

            @Override
            public void onCommitted() {
                cbs.add("commit");
            }
        });
        leader.apply(task);
        latch.await();
        assertEquals(2, cbs.size());
        assertEquals("commit", cbs.get(0));
        assertEquals("apply", cbs.get(1));
    }
    assertEquals(4, cluster.getFsms().size());
    assertEquals(2, cluster.getFollowers().size());
    assertEquals(1, cluster.getLearners().size());
    cluster.ensureSame();
    {
        // Adds another learner
        SynchronizedClosure done = new SynchronizedClosure();
        PeerId learnerPeer = new PeerId(TestUtils.getLocalAddress(), TestUtils.INIT_PORT + 4);
        // Start learner
        assertTrue(cluster.startLearner(learnerPeer));
        leader.addLearners(Arrays.asList(learnerPeer), done);
        assertTrue(done.await().isOk());
        assertEquals(2, leader.listAliveLearners().size());
        assertEquals(2, leader.listLearners().size());
        cluster.ensureSame();
    }
    {
        // stop two followers
        for (Node follower : cluster.getFollowers()) assertTrue(cluster.stop(follower.getNodeId().getPeerId().getEndpoint()));
        // send a new task
        ByteBuffer data = ByteBuffer.wrap("task closure".getBytes(UTF_8));
        SynchronizedClosure done = new SynchronizedClosure();
        leader.apply(new Task(data, done));
        // should fail
        assertFalse(done.await().isOk());
        assertEquals(RaftError.EPERM, done.getStatus().getRaftError());
        // One peer with two learners.
        assertEquals(3, cluster.getFsms().size());
    }
}
Also used : Status(org.apache.ignite.raft.jraft.Status) SynchronizedClosure(org.apache.ignite.raft.jraft.closure.SynchronizedClosure) Task(org.apache.ignite.raft.jraft.entity.Task) Node(org.apache.ignite.raft.jraft.Node) ArrayList(java.util.ArrayList) Collections.synchronizedList(java.util.Collections.synchronizedList) ArrayList(java.util.ArrayList) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBuffer(java.nio.ByteBuffer) PeerId(org.apache.ignite.raft.jraft.entity.PeerId) TaskClosure(org.apache.ignite.raft.jraft.closure.TaskClosure) Test(org.junit.jupiter.api.Test)

Aggregations

SynchronizedClosure (org.apache.ignite.raft.jraft.closure.SynchronizedClosure)13 Test (org.junit.jupiter.api.Test)11 Node (org.apache.ignite.raft.jraft.Node)10 PeerId (org.apache.ignite.raft.jraft.entity.PeerId)10 ArrayList (java.util.ArrayList)7 Configuration (org.apache.ignite.raft.jraft.conf.Configuration)7 Endpoint (org.apache.ignite.raft.jraft.util.Endpoint)7 Status (org.apache.ignite.raft.jraft.Status)6 Task (org.apache.ignite.raft.jraft.entity.Task)4 ExecutorService (java.util.concurrent.ExecutorService)3 LinkedHashSet (java.util.LinkedHashSet)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 SaveSnapshotClosure (org.apache.ignite.raft.jraft.closure.SaveSnapshotClosure)2 NodeOptions (org.apache.ignite.raft.jraft.option.NodeOptions)2 ByteBuffer (java.nio.ByteBuffer)1 Collections.synchronizedList (java.util.Collections.synchronizedList)1 HashSet (java.util.HashSet)1 List (java.util.List)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1