/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.cassandra.locator; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.dht.StringToken; import org.apache.cassandra.dht.Token; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; public class NetworkTopologyStrategyTest { private String keyspaceName = "Keyspace1"; private static final Logger logger = LoggerFactory.getLogger(NetworkTopologyStrategyTest.class); @Test public void testProperties() throws IOException, ConfigurationException { IEndpointSnitch snitch = new PropertyFileSnitch(); DatabaseDescriptor.setEndpointSnitch(snitch); TokenMetadata metadata = new TokenMetadata(); createDummyTokens(metadata, true); Map<String, String> configOptions = new HashMap<String, String>(); configOptions.put("DC1", "3"); configOptions.put("DC2", "2"); configOptions.put("DC3", "1"); // Set the localhost to the tokenmetadata. Embedded cassandra way? NetworkTopologyStrategy strategy = new NetworkTopologyStrategy(keyspaceName, metadata, snitch, configOptions); assert strategy.getReplicationFactor("DC1") == 3; assert strategy.getReplicationFactor("DC2") == 2; assert strategy.getReplicationFactor("DC3") == 1; // Query for the natural hosts ArrayList<InetAddress> endpoints = strategy.getNaturalEndpoints(new StringToken("123")); assert 6 == endpoints.size(); assert 6 == new HashSet<InetAddress>(endpoints).size(); // ensure uniqueness } @Test public void testPropertiesWithEmptyDC() throws IOException, ConfigurationException { IEndpointSnitch snitch = new PropertyFileSnitch(); DatabaseDescriptor.setEndpointSnitch(snitch); TokenMetadata metadata = new TokenMetadata(); createDummyTokens(metadata, false); Map<String, String> configOptions = new HashMap<String, String>(); configOptions.put("DC1", "3"); configOptions.put("DC2", "3"); configOptions.put("DC3", "0"); // Set the localhost to the tokenmetadata. Embedded cassandra way? NetworkTopologyStrategy strategy = new NetworkTopologyStrategy(keyspaceName, metadata, snitch, configOptions); assert strategy.getReplicationFactor("DC1") == 3; assert strategy.getReplicationFactor("DC2") == 3; assert strategy.getReplicationFactor("DC3") == 0; // Query for the natural hosts ArrayList<InetAddress> endpoints = strategy.getNaturalEndpoints(new StringToken("123")); assert 6 == endpoints.size(); assert 6 == new HashSet<InetAddress>(endpoints).size(); // ensure uniqueness } @Test public void testLargeCluster() throws UnknownHostException, ConfigurationException { int[] dcRacks = new int[]{2, 4, 8}; int[] dcEndpoints = new int[]{128, 256, 512}; int[] dcReplication = new int[]{2, 6, 6}; IEndpointSnitch snitch = new RackInferringSnitch(); DatabaseDescriptor.setEndpointSnitch(snitch); TokenMetadata metadata = new TokenMetadata(); Map<String, String> configOptions = new HashMap<String, String>(); Multimap<InetAddress, Token> tokens = HashMultimap.create(); int totalRF = 0; for (int dc = 0; dc < dcRacks.length; ++dc) { totalRF += dcReplication[dc]; configOptions.put(Integer.toString(dc), Integer.toString(dcReplication[dc])); for (int rack = 0; rack < dcRacks[dc]; ++rack) { for (int ep = 1; ep <= dcEndpoints[dc]/dcRacks[dc]; ++ep) { byte[] ipBytes = new byte[]{10, (byte)dc, (byte)rack, (byte)ep}; InetAddress address = InetAddress.getByAddress(ipBytes); StringToken token = new StringToken(String.format("%02x%02x%02x", ep, rack, dc)); logger.debug("adding node " + address + " at " + token); tokens.put(address, token); } } } metadata.updateNormalTokens(tokens); NetworkTopologyStrategy strategy = new NetworkTopologyStrategy(keyspaceName, metadata, snitch, configOptions); for (String testToken : new String[]{"123456", "200000", "000402", "ffffff", "400200"}) { List<InetAddress> endpoints = strategy.calculateNaturalEndpoints(new StringToken(testToken), metadata); Set<InetAddress> epSet = new HashSet<InetAddress>(endpoints); Assert.assertEquals(totalRF, endpoints.size()); Assert.assertEquals(totalRF, epSet.size()); logger.debug(testToken + ": " + endpoints.toString()); } } public void createDummyTokens(TokenMetadata metadata, boolean populateDC3) throws UnknownHostException { // DC 1 tokenFactory(metadata, "123", new byte[]{ 10, 0, 0, 10 }); tokenFactory(metadata, "234", new byte[]{ 10, 0, 0, 11 }); tokenFactory(metadata, "345", new byte[]{ 10, 0, 0, 12 }); // Tokens for DC 2 tokenFactory(metadata, "789", new byte[]{ 10, 20, 114, 10 }); tokenFactory(metadata, "890", new byte[]{ 10, 20, 114, 11 }); //tokens for DC3 if (populateDC3) { tokenFactory(metadata, "456", new byte[]{ 10, 21, 119, 13 }); tokenFactory(metadata, "567", new byte[]{ 10, 21, 119, 10 }); } // Extra Tokens tokenFactory(metadata, "90A", new byte[]{ 10, 0, 0, 13 }); if (populateDC3) tokenFactory(metadata, "0AB", new byte[]{ 10, 21, 119, 14 }); tokenFactory(metadata, "ABC", new byte[]{ 10, 20, 114, 15 }); } public void tokenFactory(TokenMetadata metadata, String token, byte[] bytes) throws UnknownHostException { Token token1 = new StringToken(token); InetAddress add1 = InetAddress.getByAddress(bytes); metadata.updateNormalToken(token1, add1); } }