Search in sources :

Example 41 with VotingConfiguration

use of org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration in project crate by crate.

the class NodeJoinTests method testJoinWithHigherTermButBetterStateGetsRejected.

public void testJoinWithHigherTermButBetterStateGetsRejected() {
    DiscoveryNode node0 = newNode(0, true);
    DiscoveryNode node1 = newNode(1, true);
    long initialTerm = randomLongBetween(1, 10);
    long initialVersion = randomLongBetween(1, 10);
    setupFakeMasterServiceAndCoordinator(initialTerm, initialState(node0, initialTerm, initialVersion, new VotingConfiguration(Collections.singleton(node1.getId()))));
    assertFalse(isLocalNodeElectedMaster());
    long newTerm = initialTerm + randomLongBetween(1, 10);
    long higherVersion = initialVersion + randomLongBetween(1, 10);
    expectThrows(CoordinationStateRejectedException.class, () -> joinNodeAndRun(new JoinRequest(node1, Optional.of(new Join(node1, node0, newTerm, initialTerm, higherVersion)))));
    assertFalse(isLocalNodeElectedMaster());
}
Also used : DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) VotingConfiguration(org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration)

Example 42 with VotingConfiguration

use of org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration in project crate by crate.

the class NodeJoinTests method testConcurrentJoining.

