/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.quorum; import com.hazelcast.config.CacheSimpleConfig; import com.hazelcast.config.Config; import com.hazelcast.config.LockConfig; import com.hazelcast.config.MapConfig; import com.hazelcast.config.QueueConfig; import com.hazelcast.config.QuorumConfig; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.MembershipAdapter; import com.hazelcast.core.MembershipEvent; import com.hazelcast.instance.Node; import com.hazelcast.nio.tcp.FirewallingConnectionManager; import com.hazelcast.spi.properties.GroupProperty; import com.hazelcast.test.AssertTask; import com.hazelcast.test.TestHazelcastInstanceFactory; import java.util.concurrent.CountDownLatch; import static com.hazelcast.test.HazelcastTestSupport.assertClusterSize; import static com.hazelcast.test.HazelcastTestSupport.assertClusterSizeEventually; import static com.hazelcast.test.HazelcastTestSupport.assertOpenEventually; import static com.hazelcast.test.HazelcastTestSupport.assertTrueEventually; import static com.hazelcast.test.HazelcastTestSupport.generateRandomString; import static com.hazelcast.test.HazelcastTestSupport.getNode; import static com.hazelcast.test.HazelcastTestSupport.suspectMember; import static org.junit.Assert.assertFalse; public class PartitionedCluster { private static final String SUCCESSFUL_SPLIT_TEST_QUORUM_NAME = "SUCCESSFUL_SPLIT_TEST_QUORUM"; public HazelcastInstance h1; public HazelcastInstance h2; public HazelcastInstance h3; public HazelcastInstance h4; public HazelcastInstance h5; protected TestHazelcastInstanceFactory factory; public PartitionedCluster(TestHazelcastInstanceFactory factory) { this.factory = factory; } public PartitionedCluster partitionFiveMembersThreeAndTwo(MapConfig mapConfig, QuorumConfig quorumConfig) { createFiveMemberCluster(mapConfig, quorumConfig); return splitFiveMembersThreeAndTwo(); } public PartitionedCluster partitionFiveMembersThreeAndTwo(CacheSimpleConfig cacheSimpleConfig, QuorumConfig quorumConfig) { createFiveMemberCluster(cacheSimpleConfig, quorumConfig); return splitFiveMembersThreeAndTwo(); } public PartitionedCluster partitionFiveMembersThreeAndTwo(QueueConfig qConfig, QuorumConfig quorumConfig) { createFiveMemberCluster(qConfig, quorumConfig); return splitFiveMembersThreeAndTwo(); } private PartitionedCluster createFiveMemberCluster(MapConfig mapConfig, QuorumConfig quorumConfig) { Config config = createClusterConfig() .addMapConfig(mapConfig) .addQuorumConfig(quorumConfig); createInstances(config); return this; } public PartitionedCluster createFiveMemberCluster(CacheSimpleConfig cacheSimpleConfig, QuorumConfig quorumConfig) { Config config = createClusterConfig() .addCacheConfig(cacheSimpleConfig) .addQuorumConfig(quorumConfig); createInstances(config); return this; } public PartitionedCluster createFiveMemberCluster(QueueConfig queueConfig, QuorumConfig quorumConfig) { Config config = createClusterConfig() .addQueueConfig(queueConfig) .addQuorumConfig(quorumConfig); createInstances(config); return this; } public PartitionedCluster createFiveMemberCluster(LockConfig lockConfig, QuorumConfig quorumConfig) { Config config = createClusterConfig() .addLockConfig(lockConfig) .addQuorumConfig(quorumConfig); createInstances(config); return this; } private Config createClusterConfig() { Config config = new Config(); config.setProperty(GroupProperty.MERGE_FIRST_RUN_DELAY_SECONDS.getName(), "9999"); config.setProperty(GroupProperty.MERGE_NEXT_RUN_DELAY_SECONDS.getName(), "9999"); config.getGroupConfig().setName(generateRandomString(10)); config.addQuorumConfig(createSuccessfulSplitTestQuorum()); return config; } public PartitionedCluster splitFiveMembersThreeAndTwo() { final CountDownLatch splitLatch = new CountDownLatch(6); h4.getCluster().addMembershipListener(new MembershipAdapter() { @Override public void memberRemoved(MembershipEvent membershipEvent) { splitLatch.countDown(); } }); h5.getCluster().addMembershipListener(new MembershipAdapter() { @Override public void memberRemoved(MembershipEvent membershipEvent) { splitLatch.countDown(); } }); splitCluster(); assertOpenEventually(splitLatch, 30); assertClusterSizeEventually(3, h1, h2, h3); assertClusterSizeEventually(2, h4, h5); assertTrueEventually(new AssertTask() { @Override public void run() throws Exception { assertFalse(h4.getQuorumService().getQuorum(SUCCESSFUL_SPLIT_TEST_QUORUM_NAME).isPresent()); assertFalse(h5.getQuorumService().getQuorum(SUCCESSFUL_SPLIT_TEST_QUORUM_NAME).isPresent()); } }); return this; } private void createInstances(Config config) { h1 = factory.newHazelcastInstance(config); h2 = factory.newHazelcastInstance(config); h3 = factory.newHazelcastInstance(config); h4 = factory.newHazelcastInstance(config); h5 = factory.newHazelcastInstance(config); assertClusterSize(5, h1, h4); assertClusterSizeEventually(5, h2, h3, h4); } private QuorumConfig createSuccessfulSplitTestQuorum() { QuorumConfig splitConfig = new QuorumConfig(); splitConfig.setEnabled(true); splitConfig.setSize(3); splitConfig.setName(SUCCESSFUL_SPLIT_TEST_QUORUM_NAME); return splitConfig; } private void splitCluster() { Node n1 = getNode(h1); Node n2 = getNode(h2); Node n3 = getNode(h3); Node n4 = getNode(h4); Node n5 = getNode(h5); FirewallingConnectionManager cm1 = getConnectionManager(n1); FirewallingConnectionManager cm2 = getConnectionManager(n2); FirewallingConnectionManager cm3 = getConnectionManager(n3); FirewallingConnectionManager cm4 = getConnectionManager(n4); FirewallingConnectionManager cm5 = getConnectionManager(n5); cm1.block(n4.address); cm2.block(n4.address); cm3.block(n4.address); cm1.block(n5.address); cm2.block(n5.address); cm3.block(n5.address); cm4.block(n1.address); cm4.block(n2.address); cm4.block(n3.address); cm5.block(n1.address); cm5.block(n2.address); cm5.block(n3.address); suspectMember(n4, n1); suspectMember(n4, n2); suspectMember(n4, n3); suspectMember(n5, n1); suspectMember(n5, n2); suspectMember(n5, n3); suspectMember(n1, n4); suspectMember(n2, n4); suspectMember(n3, n4); suspectMember(n1, n5); suspectMember(n2, n5); suspectMember(n3, n5); } private static FirewallingConnectionManager getConnectionManager(Node node) { return (FirewallingConnectionManager) node.getConnectionManager(); } }