/* * INESC-ID, Instituto de Engenharia de Sistemas e Computadores Investigação e Desevolvimento em Lisboa * Copyright 2013 INESC-ID and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3.0 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.infinispan.dataplacement; import org.infinispan.commons.hash.Hash; import org.infinispan.distribution.TestAddress; import org.infinispan.remoting.transport.Address; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * Cluster Snapshot testing * * @author Pedro Ruivo * @since 5.2 */ @Test(groups = "functional", testName = "dataplacement.ClusterSnapshotTest") public class ClusterSnapshotTest { private static final Log log = LogFactory.getLog(ClusterSnapshotTest.class); private final TestHash HASH_FUNCTION = new TestHash(); public void testEmpty() { ClusterSnapshot clusterSnapshot = createClusterSnapshot(0, new LinkedList<Address>()); assert !clusterSnapshot.contains(new TestAddress(0)); assert clusterSnapshot.get(0) == null; assert clusterSnapshot.get(-10) == null; assert clusterSnapshot.indexOf(new TestAddress(1)) == -1; } public void testGet() { ArrayList<Address> members = new ArrayList<Address>(); ClusterSnapshot clusterSnapshot = createClusterSnapshot(100, members); for (Address address : members) { assert clusterSnapshot.contains(address); int index = clusterSnapshot.indexOf(address); assert index != -1; assert address.equals(clusterSnapshot.get(index)); } } public void testContainsAll() { ArrayList<Address> members = new ArrayList<Address>(100); ClusterSnapshot snapshot = createClusterSnapshot(100, members); for (Address address : members) { assert snapshot.contains(address); assert snapshot.indexOf(address) != -1; } } public void testNotContains() { ArrayList<Address> members = new ArrayList<Address>(100); ClusterSnapshot snapshot = createClusterSnapshot(100, members); assert !snapshot.contains(new TestAddress(101)); assert snapshot.indexOf(new TestAddress(101)) == -1; assert snapshot.get(101) == null; } public void testSameIndex() { ArrayList<Address> members = new ArrayList<Address>(100); ClusterSnapshot snapshot = createClusterSnapshot(100, members); Address address = new TestAddress(10); assert snapshot.contains(address); int index = snapshot.indexOf(address); for (int i = 0; i < 10; i++) { assert index == snapshot.indexOf(address); } } public void testNonContainsConflicting() { ArrayList<Address> members = new ArrayList<Address>(100); ClusterSnapshot snapshot = createClusterSnapshot(100, members); Address address = new TestAddress(101); Address conflicting = new TestAddress(-101); assert HASH_FUNCTION.hash(address) == HASH_FUNCTION.hash(conflicting); assert !address.equals(conflicting); assert !snapshot.contains(conflicting); assert snapshot.indexOf(conflicting) == -1; } public void testContainsConflicting() { ArrayList<Address> members = new ArrayList<Address>(100); createConflictingHash(50, members); ClusterSnapshot snapshot = createClusterSnapshot(50, members); Address address = new TestAddress(10); Address conflicting = new TestAddress(-10); assert HASH_FUNCTION.hash(address) == HASH_FUNCTION.hash(conflicting); assert !address.equals(conflicting); assert snapshot.contains(conflicting); assert snapshot.contains(address); int aIndex = snapshot.indexOf(address); int cIndex = snapshot.indexOf(conflicting); assert aIndex != -1; assert cIndex != -1; assert aIndex != cIndex; } public void testSize() { ClusterSnapshot snapshot = createClusterSnapshot(10, new LinkedList<Address>()); assert snapshot.size() == 10; snapshot = createClusterSnapshot(15, new LinkedList<Address>()); assert snapshot.size() == 15; snapshot = createClusterSnapshot(0, new LinkedList<Address>()); assert snapshot.size() == 0; } public void testPerformance() { int size = 10000; ArrayList<Address> members = new ArrayList<Address>(); ClusterSnapshot snapshot = createClusterSnapshot(size, members); performance(members, snapshot, "0% Hash Conflicts"); members.clear(); for (int i = 0; i < size / 2; ++i) { members.add(new SameHashAddress(i)); } snapshot = createClusterSnapshot(size / 2, members); performance(members, snapshot, "50% Hash Conflicts"); members.clear(); for (int i = 0; i < size; ++i) { members.add(new SameHashAddress(i)); } snapshot = createClusterSnapshot(0, members); performance(members, snapshot, "100% Hash Conflicts"); } private void performance(ArrayList<Address> members, ClusterSnapshot snapshot, String title) { for (int iteration = 0; iteration < 5; ++iteration) { long start = System.currentTimeMillis(); for (Address address : members) { int index = members.indexOf(address); assert index != -1; } long end = System.currentTimeMillis(); long arrayListDuration = end - start; start = System.currentTimeMillis(); for (Address address : members) { int index = snapshot.indexOf(address); assert index != -1; } end = System.currentTimeMillis(); long clusterSnapshotDuration = end - start; String msg = String.format("Performance results[%s,%s]: Array List: %s ms, Cluster Snapshot: %s ms", iteration, title, arrayListDuration, clusterSnapshotDuration); log.info(msg); } } private void createConflictingHash(int size, List<Address> members) { for (int i = 0; i < size; i++) { members.add(new TestAddress(i * -1)); } } private ClusterSnapshot createClusterSnapshot(int size, List<Address> members) { for (int i = 0; i < size; ++i) { members.add(new TestAddress(i)); } Address[] membersArray = members.toArray(new Address[size]); ClusterSnapshot clusterSnapshot = new ClusterSnapshot(membersArray, HASH_FUNCTION); log.infof("Created cluster snapshot: %s", clusterSnapshot); return clusterSnapshot; } private class TestHash implements Hash { @Override public int hash(byte[] payload) { return 0; } @Override public int hash(int hashcode) { return hashcode; } @Override public int hash(Object o) { if (o instanceof SameHashAddress) { return 0; } return Math.abs(o.hashCode()); } } private class SameHashAddress extends TestAddress { private SameHashAddress(int addressNum) { super(addressNum); } } }