public void testConcurrentJoining() {
    List<DiscoveryNode> masterNodes = IntStream.rangeClosed(1, randomIntBetween(2, 5)).mapToObj(nodeId -> newNode(nodeId, true)).collect(Collectors.toList());
    List<DiscoveryNode> otherNodes = IntStream.rangeClosed(masterNodes.size() + 1, masterNodes.size() + 1 + randomIntBetween(0, 5)).mapToObj(nodeId -> newNode(nodeId, false)).collect(Collectors.toList());
    List<DiscoveryNode> allNodes = Stream.concat(masterNodes.stream(), otherNodes.stream()).collect(Collectors.toList());
    DiscoveryNode localNode = masterNodes.get(0);
    VotingConfiguration votingConfiguration = new VotingConfiguration(randomValueOtherThan(singletonList(localNode), () -> randomSubsetOf(randomIntBetween(1, masterNodes.size()), masterNodes)).stream().map(DiscoveryNode::getId).collect(Collectors.toSet()));
    logger.info("Voting configuration: {}", votingConfiguration);
    long initialTerm = randomLongBetween(1, 10);
    long initialVersion = randomLongBetween(1, 10);
    setupRealMasterServiceAndCoordinator(initialTerm, initialState(localNode, initialTerm, initialVersion, votingConfiguration));
    long newTerm = initialTerm + randomLongBetween(1, 10);
    // we need at least a quorum of voting nodes with a correct term and worse state
    List<DiscoveryNode> successfulNodes;
    do {
        successfulNodes = randomSubsetOf(allNodes);
    } while (votingConfiguration.hasQuorum(successfulNodes.stream().map(DiscoveryNode::getId).collect(Collectors.toList())) == false);
    logger.info("Successful voting nodes: {}", successfulNodes);
    List<JoinRequest> correctJoinRequests = successfulNodes.stream().map(node -> new JoinRequest(node, Optional.of(new Join(node, localNode, newTerm, initialTerm, initialVersion)))).collect(Collectors.toList());
    List<DiscoveryNode> possiblyUnsuccessfulNodes = new ArrayList<>(allNodes);
    possiblyUnsuccessfulNodes.removeAll(successfulNodes);
    logger.info("Possibly unsuccessful voting nodes: {}", possiblyUnsuccessfulNodes);
    List<JoinRequest> possiblyFailingJoinRequests = possiblyUnsuccessfulNodes.stream().map(node -> {
        if (randomBoolean()) {
            // a correct request
            return new JoinRequest(node, Optional.of(new Join(node, localNode, newTerm, initialTerm, initialVersion)));
        } else if (randomBoolean()) {
            // term too low
            return new JoinRequest(node, Optional.of(new Join(node, localNode, randomLongBetween(0, initialTerm), initialTerm, initialVersion)));
        } else {
            // better state
            return new JoinRequest(node, Optional.of(new Join(node, localNode, newTerm, initialTerm, initialVersion + randomLongBetween(1, 10))));
        }
    }).collect(Collectors.toList());
    // duplicate some requests, which will be unsuccessful
    possiblyFailingJoinRequests.addAll(randomSubsetOf(possiblyFailingJoinRequests));
    CyclicBarrier barrier = new CyclicBarrier(correctJoinRequests.size() + possiblyFailingJoinRequests.size() + 1);
    final Runnable awaitBarrier = () -> {
        try {
            barrier.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            throw new RuntimeException(e);
        }
    };
    final AtomicBoolean stopAsserting = new AtomicBoolean();
    final Thread assertionThread = new Thread(() -> {
        awaitBarrier.run();
        while (stopAsserting.get() == false) {
            coordinator.invariant();
        }
    }, "assert invariants");
    final List<Thread> joinThreads = Stream.concat(correctJoinRequests.stream().map(joinRequest -> new Thread(() -> {
        awaitBarrier.run();
        joinNode(joinRequest);
    }, "process " + joinRequest)), possiblyFailingJoinRequests.stream().map(joinRequest -> new Thread(() -> {
        awaitBarrier.run();
        try {
            joinNode(joinRequest);
        } catch (CoordinationStateRejectedException e) {
        // ignore - these requests are expected to fail
        }
    }, "process " + joinRequest))).collect(Collectors.toList());
    assertionThread.start();
    joinThreads.forEach(Thread::start);
    joinThreads.forEach(t -> {
        try {
            t.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    });
    stopAsserting.set(true);
    try {
        assertionThread.join();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    assertTrue(MasterServiceTests.discoveryState(masterService).nodes().isLocalNodeElectedMaster());
    for (DiscoveryNode successfulNode : successfulNodes) {
        assertTrue(successfulNode + " joined cluster", clusterStateHasNode(successfulNode));
        assertFalse(successfulNode + " voted for master", coordinator.missingJoinVoteFrom(successfulNode));
    }
}
Also used : ESAllocationTestCase(org.elasticsearch.cluster.ESAllocationTestCase) HANDSHAKE_ACTION_NAME(org.elasticsearch.transport.TransportService.HANDSHAKE_ACTION_NAME) TransportRequest(org.elasticsearch.transport.TransportRequest) Random(java.util.Random) ClusterBlocks(org.elasticsearch.cluster.block.ClusterBlocks) CapturingTransport(org.elasticsearch.test.transport.CapturingTransport) Collections.singletonList(java.util.Collections.singletonList) ClusterState(org.elasticsearch.cluster.ClusterState) Settings(org.elasticsearch.common.settings.Settings) After(org.junit.After) ThreadPool(org.elasticsearch.threadpool.ThreadPool) ClusterName(org.elasticsearch.cluster.ClusterName) AfterClass(org.junit.AfterClass) CyclicBarrier(java.util.concurrent.CyclicBarrier) Transport(org.elasticsearch.transport.Transport) TestLogging(org.elasticsearch.test.junit.annotations.TestLogging) Collections.emptyList(java.util.Collections.emptyList) Set(java.util.Set) Collectors(java.util.stream.Collectors) List(java.util.List) Version(org.elasticsearch.Version) Stream(java.util.stream.Stream) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Optional(java.util.Optional) DiscoveryNodeRole(org.elasticsearch.cluster.node.DiscoveryNodeRole) Matchers.containsString(org.hamcrest.Matchers.containsString) IntStream(java.util.stream.IntStream) BeforeClass(org.junit.BeforeClass) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) RequestHandlerRegistry(org.elasticsearch.transport.RequestHandlerRegistry) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) BaseFuture(org.elasticsearch.common.util.concurrent.BaseFuture) Metadata(org.elasticsearch.cluster.metadata.Metadata) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) Node(org.elasticsearch.node.Node) TestTransportChannel(org.elasticsearch.transport.TestTransportChannel) VotingConfiguration(org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration) TransportResponse(org.elasticsearch.transport.TransportResponse) ESTestCase(org.elasticsearch.test.ESTestCase) TransportService(org.elasticsearch.transport.TransportService) MasterServiceTests(org.elasticsearch.cluster.service.MasterServiceTests) Collections.emptyMap(java.util.Collections.emptyMap) DiscoveryNodes(org.elasticsearch.cluster.node.DiscoveryNodes) TestThreadPool(org.elasticsearch.threadpool.TestThreadPool) FutureUtils(org.elasticsearch.common.util.concurrent.FutureUtils) MasterService(org.elasticsearch.cluster.service.MasterService) BrokenBarrierException(java.util.concurrent.BrokenBarrierException) TimeUnit(java.util.concurrent.TimeUnit) ClusterSettings(org.elasticsearch.common.settings.ClusterSettings) FakeThreadPoolMasterService(org.elasticsearch.cluster.service.FakeThreadPoolMasterService) ClusterServiceUtils(org.elasticsearch.test.ClusterServiceUtils) Collections(java.util.Collections) ActionListener(org.elasticsearch.action.ActionListener) Randomness(org.elasticsearch.common.Randomness) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) ArrayList(java.util.ArrayList) VotingConfiguration(org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration) CyclicBarrier(java.util.concurrent.CyclicBarrier) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean)

Example 43 with VotingConfiguration

use of org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration in project crate by crate.

the class NodeJoinTests method testJoinElectedLeader.

public void testJoinElectedLeader() {
    DiscoveryNode node0 = newNode(0, true);
    DiscoveryNode node1 = newNode(1, true);
    long initialTerm = randomLongBetween(1, 10);
    long initialVersion = randomLongBetween(1, 10);
    setupFakeMasterServiceAndCoordinator(initialTerm, initialState(node0, initialTerm, initialVersion, new VotingConfiguration(Collections.singleton(node0.getId()))));
    assertFalse(isLocalNodeElectedMaster());
    long newTerm = initialTerm + randomLongBetween(1, 10);
    joinNodeAndRun(new JoinRequest(node0, Optional.of(new Join(node0, node0, newTerm, initialTerm, initialVersion))));
    assertTrue(isLocalNodeElectedMaster());
    assertFalse(clusterStateHasNode(node1));
    joinNodeAndRun(new JoinRequest(node1, Optional.of(new Join(node1, node0, newTerm, initialTerm, initialVersion))));
    assertTrue(isLocalNodeElectedMaster());
    assertTrue(clusterStateHasNode(node1));
}
Also used : DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) VotingConfiguration(org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration)

Example 44 with VotingConfiguration

use of org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration in project crate by crate.

the class NodeJoinTests method testJoinFollowerFails.

public void testJoinFollowerFails() throws Exception {
    DiscoveryNode node0 = newNode(0, true);
    DiscoveryNode node1 = newNode(1, true);
    long initialTerm = randomLongBetween(1, 10);
    long initialVersion = randomLongBetween(1, 10);
    setupFakeMasterServiceAndCoordinator(initialTerm, initialState(node0, initialTerm, initialVersion, new VotingConfiguration(Collections.singleton(node0.getId()))));
    long newTerm = initialTerm + randomLongBetween(1, 10);
    handleStartJoinFrom(node1, newTerm);
    handleFollowerCheckFrom(node1, newTerm);
    assertThat(expectThrows(CoordinationStateRejectedException.class, () -> joinNodeAndRun(new JoinRequest(node1, Optional.empty()))).getMessage(), containsString("join target is a follower"));
    assertFalse(isLocalNodeElectedMaster());
}
Also used : DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) VotingConfiguration(org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration)

Example 45 with VotingConfiguration

use of org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration in project crate by crate.

the class NodeJoinTests method testJoinWithHigherTermButBetterStateStillElectsMasterThroughSelfJoin.

public void testJoinWithHigherTermButBetterStateStillElectsMasterThroughSelfJoin() {
    DiscoveryNode node0 = newNode(0, true);
    DiscoveryNode node1 = newNode(1, true);
    long initialTerm = randomLongBetween(1, 10);
    long initialVersion = randomLongBetween(1, 10);
    setupFakeMasterServiceAndCoordinator(initialTerm, initialState(node0, initialTerm, initialVersion, new VotingConfiguration(Collections.singleton(node0.getId()))));
    assertFalse(isLocalNodeElectedMaster());
    long newTerm = initialTerm + randomLongBetween(1, 10);
    long higherVersion = initialVersion + randomLongBetween(1, 10);
    joinNodeAndRun(new JoinRequest(node1, Optional.of(new Join(node1, node0, newTerm, initialTerm, higherVersion))));
    assertTrue(isLocalNodeElectedMaster());
}
Also used : DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) VotingConfiguration(org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration)

Aggregations

VotingConfiguration (org.elasticsearch.cluster.coordination.CoordinationMetadata.VotingConfiguration)66 ClusterState (org.elasticsearch.cluster.ClusterState)40 DiscoveryNode (org.elasticsearch.cluster.node.DiscoveryNode)19 DiscoveryNodes (org.elasticsearch.cluster.node.DiscoveryNodes)8 Set (java.util.Set)6 HashSet (java.util.HashSet)5 Settings (org.elasticsearch.common.settings.Settings)5 Tuple (io.crate.common.collections.Tuple)4 Collections (java.util.Collections)4 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)4 Collectors (java.util.stream.Collectors)4 ClusterSettings (org.elasticsearch.common.settings.ClusterSettings)4 TimeValue (io.crate.common.unit.TimeValue)3 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 Optional (java.util.Optional)3 TimeUnit (java.util.concurrent.TimeUnit)3 Stream (java.util.stream.Stream)3 ESTestCase (org.elasticsearch.test.ESTestCase)3