[infinispan-commits] Infinispan SVN: r2622 - in trunk: core/src/main/java/org/infinispan/commands and 11 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed Oct 27 17:00:57 EDT 2010
Author: mircea.markus
Date: 2010-10-27 17:00:52 -0400 (Wed, 27 Oct 2010)
New Revision: 2622
Added:
trunk/core/src/main/java/org/infinispan/distribution/ch/
trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java
trunk/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java
trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java
trunk/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java
trunk/core/src/test/java/org/infinispan/distribution/DistributionManagerImplTest.java
trunk/core/src/test/java/org/infinispan/distribution/TopologyAwareConsistentHashTest.java
Removed:
trunk/core/src/main/java/org/infinispan/distribution/AbstractConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ConsistentHashHelper.java
trunk/core/src/main/java/org/infinispan/distribution/DefaultConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ExperimentalDefaultConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/UnionConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java
trunk/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java
trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java
trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java
trunk/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java
Modified:
trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceFactory.java
trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceImpl.java
trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java
trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java
trunk/core/src/main/java/org/infinispan/commands/control/RehashControlCommand.java
trunk/core/src/main/java/org/infinispan/commands/tx/CommitCommand.java
trunk/core/src/main/java/org/infinispan/config/Configuration.java
trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java
trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java
trunk/core/src/main/java/org/infinispan/distribution/InvertedLeaveTask.java
trunk/core/src/main/java/org/infinispan/distribution/JoinTask.java
trunk/core/src/main/java/org/infinispan/distribution/RehashTask.java
trunk/core/src/main/java/org/infinispan/distribution/TransactionLoggerImpl.java
trunk/core/src/main/java/org/infinispan/marshall/jboss/ConstantObjectTable.java
trunk/core/src/test/java/org/infinispan/affinity/BaseKeyAffinityServiceTest.java
trunk/core/src/test/java/org/infinispan/affinity/KeyAffinityServiceTest.java
trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java
trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java
trunk/core/src/test/java/org/infinispan/distribution/ConsistentHashPerfTest.java
trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java
trunk/core/src/test/java/org/infinispan/distribution/rehash/RehashTestBase.java
trunk/core/src/test/java/org/infinispan/distribution/rehash/WorkDuringJoinTest.java
trunk/server/hotrod/src/test/scala/org/infinispan/server/hotrod/HotRodDistributionTest.scala
Log:
[ISPN-180]-ongoing work
Modified: trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceFactory.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceFactory.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -12,7 +12,7 @@
* Services build by this factory have the following characteristics:
* <ul>
* <li>are run asynchronously by a thread that can be plugged through an {@link org.infinispan.executors.ExecutorFactory} </li>
- * <li>for key generation, the {@link org.infinispan.distribution.ConsistentHash} function of a distributed cache is used. Service does not make sense for replicated caches.</li>
+ * <li>for key generation, the {@link org.infinispan.distribution.ch.ConsistentHash} function of a distributed cache is used. Service does not make sense for replicated caches.</li>
* <li>for each address cluster member (identified by an {@link org.infinispan.remoting.transport.Address} member, a fixed number of keys is generated</li>
* </ul>
*
Modified: trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceImpl.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceImpl.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -3,7 +3,7 @@
import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;
import org.infinispan.Cache;
-import org.infinispan.distribution.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.notifications.cachemanagerlistener.event.CacheStoppedEvent;
Modified: trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -44,7 +44,7 @@
import org.infinispan.commands.write.ReplaceCommand;
import org.infinispan.commands.write.WriteCommand;
import org.infinispan.container.entries.InternalCacheValue;
-import org.infinispan.distribution.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.factories.scopes.Scope;
import org.infinispan.factories.scopes.Scopes;
import org.infinispan.remoting.transport.Address;
@@ -53,7 +53,6 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* A factory to build commands, initializing and injecting dependencies accordingly. Commands built for a specific,
Modified: trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -52,7 +52,7 @@
import org.infinispan.container.DataContainer;
import org.infinispan.container.entries.InternalCacheValue;
import org.infinispan.context.InvocationContextContainer;
-import org.infinispan.distribution.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.Start;
Modified: trunk/core/src/main/java/org/infinispan/commands/control/RehashControlCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/control/RehashControlCommand.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/commands/control/RehashControlCommand.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -11,7 +11,7 @@
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.container.entries.InternalCacheValue;
import org.infinispan.context.InvocationContext;
-import org.infinispan.distribution.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.loaders.CacheLoaderException;
import org.infinispan.loaders.CacheStore;
Modified: trunk/core/src/main/java/org/infinispan/commands/tx/CommitCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/tx/CommitCommand.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/commands/tx/CommitCommand.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -53,4 +53,9 @@
public byte getCommandId() {
return COMMAND_ID;
}
+
+ @Override
+ public String toString() {
+ return "CommitCommand{" + super.toString();
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/config/Configuration.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/Configuration.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/config/Configuration.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -21,7 +21,7 @@
*/
package org.infinispan.config;
-import org.infinispan.distribution.DefaultConsistentHash;
+import org.infinispan.distribution.ch.DefaultConsistentHash;
import org.infinispan.eviction.EvictionStrategy;
import org.infinispan.eviction.EvictionThreadPolicy;
import org.infinispan.factories.ComponentRegistry;
Deleted: trunk/core/src/main/java/org/infinispan/distribution/AbstractConsistentHash.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/AbstractConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/AbstractConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,32 +0,0 @@
-package org.infinispan.distribution;
-
-import org.infinispan.remoting.transport.Address;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * An abstract consistent hash implementation that handles common implementations of certain methods. In particular,
- * default implementations of {@link #locateAll(java.util.Collection, int)} and {@link #isKeyLocalToAddress(org.infinispan.remoting.transport.Address, Object, int)}.
- * <p />
- * The versions provided here are relatively inefficient in that they call {@link #locate(Object, int)} first (and
- * sometimes in a loop). Depending on the algorithm used, there may be more efficient ways to achieve the same results
- * and in such cases the methods provided here should be overridden.
- * <p />
- * @author Manik Surtani
- * @since 4.0
- */
-public abstract class AbstractConsistentHash implements ConsistentHash {
- public Map<Object, List<Address>> locateAll(Collection<Object> keys, int replCount) {
- Map<Object, List<Address>> locations = new HashMap<Object, List<Address>>();
- for (Object k : keys) locations.put(k, locate(k, replCount));
- return locations;
- }
-
- public boolean isKeyLocalToAddress(Address a, Object key, int replCount) {
- // simple, brute-force impl
- return locate(key, replCount).contains(a);
- }
-}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ConsistentHash.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,100 +0,0 @@
-package org.infinispan.distribution;
-
-import org.infinispan.remoting.transport.Address;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A consistent hash algorithm implementation. Implementations would typically be constructed via reflection so should
- * implement a public, no-arg constructor.
- *
- * @author Manik Surtani
- * @since 4.0
- */
-public interface ConsistentHash {
-
- /**
- * Sets the collection of cache addresses in the cluster. The implementation should store these internally and use
- * these to locate keys.
- *
- * @param caches caches in cluster.
- */
- void setCaches(List<Address> caches);
-
- /**
- * Should return a collection of cache addresses in the cluster.
- *
- * @return collection of cache addresses
- */
- List<Address> getCaches();
-
- /**
- * Locates a key, given a replication count (number of copies).
- *
- * @param key key to locate
- * @param replCount replication count (number of copies)
- * @return a list of addresses where the key resides, where this list is a subset of the addresses set in {@link
- * #setCaches(java.util.List)}. Should never be null, and should contain replCount elements or the max
- * number of caches available, whichever is smaller.
- */
- List<Address> locate(Object key, int replCount);
-
- /**
- * The logical equivalent of calling {@link #locate(Object, int)} multiple times for each key in the collection of
- * keys. Implementations may be optimised for such a bulk lookup, or may just repeatedly call {@link #locate(Object,
- * int)}.
- *
- * @param keys keys to locate
- * @param replCount replication count (number of copies) for each key
- * @return Map of locations, keyed on key.
- */
- Map<Object, List<Address>> locateAll(Collection<Object> keys, int replCount);
-
- /**
- * Calculates the logical distance between two addresses. This distance is based on where the addresses lie in the
- * hash space.
- *
- * @param a1 address to test
- * @param a2 address to test
- * @return the distance between the 2 nodes. Always a positive number, where the distance between a1 and itself is
- * 0. The distance between a1 and the next adjacent node is 1 and teh distance between a1 and the previous
- * adjacent node is caches.size() - 1. A -1 may be returned if either of the addresses do not exist.
- */
- int getDistance(Address a1, Address a2);
-
- /**
- * Tests whether two addresses are logically next to each other in the hash space.
- *
- * @param a1 address to test
- * @param a2 address to test
- * @return true if adjacent, false if not
- */
- boolean isAdjacent(Address a1, Address a2);
-
- /**
- * Test to see whether a key is mapped to a given address.
- * @param a address to test
- * @param key key to test
- * @param replCount repl count
- * @return true if the key is mapped to the address; false otherwise
- */
- boolean isKeyLocalToAddress(Address a, Object key, int replCount);
-
- /**
- * Returns the value between 0 and the hash space limit, or hash id, for a particular address. If there's no such
- * value for an address, this method will return -1.
- *
- * @return An int between 0 and hash space if the address is present in the hash wheel, otherwise it returns -1.
- */
- int getHashId(Address a);
-
- /**
- * Returns the hash space constant for this consistent hash algorithm class. This integer is often used as modulus
- * for arithmetic operations within the algorithm, for example, limiting the range of possible hash values.
- *
- * @return A positive integer containing the hash space constant or 0 is not supported by implementation.
- */
- int getHashSpace();
-}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ConsistentHashHelper.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ConsistentHashHelper.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ConsistentHashHelper.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,144 +0,0 @@
-package org.infinispan.distribution;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.Util;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * A helper class that handles the construction of consistent hash instances based on configuration.
- *
- * @author Manik Surtani
- * @since 4.0
- */
-public class ConsistentHashHelper {
-
- /**
- * Returns a new consistent hash of the same type with the given address removed.
- *
- * @param ch consistent hash to start with
- * @param toRemove address to remove
- * @param c configuration
- * @return a new consistent hash instance of the same type
- */
- public static ConsistentHash removeAddress(ConsistentHash ch, Address toRemove, Configuration c) {
- if (ch instanceof UnionConsistentHash)
- return removeAddressFromUnionConsistentHash((UnionConsistentHash) ch, toRemove, c);
- else {
- ConsistentHash newCH = (ConsistentHash) Util.getInstance(c.getConsistentHashClass());
- List<Address> caches = new ArrayList<Address>(ch.getCaches());
- caches.remove(toRemove);
- newCH.setCaches(caches);
- return newCH;
- }
- }
-
- /**
- * Creates a new UnionConsistentHash instance based on the old instance, removing the provided address from both
- * target consistent hash instances in the union.
- *
- * @param uch union consistent hash instance
- * @param toRemove address to remove
- * @param c configuration
- * @return a new UnionConsistentHash instance
- */
- public static UnionConsistentHash removeAddressFromUnionConsistentHash(UnionConsistentHash uch, Address toRemove, Configuration c) {
- ConsistentHash newFirstCH = removeAddress(uch.getOldConsistentHash(), toRemove, c);
- ConsistentHash newSecondCH = removeAddress(uch.getNewConsistentHash(), toRemove, c);
- return new UnionConsistentHash(newFirstCH, newSecondCH);
- }
-
- /**
- * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param c configuration
- * @param addresses with which to populate the consistent hash
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses) {
- ConsistentHash ch = (ConsistentHash) Util.getInstance(c.getConsistentHashClass());
- ch.setCaches(addresses);
- return ch;
- }
-
- /**
- * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param c configuration
- * @param addresses with which to populate the consistent hash
- * @param moreAddresses to add to the list of addresses
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses, Address... moreAddresses) {
- List<Address> list = new LinkedList<Address>(addresses);
- list.addAll(Arrays.asList(moreAddresses));
- return createConsistentHash(c, list);
- }
-
- /**
- * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param c configuration
- * @param addresses with which to populate the consistent hash
- * @param moreAddresses to add to the list of addresses
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses, Collection<Address> moreAddresses) {
- List<Address> list = new LinkedList<Address>(addresses);
- list.addAll(moreAddresses);
- return createConsistentHash(c, list);
- }
-
- /**
- * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param clazz type of the consistent hash to create
- * @param addresses with which to populate the consistent hash
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses) {
- ConsistentHash ch;
- ch = Util.getInstance(clazz);
- if (addresses != null && !addresses.isEmpty()) ch.setCaches(addresses);
- return ch;
- }
-
- /**
- * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param clazz type of the consistent hash to create
- * @param addresses with which to populate the consistent hash
- * @param moreAddresses to add to the list of addresses
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses, Address... moreAddresses) {
- List<Address> list = new LinkedList<Address>(addresses);
- list.addAll(Arrays.asList(moreAddresses));
- return createConsistentHash(clazz, list);
- }
-
- /**
- * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param clazz type of the consistent hash to create
- * @param addresses with which to populate the consistent hash
- * @param moreAddresses to add to the list of addresses
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses, Collection<Address> moreAddresses) {
- List<Address> list = new LinkedList<Address>(addresses);
- list.addAll(moreAddresses);
- return createConsistentHash(clazz, list);
- }
-}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/DefaultConsistentHash.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/DefaultConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/DefaultConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,213 +0,0 @@
-package org.infinispan.distribution;
-
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-import org.infinispan.remoting.transport.Address;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import static java.lang.Math.min;
-import static org.infinispan.util.hash.MurmurHash2.hash;
-
- at Marshallable(externalizer = DefaultConsistentHash.Externalizer.class, id = Ids.DEFAULT_CONSISTENT_HASH)
-public class DefaultConsistentHash extends AbstractConsistentHash {
-
- // make sure all threads see the current list
- ArrayList<Address> addresses;
- SortedMap<Integer, Address> positions;
- // TODO: Maybe address and addressToHashIds can be combined in a LinkedHashMap?
- Map<Address, Integer> addressToHashIds;
-
- final static int HASH_SPACE = 10240; // no more than 10k nodes?
-
- public void setCaches(List<Address> caches) {
-
- addresses = new ArrayList<Address>(caches);
-
- // this list won't grow.
- addresses.trimToSize();
-
- positions = new TreeMap<Integer, Address>();
- addressToHashIds = new HashMap<Address, Integer>();
-
- for (Address a : addresses) {
- int positionIndex = Math.abs(hash(a)) % HASH_SPACE;
- // this is deterministic since the address list is ordered and the order is consistent across the grid
- while (positions.containsKey(positionIndex)) positionIndex = positionIndex + 1 % HASH_SPACE;
- positions.put(positionIndex, a);
- // If address appears several times, take the lowest value to guarantee that
- // at least the initial value and subsequent +1 values would end up in the same node
- // TODO: Remove this check since https://jira.jboss.org/jira/browse/ISPN-428 contains a proper fix for this
- if (!addressToHashIds.containsKey(a))
- addressToHashIds.put(a, positionIndex);
- }
-
- addresses.clear();
- // reorder addresses as per the positions.
- for (Address a : positions.values()) addresses.add(a);
- }
-
- public List<Address> getCaches() {
- return addresses;
- }
-
- public List<Address> locate(Object key, int replCount) {
- int keyHashCode = hash(key);
- if (keyHashCode == Integer.MIN_VALUE) keyHashCode += 1;
- int hash = Math.abs(keyHashCode);
- int numCopiesToFind = min(replCount, addresses.size());
-
- List<Address> owners = new ArrayList<Address>(numCopiesToFind);
-
- SortedMap<Integer, Address> candidates = positions.tailMap(hash % HASH_SPACE);
-
- int numOwnersFound = 0;
-
- for (Address a : candidates.values()) {
- if (numOwnersFound < numCopiesToFind) {
- owners.add(a);
- numOwnersFound++;
- } else {
- break;
- }
- }
-
- if (numOwnersFound < numCopiesToFind) {
- for (Address a : positions.values()) {
- if (numOwnersFound < numCopiesToFind) {
- owners.add(a);
- numOwnersFound++;
- } else {
- break;
- }
- }
- }
-
- return owners;
- }
-
- @Override
- public boolean isKeyLocalToAddress(Address target, Object key, int replCount) {
- // more efficient impl
- int keyHashCode = hash(key);
- if (keyHashCode == Integer.MIN_VALUE) keyHashCode += 1;
- int hash = Math.abs(keyHashCode);
- int numCopiesToFind = min(replCount, addresses.size());
-
- SortedMap<Integer, Address> candidates = positions.tailMap(hash % HASH_SPACE);
- int nodesTested = 0;
- for (Address a : candidates.values()) {
- if (nodesTested < numCopiesToFind) {
- if (a.equals(target)) return true;
- nodesTested++;
- } else {
- break;
- }
- }
-
- // start from the beginning
- if (nodesTested < numCopiesToFind) {
- for (Address a : positions.values()) {
- if (nodesTested < numCopiesToFind) {
- if (a.equals(target)) return true;
- nodesTested++;
- } else {
- break;
- }
- }
- }
-
- return false;
- }
-
-
- public int getDistance(Address a1, Address a2) {
- if (a1 == null || a2 == null) throw new NullPointerException("Cannot deal with nulls as parameters!");
-
- int p1 = addresses.indexOf(a1);
- if (p1 < 0)
- return -1;
-
- int p2 = addresses.indexOf(a2);
- if (p2 < 0)
- return -1;
-
- if (p1 <= p2)
- return p2 - p1;
- else
- return addresses.size() - (p1 - p2);
- }
-
- public boolean isAdjacent(Address a1, Address a2) {
- int distance = getDistance(a1, a2);
- return distance == 1 || distance == addresses.size() - 1;
- }
-
- @Override
- public int getHashId(Address a) {
- Integer hashId = addressToHashIds.get(a);
- if (hashId == null)
- return -1;
- else
- return hashId.intValue();
- }
-
- @Override
- public int getHashSpace() {
- return HASH_SPACE;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- DefaultConsistentHash that = (DefaultConsistentHash) o;
-
- if (addresses != null ? !addresses.equals(that.addresses) : that.addresses != null) return false;
- if (positions != null ? !positions.equals(that.positions) : that.positions != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = addresses != null ? addresses.hashCode() : 0;
- result = 31 * result + (positions != null ? positions.hashCode() : 0);
- return result;
- }
-
- public static class Externalizer implements org.infinispan.marshall.Externalizer {
- public void writeObject(ObjectOutput output, Object subject) throws IOException {
- DefaultConsistentHash dch = (DefaultConsistentHash) subject;
- output.writeObject(dch.addresses);
- output.writeObject(dch.positions);
- output.writeObject(dch.addressToHashIds);
- }
-
- @SuppressWarnings("unchecked")
- public Object readObject(ObjectInput unmarshaller) throws IOException, ClassNotFoundException {
- DefaultConsistentHash dch = new DefaultConsistentHash();
- dch.addresses = (ArrayList<Address>) unmarshaller.readObject();
- dch.positions = (SortedMap<Integer, Address>) unmarshaller.readObject();
- dch.addressToHashIds = (Map<Address, Integer>) unmarshaller.readObject();
- return dch;
- }
- }
-
- @Override
- public String toString() {
- return "DefaultConsistentHash{" +
- "addresses =" + positions +
- ", hash space =" + HASH_SPACE +
- '}';
- }
-}
\ No newline at end of file
Modified: trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -3,6 +3,7 @@
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.container.entries.InternalCacheValue;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.factories.scopes.Scope;
import org.infinispan.factories.scopes.Scopes;
import org.infinispan.loaders.CacheStore;
@@ -72,8 +73,8 @@
/**
* Retrieves the consistent hash instance currently in use, which may be an instance of the configured ConsistentHash
- * instance (which defaults to {@link org.infinispan.distribution.DefaultConsistentHash}, or an instance of
- * {@link org.infinispan.distribution.UnionConsistentHash} if a rehash is in progress.
+ * instance (which defaults to {@link org.infinispan.distribution.ch.DefaultConsistentHash}, or an instance of
+ * {@link org.infinispan.distribution.ch.UnionConsistentHash} if a rehash is in progress.
*
* @return a ConsistentHash instance
*/
@@ -110,7 +111,7 @@
List<Address> requestPermissionToJoin(Address joiner);
/**
- * This will cause all nodes to add the joiner to their consistent hash instance (usually by creating a {@link org.infinispan.distribution.UnionConsistentHash}
+ * This will cause all nodes to add the joiner to their consistent hash instance (usually by creating a {@link org.infinispan.distribution.ch.UnionConsistentHash}
*
* @param joiner address of joiner
* @param starting if true, the joiner is reporting that it is starting the join process. If false, the joiner is
Modified: trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -14,8 +14,11 @@
import org.infinispan.context.InvocationContext;
import org.infinispan.context.InvocationContextContainer;
-import static org.infinispan.distribution.ConsistentHashHelper.createConsistentHash;
+import static org.infinispan.distribution.ch.ConsistentHashHelper.createConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHashHelper;
+import org.infinispan.distribution.ch.UnionConsistentHash;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.Start;
import org.infinispan.factories.annotations.Stop;
@@ -47,15 +50,7 @@
import org.rhq.helpers.pluginAnnotations.agent.Operation;
import org.rhq.helpers.pluginAnnotations.agent.Parameter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.HashMap;
+import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -69,7 +64,9 @@
/**
* The default distribution manager implementation
*
- * @author Manik Surtani, Vladimir Blagojevic
+ * @author Manik Surtani
+ * @author Vladimir Blagojevic
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
@MBean(objectName = "DistributionManager", description = "Component that handles distribution of content across a cluster")
@@ -221,25 +218,31 @@
Address leaver = MembershipArithmetic.getMemberLeft(oldMembers, newMembers);
log.info("This is a LEAVE event! Node {0} has just left", leaver);
- boolean willReceiveLeaverState = willReceiveLeaverState(leaver);
- boolean willSendLeaverState = willSendLeaverState(leaver);
- List<Address> stateProviders = holdersOfLeaversState(newMembers, leaver);
-
try {
- if (!(consistentHash instanceof UnionConsistentHash)) oldConsistentHash = consistentHash;
- else oldConsistentHash = ((UnionConsistentHash) consistentHash).newCH;
+ if (!(consistentHash instanceof UnionConsistentHash)) {
+ oldConsistentHash = consistentHash;
+ } else {
+ oldConsistentHash = ((UnionConsistentHash) consistentHash).getNewCH();
+ }
consistentHash = ConsistentHashHelper.removeAddress(consistentHash, leaver, configuration);
} catch (Exception e) {
log.fatal("Unable to process leaver!!", e);
throw new CacheException(e);
}
+ boolean willReceiveLeaverState = willReceiveLeaverState(leaver);
+ List<Address> stateProviders = holdersOfLeaversState(leaver);
+ boolean willSendLeaverState = stateProviders.contains(self);
+
if (willReceiveLeaverState || willSendLeaverState) {
log.info("I {0} am participating in rehash", rpcManager.getTransport().getAddress());
transactionLogger.enable();
if (leaveTaskFuture != null
&& (!leaveTaskFuture.isCancelled() || !leaveTaskFuture.isDone())) {
+ if (log.isTraceEnabled()) {
+ log.trace("Canceling running leave task!");
+ }
leaveTaskFuture.cancel(true);
}
@@ -253,27 +256,14 @@
}
}
- boolean willSendLeaverState(Address leaver) {
- ConsistentHash ch = consistentHash instanceof UnionConsistentHash ? oldConsistentHash : consistentHash;
- return ch.isAdjacent(leaver, self);
+ List<Address> holdersOfLeaversState(Address leaver) {
+ List<Address> addresses = oldConsistentHash.getStateProvidersOnLeave(leaver, getReplCount());
+ if (log.isTraceEnabled()) log.trace("Holders of leaver's state are: " + addresses);
+ return addresses;
}
- List<Address> holdersOfLeaversState(List<Address> members, Address leaver) {
- ConsistentHash ch = consistentHash instanceof UnionConsistentHash ? oldConsistentHash : consistentHash;
- Set<Address> holders = new HashSet<Address>();
- for (Address address : members) {
-
- if (ch.isAdjacent(leaver, address)) {
- holders.add(address);
- }
- }
- return new ArrayList<Address>(holders);
- }
-
boolean willReceiveLeaverState(Address leaver) {
- ConsistentHash ch = consistentHash instanceof UnionConsistentHash ? oldConsistentHash : consistentHash;
- int dist = ch.getDistance(leaver, self);
- return dist >= 0 && dist <= getReplCount();
+ return oldConsistentHash.isStateReceiverOnLeave(leaver, self, getReplCount());
}
public boolean isLocal(Object key) {
@@ -332,6 +322,10 @@
this.consistentHash = consistentHash;
}
+ public void setOldConsistentHash(ConsistentHash oldConsistentHash) {
+ this.oldConsistentHash = oldConsistentHash;
+ }
+
@ManagedOperation(description = "Determines whether a given key is affected by an ongoing rehash, if any.")
@Operation(displayName = "Could key be affected by rehash?")
public boolean isAffectedByRehash(@Parameter(name = "key", description = "Key to check") Object key) {
@@ -499,4 +493,12 @@
public String toString() {
return "DistributionManagerImpl[rehashInProgress=" + rehashInProgress + ", consistentHash=" + consistentHash + "]";
}
+
+ public void setSelf(Address self) {
+ this.self = self;
+ }
+
+ public void setConfiguration(Configuration configuration) {
+ this.configuration = configuration;
+ }
}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ExperimentalDefaultConsistentHash.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ExperimentalDefaultConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ExperimentalDefaultConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,371 +0,0 @@
-package org.infinispan.distribution;
-
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.Util;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import static java.lang.Math.min;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * <a href = "http://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html">Consistent hashing
- * algorithm</a>. Each target is entered into the pool <i>weight[i]</i>*<i>weightFactor</i> times. Where
- * <i>weight[i]</i> and <i>weightFactor</i> are integers greater than zero.
- * <p/>
- * Based on akluge's impl on <a href-="http://www.vizitsolutions.com/ConsistentHashingCaching.html">http://www.vizitsolutions.com/ConsistentHashingCaching.html</a>
- *
- * @author akluge
- * @author Manik Surtani
- */
- at Marshallable(externalizer = ExperimentalDefaultConsistentHash.Externalizer.class, id = Ids.DEFAULT_CONSISTENT_HASH)
-public class ExperimentalDefaultConsistentHash extends AbstractConsistentHash {
- /**
- * A Weight and weight factor of 1 gives one node per address. In future we may decide to make these configurable,
- * to allow for virtual nodes and a better spread of state across nodes, but we need to ensure we deal with backups
- * not falling on virtual nodes on the same cache instances first.
- */
- private static final int DEFAULT_WEIGHT = 1;
- private static final int DEFAULT_WEIGHTFACTOR = 1;
-
- private List<Address> nodes;
- private List<Entry> pool;
- private int poolSize;
-
- public static class Externalizer implements org.infinispan.marshall.Externalizer {
-
- public void writeObject(ObjectOutput output, Object object) throws IOException {
- ExperimentalDefaultConsistentHash gch = (ExperimentalDefaultConsistentHash) object;
- output.writeObject(gch.nodes);
- }
-
- @SuppressWarnings("unchecked")
- public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
- List<Address> addresses = (List<Address>) input.readObject();
- DefaultConsistentHash gch = new DefaultConsistentHash();
- gch.setCaches(addresses);
- return gch;
- }
- }
-
- public List<Address> getCaches() {
- return nodes;
- }
-
- public void setCaches(List<Address> caches) {
- nodes = caches;
- int numNodes = nodes.size();
-
- int poolSize = 0;
-
- for (int i = 0; i < numNodes; i++) {
- poolSize += DEFAULT_WEIGHT * DEFAULT_WEIGHTFACTOR;
- }
- this.poolSize = poolSize;
- pool = new ArrayList<Entry>(poolSize);
-
- int numEntries = 0;
- for (int i = 0; i < numNodes; i++) {
- numEntries = add(nodes.get(i), DEFAULT_WEIGHT * DEFAULT_WEIGHTFACTOR, numEntries);
- }
- Collections.sort(pool);
- nodes = getSortedCachesList();
- }
-
- private List<Address> getSortedCachesList() {
- ArrayList<Address> caches = new ArrayList<Address>();
- for (Entry e : pool) {
- if (!caches.contains(e.address)) caches.add(e.address);
- }
- caches.trimToSize();
- return caches;
- }
-
- /**
- * Adds an Address to the pool of available addresses.
- *
- * @param node Address to be added to the hash pool.
- * @param count An int giving the number of times the node is added to the pool. The count is greater than zero,
- * and is likely greater than 10 if weights are used. The count for the i-th node is usually the
- * <i>weights</i>[i]*<i>weightfactor</i>, if weights are used.
- * @param position The position in the pool to begin adding node entries.
- * @return position;
- */
- private int add(Address node, int count, int position) {
- int hash;
- String nodeName = node.toString();
- for (int i = 0; i < count; i++) {
- hash = hash((Integer.toString(i) + nodeName).getBytes());
- pool.add(position++, new Entry(node, nodeName, i, hash));
- }
- return position;
- }
-
- /**
- * The distance between the first entries in the address array for two caches, a1 and a2. Of questionable use when
- * virtual nodes are employed.
- *
- * @param a1 The address of the first cache.
- * @param a2 The address of the second cache.
- * @return Am int containing the difference between these two indices.
- */
- public int getDistance(Address a1, Address a2) {
- if (a1 == null || a2 == null) throw new NullPointerException("Cannot find the distance between null servers.");
-
- int p1 = nodes.indexOf(a1);
- if (p1 < 0)
- throw new IllegalArgumentException("Address " + a1 + " not in the addresses list of this consistent hash impl!");
-
- int p2 = nodes.indexOf(a2);
- if (p2 < 0)
- throw new IllegalArgumentException("Address " + a2 + " not in the addresses list of this consistent hash impl!");
-
- if (p1 <= p2)
- return p2 - p1;
- else
- return pool.size() - (p1 - p2);
- }
-
- /**
- * Two hashes are adjacent if they are next to each other in the consistent hash.
- *
- * @param a1 The address of the first cache.
- * @param a2 The address of the second cache.
- * @return A boolean, true if they are adjacent, false if not.
- */
- public boolean isAdjacent(Address a1, Address a2) {
- int distance = getDistance(a1, a2);
- return distance == 1 || distance == pool.size() - 1;
- }
-
- public List<Address> locate(Object key, int replCount) {
- if (key == null) throw new NullPointerException("Attempt to get with null key");
-
- int clusterSize = pool.size();
- int numCopiesToFind = min(replCount, clusterSize);
- int hashValue = hash(key);
- return locate(hashValue, numCopiesToFind, replCount);
- }
-
- /**
- * Returns a List of <i>numCopiesToFind</i> unique Addresses.
- *
- * @param hashValue An int, usually a hash, to be mapped to a bin via the CH.
- * @param numCopiesToFind number of copies to find
- * @param replCount replication count
- * @return Returns a List of <i>numCopiesToFind</i> unique Addresses.
- */
- private List<Address> locate(int hashValue, int numCopiesToFind, int replCount) {
- // Stop looking if we have checked the entire pool.
- int checked = 0;
- // Start looking at the first (primary) node for entries for this value.
- int inode = findNearestNodeInPool(hashValue);
- List<Address> nodes = new ArrayList<Address>(numCopiesToFind);
-
- while (nodes.size() < replCount && checked < poolSize) {
- Entry poolEntry;
- if ((poolEntry = pool.get(inode)) != null && nodes.indexOf(poolEntry.address) < 0) {
- nodes.add(poolEntry.address);
- }
- inode = (++inode) % poolSize;
- checked++;
- }
- return nodes;
- }
-
- /**
- * Find a target for a hash key within the pool of node Entries. We search within a slice of the array bounded by
- * lowerBound and upperBound. Further we assume that lowerBound and upperBound are small enough that their sum will
- * not overflow an int.
- * <p/>
- *
- * @param hash The desired hash to locate.
- * @return An int giving the index of the desired entry in the list of targets. If the target is not found, then
- * -(lowerBound +1) will be returned, where lowerBound is the lower bound of the search after possibly
- * several iterations.
- */
- private int binarySearch(int hash) {
- int lowerBound = 0;
- int upperBound = pool.size() - 1;
- while (lowerBound <= upperBound) {
- // Fast div by 2. We assume that the number of targets is small enough
- // that the sum will not overflow an int.
- int mid = (lowerBound + upperBound) >>> 1;
- int currentHash = pool.get(mid).hash;
-
- if (currentHash < hash) {
- lowerBound = mid + 1;
- } else if (currentHash > hash) {
- upperBound = mid - 1;
- } else {
- return mid;
- }
- }
- // The +1 ensures that the return value is negative, even when the hash
- // is off the left edge of the array.
- return -(lowerBound + 1);
- }
-
- /**
- * Finds the lowest index into the pool ArrayList such that the hash of the i-th entry >= hash.
- *
- * @param hash The hash being mapped to a bin via the consistent hash.
- * @return An int, the lowest index into the target array such that the hash of the i-th entry >= hash.
- */
- private int findNearestNodeInPool(int hash) {
- // Find the index of the node - or at least a near one.
- // We only search up to targets.length-1. If the element
- // is greater than the last entry in the list, then map
- // it to the first one.
- int nodeIndex = binarySearch(hash);
-
- // If the returned value is less than zero, then no exact match was found.
- if (nodeIndex < 0) {
- // The value returned is -(lowerBound +1), we want the lower bound back.
- nodeIndex = -(nodeIndex + 1);
-
- // If hash is greater than the last entry, wrap around to the first.
- if (nodeIndex >= pool.size()) {
- nodeIndex = 0;
- }
- }
-
- return nodeIndex;
- }
-
- /**
- * Use the objects built in hash to obtain an initial value, then use a second four byte hash to obtain a more
- * uniform distribution of hash values. This uses a <a href = "http://burtleburtle.net/bob/hash/integer.html">4-byte
- * (integer) hash</a>, which produces well distributed values even when the original hash produces thghtly clustered
- * values.
- * <p/>
- * It is important that the object implement its own hashcode, and not use the Object hashcode.
- *
- * @param object object to hash
- * @return an appropriately spread hash code
- */
- private int hash(Object object) {
- int hash = object.hashCode();
-
- hash = (hash + 0x7ED55D16) + (hash << 12);
- hash = (hash ^ 0xc761c23c) ^ (hash >> 19);
- hash = (hash + 0x165667b1) + (hash << 5);
- hash = (hash + 0xd3a2646c) ^ (hash << 9);
- hash = (hash + 0xfd7046c5) + (hash << 3);
- hash = (hash ^ 0xb55a4f09) ^ (hash >> 16);
-
- return hash;
- }
-
- @Override
- public int getHashId(Address a) {
- throw new RuntimeException("Not yet implemented");
- }
-
- @Override
- public int getHashSpace() {
- return Integer.MAX_VALUE; // Entire positive integer range
- }
-
- /**
- * @return A String representing the object pool.
- */
- @Override
- public String toString() {
- return " pool: " + pool;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == null
- || !(other instanceof ExperimentalDefaultConsistentHash)) {
- return false;
- }
-
- ExperimentalDefaultConsistentHash otherHash = (ExperimentalDefaultConsistentHash) other;
- return Util.safeEquals(pool, otherHash.pool);
- }
-
- @Override
- public int hashCode() {
- int hashCode = 1;
- for (Entry e : pool) hashCode = 31 * hashCode + e.hash;
- return hashCode;
- }
-
- /**
- * An entry into a consistent hash. It wraps the original object, the object's hash as used to generate the
- * consistent hash, the value extracted from the object used to generate the hash, and the modifier used to
- * differentiate the hash.
- */
- public static class Entry implements Comparable<Entry> {
- public final int differentiator;
- public final int hash;
- public final Address address;
- public final String string;
-
- public Entry(Address address, String string, int differentiator, int hash) {
- this.differentiator = differentiator;
- this.hash = hash;
- this.address = address;
- this.string = string;
- }
-
- /**
- * Compare this Entry with another Entry. First the hash values are compared, then the differentiator is compared.
- * if the hash values are equal.
- *
- * @param other An Entry object to be compared with this object. Returns <ul> <li>-1 if this Entry is less than
- * the other Entry.</li> <li>0 if they are equal.</li> <li>+1 if this Entry is greater than the
- * other Entry.</li> </ul>
- * @return
- */
- public int compareTo(Entry other) {
- if (this.hash < other.hash) {
- return -1;
- }
-
- if (this.hash > other.hash) {
- return 1;
- }
-
- if (this.differentiator < other.differentiator) {
- return -1;
- }
-
- if (this.differentiator > other.differentiator) {
- return +1;
- }
-
- return 0;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof Entry) {
- Entry otherEntry = (Entry) other;
-
- return hash == otherEntry.hash
- && differentiator == otherEntry.differentiator
- && address.equals(otherEntry.address);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return hash;
- }
-
-
- @Override
- public String toString() {
- return string + ":" + Integer.toHexString(hash);
- }
- }
-}
\ No newline at end of file
Modified: trunk/core/src/main/java/org/infinispan/distribution/InvertedLeaveTask.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/InvertedLeaveTask.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/InvertedLeaveTask.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -23,6 +23,8 @@
import org.infinispan.config.Configuration;
import org.infinispan.container.DataContainer;
import org.infinispan.container.entries.InternalCacheValue;
+import org.infinispan.distribution.ch.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHashHelper;
import org.infinispan.remoting.responses.Response;
import org.infinispan.remoting.responses.SuccessfulResponse;
import org.infinispan.remoting.rpc.RpcManager;
@@ -84,12 +86,10 @@
if (isReceiver) {
Address myAddress = rpcManager.getTransport().getAddress();
RehashControlCommand cmd = cf.buildRehashControlCommand(PULL_STATE_LEAVE, myAddress,
- null, oldCH, newCH,leaversHandled);
+ null, oldCH, newCH, leaversHandled);
- List<Address> addressesWhoMaySendStuff = getStateProviderTargets();
- log.debug("I {0} am pulling state from {1}", self, addressesWhoMaySendStuff);
- List<Response> resps = rpcManager.invokeRemotely(addressesWhoMaySendStuff, cmd,
- SYNCHRONOUS, configuration.getRehashRpcTimeout(), true);
+ log.debug("I {0} am pulling state from {1}", self, stateProviders);
+ List<Response> resps = rpcManager.invokeRemotely(stateProviders, cmd, SYNCHRONOUS, configuration.getRehashRpcTimeout(), true);
log.debug("I {0} received response {1} ", self, resps);
for (Response r : resps) {
@@ -118,17 +118,13 @@
}
}
- private List<Address> getStateProviderTargets() {
- return stateProviders;
- }
-
private void processAndDrainTxLog(ConsistentHash oldCH, ConsistentHash newCH, int replCount) {
- if (trace)
- log.trace("Processing transaction log iteratively");
List<WriteCommand> c;
int i = 0;
TransactionLogger transactionLogger = dmi.getTransactionLogger();
+ if (trace)
+ log.trace("Processing transaction log iteratively: " + transactionLogger);
while (transactionLogger.shouldDrainWithoutLock()) {
if (trace)
log.trace("Processing transaction log, iteration {0}", i++);
@@ -182,8 +178,7 @@
transactionLogger.unlockAndDisable();
}
- private void apply(ConsistentHash oldCH, ConsistentHash newCH, int replCount,
- List<WriteCommand> wc) {
+ private void apply(ConsistentHash oldCH, ConsistentHash newCH, int replCount, List<WriteCommand> wc) {
// need to create another "state map"
TransactionLogMap state = new TransactionLogMap(leavers, oldCH, newCH, replCount);
for (WriteCommand c : wc)
Modified: trunk/core/src/main/java/org/infinispan/distribution/JoinTask.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/JoinTask.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/JoinTask.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -7,7 +7,9 @@
import org.infinispan.config.Configuration;
import org.infinispan.container.DataContainer;
import org.infinispan.container.entries.InternalCacheValue;
-import static org.infinispan.distribution.ConsistentHashHelper.createConsistentHash;
+import static org.infinispan.distribution.ch.ConsistentHashHelper.createConsistentHash;
+
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.remoting.responses.Response;
import org.infinispan.remoting.responses.SuccessfulResponse;
import static org.infinispan.remoting.rpc.ResponseMode.SYNCHRONOUS;
@@ -18,7 +20,6 @@
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -210,25 +211,7 @@
* @return
*/
List<Address> getAddressesWhoMaySendStuff(ConsistentHash ch, int replCount) {
- List<Address> l = new LinkedList<Address>();
- List<Address> caches = ch.getCaches();
- int selfIdx = caches.indexOf(self);
- if (selfIdx >= replCount - 1) {
- l.addAll(caches.subList(selfIdx - replCount + 1, selfIdx));
- } else {
- l.addAll(caches.subList(0, selfIdx));
- int alreadyCollected = l.size();
- l.addAll(caches.subList(caches.size() - replCount + 1 + alreadyCollected, caches.size()));
- }
-
- Address plusOne;
- if (selfIdx == caches.size() - 1)
- plusOne = caches.get(0);
- else
- plusOne = caches.get(selfIdx + 1);
-
- if (!l.contains(plusOne)) l.add(plusOne);
- return l;
+ return ch.getStateProvidersOnJoin(self, replCount);
}
public Address getMyAddress() {
Modified: trunk/core/src/main/java/org/infinispan/distribution/RehashTask.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/RehashTask.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/RehashTask.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -4,6 +4,7 @@
import org.infinispan.commands.write.InvalidateCommand;
import org.infinispan.config.Configuration;
import org.infinispan.container.DataContainer;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.remoting.rpc.RpcManager;
import org.infinispan.remoting.transport.Address;
import org.infinispan.util.concurrent.NotifyingFutureImpl;
Modified: trunk/core/src/main/java/org/infinispan/distribution/TransactionLoggerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/TransactionLoggerImpl.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/TransactionLoggerImpl.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -166,4 +166,12 @@
uncommittedPrepares.clear();
return commands;
}
+
+ @Override
+ public String toString() {
+ return "TransactionLoggerImpl{" +
+ "commandQueue=" + commandQueue +
+ ", uncommittedPrepares=" + uncommittedPrepares +
+ '}';
+ }
}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/UnionConsistentHash.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/UnionConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/UnionConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,92 +0,0 @@
-package org.infinispan.distribution;
-
-import org.infinispan.CacheException;
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.Immutables;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A delegating wrapper that locates keys by getting a union of locations reported by two other ConsistentHash
- * implementations it delegates to.
- *
- * @author Manik Surtani
- * @since 4.0
- */
- at Marshallable(externalizer = UnionConsistentHash.Externalizer.class, id = Ids.UNION_CONSISTENT_HASH)
-public class UnionConsistentHash extends AbstractConsistentHash {
-
- ConsistentHash oldCH, newCH;
-
- public UnionConsistentHash(ConsistentHash oldCH, ConsistentHash newCH) {
- if ((oldCH instanceof UnionConsistentHash) || (newCH instanceof UnionConsistentHash))
- throw new CacheException("Expecting both newCH and oldCH to not be Unions!! oldCH=[" + oldCH.getClass() + "] and newCH=[" + newCH.getClass() + "]");
- this.oldCH = oldCH;
- this.newCH = newCH;
- }
-
- public void setCaches(List<Address> caches) {
- // no op
- }
-
- public List<Address> getCaches() {
- return Collections.emptyList();
- }
-
- public List<Address> locate(Object key, int replCount) {
- Set<Address> addresses = new LinkedHashSet<Address>();
- addresses.addAll(oldCH.locate(key, replCount));
- addresses.addAll(newCH.locate(key, replCount));
- return Immutables.immutableListConvert(addresses);
- }
-
- public int getDistance(Address a1, Address a2) {
- throw new UnsupportedOperationException("Unsupported!");
- }
-
- public boolean isAdjacent(Address a1, Address a2) {
- throw new UnsupportedOperationException("Unsupported!");
- }
-
- @Override
- public int getHashId(Address a) {
- throw new UnsupportedOperationException("Unsupported!");
- }
-
- @Override
- public int getHashSpace() {
- int oldHashSpace = oldCH.getHashSpace();
- int newHashSpace = newCH.getHashSpace();
- // In a union, the hash space is the biggest of the hash spaces.
- return oldHashSpace > newHashSpace ? oldHashSpace : newHashSpace;
- }
-
- public ConsistentHash getNewConsistentHash() {
- return newCH;
- }
-
- public ConsistentHash getOldConsistentHash() {
- return oldCH;
- }
-
- public static class Externalizer implements org.infinispan.marshall.Externalizer {
-
- public void writeObject(ObjectOutput output, Object object) throws IOException {
- UnionConsistentHash uch = (UnionConsistentHash) object;
- output.writeObject(uch.oldCH);
- output.writeObject(uch.newCH);
- }
-
- public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
- return new UnionConsistentHash((ConsistentHash) input.readObject(), (ConsistentHash) input.readObject());
- }
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch)
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,45 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.remoting.transport.Address;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * An abstract consistent hash implementation that handles common implementations of certain methods. In particular,
- * default implementations of {@link #locateAll(java.util.Collection, int)} and {@link #isKeyLocalToAddress(org.infinispan.remoting.transport.Address, Object, int)}.
- * <p />
- * The versions provided here are relatively inefficient in that they call {@link #locate(Object, int)} first (and
- * sometimes in a loop). Depending on the algorithm used, there may be more efficient ways to achieve the same results
- * and in such cases the methods provided here should be overridden.
- * <p />
- * @author Manik Surtani
- * @author Mircea.Markus at jboss.com
- * @since 4.0
- */
-public abstract class AbstractConsistentHash implements ConsistentHash {
-
- protected volatile List<Address> caches;
- protected TopologyInfo topologyInfo;
-
- public void setCaches(List<Address> caches) {
- this.caches = caches;
- }
-
- public Map<Object, List<Address>> locateAll(Collection<Object> keys, int replCount) {
- Map<Object, List<Address>> locations = new HashMap<Object, List<Address>>();
- for (Object k : keys) locations.put(k, locate(k, replCount));
- return locations;
- }
-
- public boolean isKeyLocalToAddress(Address a, Object key, int replCount) {
- // simple, brute-force impl
- return locate(key, replCount).contains(a);
- }
-
- public void setTopologyInfo(TopologyInfo topologyInfo) {
- this.topologyInfo = topologyInfo;
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,45 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.remoting.transport.Address;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An abstract consistent hash implementation that handles common implementations of certain methods. In particular,
+ * default implementations of {@link #locateAll(java.util.Collection, int)} and {@link #isKeyLocalToAddress(org.infinispan.remoting.transport.Address, Object, int)}.
+ * <p />
+ * The versions provided here are relatively inefficient in that they call {@link #locate(Object, int)} first (and
+ * sometimes in a loop). Depending on the algorithm used, there may be more efficient ways to achieve the same results
+ * and in such cases the methods provided here should be overridden.
+ * <p />
+ * @author Manik Surtani
+ * @author Mircea.Markus at jboss.com
+ * @since 4.0
+ */
+public abstract class AbstractConsistentHash implements ConsistentHash {
+
+ protected volatile List<Address> caches;
+ protected TopologyInfo topologyInfo;
+
+ public void setCaches(List<Address> caches) {
+ this.caches = caches;
+ }
+
+ public Map<Object, List<Address>> locateAll(Collection<Object> keys, int replCount) {
+ Map<Object, List<Address>> locations = new HashMap<Object, List<Address>>();
+ for (Object k : keys) locations.put(k, locate(k, replCount));
+ return locations;
+ }
+
+ public boolean isKeyLocalToAddress(Address a, Object key, int replCount) {
+ // simple, brute-force impl
+ return locate(key, replCount).contains(a);
+ }
+
+ public void setTopologyInfo(TopologyInfo topologyInfo) {
+ this.topologyInfo = topologyInfo;
+ }
+}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,99 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import static org.infinispan.util.hash.MurmurHash2.hash;
-
-/**
- * Abstract class for the wheel-based CH implementations.
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
-public abstract class AbstractWheelConsistentHash extends AbstractConsistentHash {
-
- private static Log log = LogFactory.getLog(AbstractWheelConsistentHash.class);
- protected ArrayList<Address> addresses;
- protected SortedMap<Integer, Address> positions;
- // TODO: Maybe address and addressToHashIds can be combined in a LinkedHashMap?
- protected Map<Address, Integer> addressToHashIds;
-
- final static int HASH_SPACE = 10240; // no more than 10k nodes?
-
- public void setCaches(List<Address> caches) {
- super.setCaches(caches);
-
- addresses = new ArrayList<Address>(caches);
-
- // this list won't grow.
- addresses.trimToSize();
-
- positions = new TreeMap<Integer, Address>();
- addressToHashIds = new HashMap<Address, Integer>();
-
- for (Address a : addresses) {
- int positionIndex = Math.abs(hash(a)) % HASH_SPACE;
- // this is deterministic since the address list is ordered and the order is consistent across the grid
- while (positions.containsKey(positionIndex)) positionIndex = positionIndex + 1 % HASH_SPACE;
- positions.put(positionIndex, a);
- // If address appears several times, take the lowest value to guarantee that
- // at least the initial value and subsequent +1 values would end up in the same node
- // TODO: Remove this check since https://jira.jboss.org/jira/browse/ISPN-428 contains a proper fix for this
- if (!addressToHashIds.containsKey(a))
- addressToHashIds.put(a, positionIndex);
- }
-
- addresses.clear();
- // reorder addresses as per the positions.
- for (Address a : positions.values()) addresses.add(a);
- if (log.isTraceEnabled()) {
- log.trace("Position are: " + positions);
- }
- }
-
- public boolean isStateReceiverOnLeave(Address leaver, Address node, int replCount) {
- for (Address address : addresses) {
- List<Address> backups = locate(address, replCount + 1);
- if (backups.contains(leaver) && (backups.indexOf(node) == backups.size() - 1)) {
- return true;
- }
- }
- return false;
- }
-
-
- public List<Address> getCaches() {
- return addresses;
- }
-
- @Override
- public int getHashSpace() {
- return HASH_SPACE;
- }
-
-
- @Override
- public int getHashId(Address a) {
- Integer hashId = addressToHashIds.get(a);
- if (hashId == null)
- return -1;
- else
- return hashId.intValue();
- }
-
- protected int getNormalizedHash(Object key) {
- // more efficient impl
- int keyHashCode = hash(key);
- if (keyHashCode == Integer.MIN_VALUE) keyHashCode += 1;
- return Math.abs(keyHashCode) % HASH_SPACE;
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/AbstractWheelConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,99 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import static org.infinispan.util.hash.MurmurHash2.hash;
+
+/**
+ * Abstract class for the wheel-based CH implementations.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+public abstract class AbstractWheelConsistentHash extends AbstractConsistentHash {
+
+ private static Log log = LogFactory.getLog(AbstractWheelConsistentHash.class);
+ protected ArrayList<Address> addresses;
+ protected SortedMap<Integer, Address> positions;
+ // TODO: Maybe address and addressToHashIds can be combined in a LinkedHashMap?
+ protected Map<Address, Integer> addressToHashIds;
+
+ final static int HASH_SPACE = 10240; // no more than 10k nodes?
+
+ public void setCaches(List<Address> caches) {
+ super.setCaches(caches);
+
+ addresses = new ArrayList<Address>(caches);
+
+ // this list won't grow.
+ addresses.trimToSize();
+
+ positions = new TreeMap<Integer, Address>();
+ addressToHashIds = new HashMap<Address, Integer>();
+
+ for (Address a : addresses) {
+ int positionIndex = Math.abs(hash(a)) % HASH_SPACE;
+ // this is deterministic since the address list is ordered and the order is consistent across the grid
+ while (positions.containsKey(positionIndex)) positionIndex = positionIndex + 1 % HASH_SPACE;
+ positions.put(positionIndex, a);
+ // If address appears several times, take the lowest value to guarantee that
+ // at least the initial value and subsequent +1 values would end up in the same node
+ // TODO: Remove this check since https://jira.jboss.org/jira/browse/ISPN-428 contains a proper fix for this
+ if (!addressToHashIds.containsKey(a))
+ addressToHashIds.put(a, positionIndex);
+ }
+
+ addresses.clear();
+ // reorder addresses as per the positions.
+ for (Address a : positions.values()) addresses.add(a);
+ if (log.isTraceEnabled()) {
+ log.trace("Position are: " + positions);
+ }
+ }
+
+ public boolean isStateReceiverOnLeave(Address leaver, Address node, int replCount) {
+ for (Address address : addresses) {
+ List<Address> backups = locate(address, replCount + 1);
+ if (backups.contains(leaver) && (backups.indexOf(node) == backups.size() - 1)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ public List<Address> getCaches() {
+ return addresses;
+ }
+
+ @Override
+ public int getHashSpace() {
+ return HASH_SPACE;
+ }
+
+
+ @Override
+ public int getHashId(Address a) {
+ Integer hashId = addressToHashIds.get(a);
+ if (hashId == null)
+ return -1;
+ else
+ return hashId.intValue();
+ }
+
+ protected int getNormalizedHash(Object key) {
+ // more efficient impl
+ int keyHashCode = hash(key);
+ if (keyHashCode == Integer.MIN_VALUE) keyHashCode += 1;
+ return Math.abs(keyHashCode) % HASH_SPACE;
+ }
+}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,114 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.remoting.transport.Address;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A consistent hash algorithm implementation. Implementations would typically be constructed via reflection so should
- * implement a public, no-arg constructor.
- *
- * @author Manik Surtani
- * @author Mircea.Markus at jboss.com
- * @since 4.0
- */
-public interface ConsistentHash {
-
- /**
- * Sets the collection of cache addresses in the cluster. The implementation should store these internally and use
- * these to locate keys.
- *
- * @param caches caches in cluster.
- */
- void setCaches(List<Address> caches);
-
- /**
- * Sets cluster topology information that can be used by CH to improve fault tolerance by smart choosing of backups.
- * More about it <a href="http://community.jboss.org/wiki/DesigningServerHinting">here<a/>
- */
- void setTopologyInfo(TopologyInfo topologyInfo);
-
- /**
- * Should return a collection of cache addresses in the cluster.
- *
- * @return collection of cache addresses
- */
- List<Address> getCaches();
-
- /**
- * Locates a key, given a replication count (number of copies).
- *
- * @param key key to locate
- * @param replCount replication count (number of copies)
- * @return a list of addresses where the key resides, where this list is a subset of the addresses set in {@link
- * #setCaches(java.util.List)}. Should never be null, and should contain replCount elements or the max
- * number of caches available, whichever is smaller.
- */
- List<Address> locate(Object key, int replCount);
-
- /**
- * The logical equivalent of calling {@link #locate(Object, int)} multiple times for each key in the collection of
- * keys. Implementations may be optimised for such a bulk lookup, or may just repeatedly call {@link #locate(Object,
- * int)}.
- *
- * @param keys keys to locate
- * @param replCount replication count (number of copies) for each key
- * @return Map of locations, keyed on key.
- */
- Map<Object, List<Address>> locateAll(Collection<Object> keys, int replCount);
-
- /**
- * Test to see whether a key is mapped to a given address.
- * @param a address to test
- * @param key key to test
- * @param replCount repl count
- * @return true if the key is mapped to the address; false otherwise
- */
- boolean isKeyLocalToAddress(Address a, Object key, int replCount);
-
- /**
- * Returns the value between 0 and the hash space limit, or hash id, for a particular address. If there's no such
- * value for an address, this method will return -1.
- *
- * @return An int between 0 and hash space if the address is present in the hash wheel, otherwise it returns -1.
- */
- int getHashId(Address a);
-
- /**
- * Returns the hash space constant for this consistent hash algorithm class. This integer is often used as modulus
- * for arithmetic operations within the algorithm, for example, limiting the range of possible hash values.
- *
- * @return A positive integer containing the hash space constant or 0 is not supported by implementation.
- */
- int getHashSpace();
-
- /**
- * Returns the nodes that need will replicate their state if the specified node crashes. The return collection
- * should contain all the nodes that backup-ed on leaver and one of the nodes which acted as a backup for the leaver .
- * <p>
- * Pre: leaver must be present in the caches known to this CH, as returned by {@link #getCaches()}
- * @param leaver the node that leaves the cluster
- * @param replCount
- */
- List<Address> getStateProvidersOnLeave(Address leaver, int replCount);
-
- /**
- * Is the specified node going to receive state if when another node leaves the cluster?
- * When a node leaves the cluster following nodes would need to receive state as result of the rehashing:
- * - a new backup node for the lever to satisfy numOwners condition
- * - the nodes that would replace the leaver as a backup for other nodes
- * @param leaver node that leaves
- * @param node is this state receiver?
- * @param replCount numOwners
- */
- boolean isStateReceiverOnLeave(Address leaver, Address node, int replCount);
-
- /**
- * Returns the nodes that would act as state providers when a new node joins:
- * - the nodes for which the joiner is a backup
- * - the nodes that held joiner's state
- */
- List<Address> getStateProvidersOnJoin(Address joiner, int replCount);
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,114 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.remoting.transport.Address;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A consistent hash algorithm implementation. Implementations would typically be constructed via reflection so should
+ * implement a public, no-arg constructor.
+ *
+ * @author Manik Surtani
+ * @author Mircea.Markus at jboss.com
+ * @since 4.0
+ */
+public interface ConsistentHash {
+
+ /**
+ * Sets the collection of cache addresses in the cluster. The implementation should store these internally and use
+ * these to locate keys.
+ *
+ * @param caches caches in cluster.
+ */
+ void setCaches(List<Address> caches);
+
+ /**
+ * Sets cluster topology information that can be used by CH to improve fault tolerance by smart choosing of backups.
+ * More about it <a href="http://community.jboss.org/wiki/DesigningServerHinting">here<a/>
+ */
+ void setTopologyInfo(TopologyInfo topologyInfo);
+
+ /**
+ * Should return a collection of cache addresses in the cluster.
+ *
+ * @return collection of cache addresses
+ */
+ List<Address> getCaches();
+
+ /**
+ * Locates a key, given a replication count (number of copies).
+ *
+ * @param key key to locate
+ * @param replCount replication count (number of copies)
+ * @return a list of addresses where the key resides, where this list is a subset of the addresses set in {@link
+ * #setCaches(java.util.List)}. Should never be null, and should contain replCount elements or the max
+ * number of caches available, whichever is smaller.
+ */
+ List<Address> locate(Object key, int replCount);
+
+ /**
+ * The logical equivalent of calling {@link #locate(Object, int)} multiple times for each key in the collection of
+ * keys. Implementations may be optimised for such a bulk lookup, or may just repeatedly call {@link #locate(Object,
+ * int)}.
+ *
+ * @param keys keys to locate
+ * @param replCount replication count (number of copies) for each key
+ * @return Map of locations, keyed on key.
+ */
+ Map<Object, List<Address>> locateAll(Collection<Object> keys, int replCount);
+
+ /**
+ * Test to see whether a key is mapped to a given address.
+ * @param a address to test
+ * @param key key to test
+ * @param replCount repl count
+ * @return true if the key is mapped to the address; false otherwise
+ */
+ boolean isKeyLocalToAddress(Address a, Object key, int replCount);
+
+ /**
+ * Returns the value between 0 and the hash space limit, or hash id, for a particular address. If there's no such
+ * value for an address, this method will return -1.
+ *
+ * @return An int between 0 and hash space if the address is present in the hash wheel, otherwise it returns -1.
+ */
+ int getHashId(Address a);
+
+ /**
+ * Returns the hash space constant for this consistent hash algorithm class. This integer is often used as modulus
+ * for arithmetic operations within the algorithm, for example, limiting the range of possible hash values.
+ *
+ * @return A positive integer containing the hash space constant or 0 is not supported by implementation.
+ */
+ int getHashSpace();
+
+ /**
+ * Returns the nodes that need will replicate their state if the specified node crashes. The return collection
+ * should contain all the nodes that backup-ed on leaver and one of the nodes which acted as a backup for the leaver .
+ * <p>
+ * Pre: leaver must be present in the caches known to this CH, as returned by {@link #getCaches()}
+ * @param leaver the node that leaves the cluster
+ * @param replCount
+ */
+ List<Address> getStateProvidersOnLeave(Address leaver, int replCount);
+
+ /**
+ * Is the specified node going to receive state if when another node leaves the cluster?
+ * When a node leaves the cluster following nodes would need to receive state as result of the rehashing:
+ * - a new backup node for the lever to satisfy numOwners condition
+ * - the nodes that would replace the leaver as a backup for other nodes
+ * @param leaver node that leaves
+ * @param node is this state receiver?
+ * @param replCount numOwners
+ */
+ boolean isStateReceiverOnLeave(Address leaver, Address node, int replCount);
+
+ /**
+ * Returns the nodes that would act as state providers when a new node joins:
+ * - the nodes for which the joiner is a backup
+ * - the nodes that held joiner's state
+ */
+ List<Address> getStateProvidersOnJoin(Address joiner, int replCount);
+}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,144 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.Util;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * A helper class that handles the construction of consistent hash instances based on configuration.
- *
- * @author Manik Surtani
- * @since 4.0
- */
-public class ConsistentHashHelper {
-
- /**
- * Returns a new consistent hash of the same type with the given address removed.
- *
- * @param ch consistent hash to start with
- * @param toRemove address to remove
- * @param c configuration
- * @return a new consistent hash instance of the same type
- */
- public static ConsistentHash removeAddress(ConsistentHash ch, Address toRemove, Configuration c) {
- if (ch instanceof UnionConsistentHash)
- return removeAddressFromUnionConsistentHash((UnionConsistentHash) ch, toRemove, c);
- else {
- ConsistentHash newCH = (ConsistentHash) Util.getInstance(c.getConsistentHashClass());
- List<Address> caches = new ArrayList<Address>(ch.getCaches());
- caches.remove(toRemove);
- newCH.setCaches(caches);
- return newCH;
- }
- }
-
- /**
- * Creates a new UnionConsistentHash instance based on the old instance, removing the provided address from both
- * target consistent hash instances in the union.
- *
- * @param uch union consistent hash instance
- * @param toRemove address to remove
- * @param c configuration
- * @return a new UnionConsistentHash instance
- */
- public static UnionConsistentHash removeAddressFromUnionConsistentHash(UnionConsistentHash uch, Address toRemove, Configuration c) {
- ConsistentHash newFirstCH = removeAddress(uch.getOldConsistentHash(), toRemove, c);
- ConsistentHash newSecondCH = removeAddress(uch.getNewConsistentHash(), toRemove, c);
- return new UnionConsistentHash(newFirstCH, newSecondCH);
- }
-
- /**
- * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param c configuration
- * @param addresses with which to populate the consistent hash
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses) {
- ConsistentHash ch = (ConsistentHash) Util.getInstance(c.getConsistentHashClass());
- ch.setCaches(addresses);
- return ch;
- }
-
- /**
- * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param c configuration
- * @param addresses with which to populate the consistent hash
- * @param moreAddresses to add to the list of addresses
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses, Address... moreAddresses) {
- List<Address> list = new LinkedList<Address>(addresses);
- list.addAll(Arrays.asList(moreAddresses));
- return createConsistentHash(c, list);
- }
-
- /**
- * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param c configuration
- * @param addresses with which to populate the consistent hash
- * @param moreAddresses to add to the list of addresses
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses, Collection<Address> moreAddresses) {
- List<Address> list = new LinkedList<Address>(addresses);
- list.addAll(moreAddresses);
- return createConsistentHash(c, list);
- }
-
- /**
- * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param clazz type of the consistent hash to create
- * @param addresses with which to populate the consistent hash
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses) {
- ConsistentHash ch;
- ch = Util.getInstance(clazz);
- if (addresses != null && !addresses.isEmpty()) ch.setCaches(addresses);
- return ch;
- }
-
- /**
- * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param clazz type of the consistent hash to create
- * @param addresses with which to populate the consistent hash
- * @param moreAddresses to add to the list of addresses
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses, Address... moreAddresses) {
- List<Address> list = new LinkedList<Address>(addresses);
- list.addAll(Arrays.asList(moreAddresses));
- return createConsistentHash(clazz, list);
- }
-
- /**
- * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
- * with the collection of addresses passed in.
- *
- * @param clazz type of the consistent hash to create
- * @param addresses with which to populate the consistent hash
- * @param moreAddresses to add to the list of addresses
- * @return a new consistent hash instance
- */
- public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses, Collection<Address> moreAddresses) {
- List<Address> list = new LinkedList<Address>(addresses);
- list.addAll(moreAddresses);
- return createConsistentHash(clazz, list);
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/ConsistentHashHelper.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,144 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.config.Configuration;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.util.Util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A helper class that handles the construction of consistent hash instances based on configuration.
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class ConsistentHashHelper {
+
+ /**
+ * Returns a new consistent hash of the same type with the given address removed.
+ *
+ * @param ch consistent hash to start with
+ * @param toRemove address to remove
+ * @param c configuration
+ * @return a new consistent hash instance of the same type
+ */
+ public static ConsistentHash removeAddress(ConsistentHash ch, Address toRemove, Configuration c) {
+ if (ch instanceof UnionConsistentHash)
+ return removeAddressFromUnionConsistentHash((UnionConsistentHash) ch, toRemove, c);
+ else {
+ ConsistentHash newCH = (ConsistentHash) Util.getInstance(c.getConsistentHashClass());
+ List<Address> caches = new ArrayList<Address>(ch.getCaches());
+ caches.remove(toRemove);
+ newCH.setCaches(caches);
+ return newCH;
+ }
+ }
+
+ /**
+ * Creates a new UnionConsistentHash instance based on the old instance, removing the provided address from both
+ * target consistent hash instances in the union.
+ *
+ * @param uch union consistent hash instance
+ * @param toRemove address to remove
+ * @param c configuration
+ * @return a new UnionConsistentHash instance
+ */
+ public static UnionConsistentHash removeAddressFromUnionConsistentHash(UnionConsistentHash uch, Address toRemove, Configuration c) {
+ ConsistentHash newFirstCH = removeAddress(uch.getOldConsistentHash(), toRemove, c);
+ ConsistentHash newSecondCH = removeAddress(uch.getNewConsistentHash(), toRemove, c);
+ return new UnionConsistentHash(newFirstCH, newSecondCH);
+ }
+
+ /**
+ * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
+ * with the collection of addresses passed in.
+ *
+ * @param c configuration
+ * @param addresses with which to populate the consistent hash
+ * @return a new consistent hash instance
+ */
+ public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses) {
+ ConsistentHash ch = (ConsistentHash) Util.getInstance(c.getConsistentHashClass());
+ ch.setCaches(addresses);
+ return ch;
+ }
+
+ /**
+ * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
+ * with the collection of addresses passed in.
+ *
+ * @param c configuration
+ * @param addresses with which to populate the consistent hash
+ * @param moreAddresses to add to the list of addresses
+ * @return a new consistent hash instance
+ */
+ public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses, Address... moreAddresses) {
+ List<Address> list = new LinkedList<Address>(addresses);
+ list.addAll(Arrays.asList(moreAddresses));
+ return createConsistentHash(c, list);
+ }
+
+ /**
+ * Creates a new consistent hash instance based on the user's configuration, and populates the consistent hash
+ * with the collection of addresses passed in.
+ *
+ * @param c configuration
+ * @param addresses with which to populate the consistent hash
+ * @param moreAddresses to add to the list of addresses
+ * @return a new consistent hash instance
+ */
+ public static ConsistentHash createConsistentHash(Configuration c, List<Address> addresses, Collection<Address> moreAddresses) {
+ List<Address> list = new LinkedList<Address>(addresses);
+ list.addAll(moreAddresses);
+ return createConsistentHash(c, list);
+ }
+
+ /**
+ * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
+ * with the collection of addresses passed in.
+ *
+ * @param clazz type of the consistent hash to create
+ * @param addresses with which to populate the consistent hash
+ * @return a new consistent hash instance
+ */
+ public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses) {
+ ConsistentHash ch;
+ ch = Util.getInstance(clazz);
+ if (addresses != null && !addresses.isEmpty()) ch.setCaches(addresses);
+ return ch;
+ }
+
+ /**
+ * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
+ * with the collection of addresses passed in.
+ *
+ * @param clazz type of the consistent hash to create
+ * @param addresses with which to populate the consistent hash
+ * @param moreAddresses to add to the list of addresses
+ * @return a new consistent hash instance
+ */
+ public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses, Address... moreAddresses) {
+ List<Address> list = new LinkedList<Address>(addresses);
+ list.addAll(Arrays.asList(moreAddresses));
+ return createConsistentHash(clazz, list);
+ }
+
+ /**
+ * Creates a new consistent hash instance based on the type specified, and populates the consistent hash
+ * with the collection of addresses passed in.
+ *
+ * @param clazz type of the consistent hash to create
+ * @param addresses with which to populate the consistent hash
+ * @param moreAddresses to add to the list of addresses
+ * @return a new consistent hash instance
+ */
+ public static ConsistentHash createConsistentHash(Class<? extends ConsistentHash> clazz, List<Address> addresses, Collection<Address> moreAddresses) {
+ List<Address> list = new LinkedList<Address>(addresses);
+ list.addAll(moreAddresses);
+ return createConsistentHash(clazz, list);
+ }
+}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,199 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-
-import static java.lang.Math.min;
-
- at Marshallable(externalizer = DefaultConsistentHash.Externalizer.class, id = Ids.DEFAULT_CONSISTENT_HASH)
-public class DefaultConsistentHash extends AbstractWheelConsistentHash {
-
- private static Log log = LogFactory.getLog(DefaultConsistentHash.class);
-
- public List<Address> locate(Object key, int replCount) {
- int hash = getNormalizedHash(key);
- int numCopiesToFind = min(replCount, addresses.size());
-
- List<Address> owners = new ArrayList<Address>(numCopiesToFind);
-
- SortedMap<Integer, Address> candidates = positions.tailMap(hash);
-
- int numOwnersFound = 0;
-
- for (Address a : candidates.values()) {
- if (numOwnersFound < numCopiesToFind) {
- owners.add(a);
- numOwnersFound++;
- } else {
- break;
- }
- }
-
- if (numOwnersFound < numCopiesToFind) {
- for (Address a : positions.values()) {
- if (numOwnersFound < numCopiesToFind) {
- owners.add(a);
- numOwnersFound++;
- } else {
- break;
- }
- }
- }
-
- return owners;
- }
-
- @Override
- public boolean isKeyLocalToAddress(Address target, Object key, int replCount) {
- int hash = getNormalizedHash(key);
- int numCopiesToFind = min(replCount, addresses.size());
-
- SortedMap<Integer, Address> candidates = positions.tailMap(hash);
- int nodesTested = 0;
- for (Address a : candidates.values()) {
- if (nodesTested < numCopiesToFind) {
- if (a.equals(target)) return true;
- nodesTested++;
- } else {
- break;
- }
- }
-
- // start from the beginning
- if (nodesTested < numCopiesToFind) {
- for (Address a : positions.values()) {
- if (nodesTested < numCopiesToFind) {
- if (a.equals(target)) return true;
- nodesTested++;
- } else {
- break;
- }
- }
- }
-
- return false;
- }
-
-
- public int getDistance(Address a1, Address a2) {
- if (a1 == null || a2 == null) throw new NullPointerException("Cannot deal with nulls as parameters!");
-
- int p1 = addresses.indexOf(a1);
- if (p1 < 0)
- return -1;
-
- int p2 = addresses.indexOf(a2);
- if (p2 < 0)
- return -1;
-
- if (p1 <= p2)
- return p2 - p1;
- else
- return addresses.size() - (p1 - p2);
- }
-
- public boolean isAdjacent(Address a1, Address a2) {
- int distance = getDistance(a1, a2);
- return distance == 1 || distance == addresses.size() - 1;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- DefaultConsistentHash that = (DefaultConsistentHash) o;
-
- if (addresses != null ? !addresses.equals(that.addresses) : that.addresses != null) return false;
- if (positions != null ? !positions.equals(that.positions) : that.positions != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = addresses != null ? addresses.hashCode() : 0;
- result = 31 * result + (positions != null ? positions.hashCode() : 0);
- return result;
- }
-
- public static class Externalizer implements org.infinispan.marshall.Externalizer {
- public void writeObject(ObjectOutput output, Object subject) throws IOException {
- DefaultConsistentHash dch = (DefaultConsistentHash) subject;
- output.writeObject(dch.addresses);
- output.writeObject(dch.positions);
- output.writeObject(dch.addressToHashIds);
- }
-
- @SuppressWarnings("unchecked")
- public Object readObject(ObjectInput unmarshaller) throws IOException, ClassNotFoundException {
- DefaultConsistentHash dch = new DefaultConsistentHash();
- dch.addresses = (ArrayList<Address>) unmarshaller.readObject();
- dch.positions = (SortedMap<Integer, Address>) unmarshaller.readObject();
- dch.addressToHashIds = (Map<Address, Integer>) unmarshaller.readObject();
- return dch;
- }
- }
-
- @Override
- public String toString() {
- return "DefaultConsistentHash{" +
- "addresses =" + positions +
- ", hash space =" + HASH_SPACE +
- '}';
- }
-
- public List<Address> getAddressOnTheWheel() {
- return addresses;
- }
-
- public List<Address> getStateProvidersOnJoin(Address self, int replCount) {
- List<Address> l = new LinkedList<Address>();
- List<Address> caches = getCaches();
- int selfIdx = caches.indexOf(self);
- if (selfIdx >= replCount - 1) {
- l.addAll(caches.subList(selfIdx - replCount + 1, selfIdx));
- } else {
- l.addAll(caches.subList(0, selfIdx));
- int alreadyCollected = l.size();
- l.addAll(caches.subList(caches.size() - replCount + 1 + alreadyCollected, caches.size()));
- }
-
- Address plusOne;
- if (selfIdx == caches.size() - 1)
- plusOne = caches.get(0);
- else
- plusOne = caches.get(selfIdx + 1);
-
- if (!l.contains(plusOne)) l.add(plusOne);
- return l;
- }
-
- public List<Address> getStateProvidersOnLeave(Address leaver, int replCount) {
- if (log.isTraceEnabled()) log.trace("List of addresses is: " + addresses + ". leaver is: " + leaver);
- Set<Address> holders = new HashSet<Address>();
- for (Address address : addresses) {
- if (isAdjacent(leaver, address)) {
- holders.add(address);
- if (log.isTraceEnabled()) log.trace(address + " is state holder");
- } else {
- if (log.isTraceEnabled()) log.trace(address + " NOT state holder");
- }
- }
- return new ArrayList<Address>(holders);
- }
-}
\ No newline at end of file
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/DefaultConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,199 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.marshall.Ids;
+import org.infinispan.marshall.Marshallable;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+
+import static java.lang.Math.min;
+
+ at Marshallable(externalizer = DefaultConsistentHash.Externalizer.class, id = Ids.DEFAULT_CONSISTENT_HASH)
+public class DefaultConsistentHash extends AbstractWheelConsistentHash {
+
+ private static Log log = LogFactory.getLog(DefaultConsistentHash.class);
+
+ public List<Address> locate(Object key, int replCount) {
+ int hash = getNormalizedHash(key);
+ int numCopiesToFind = min(replCount, addresses.size());
+
+ List<Address> owners = new ArrayList<Address>(numCopiesToFind);
+
+ SortedMap<Integer, Address> candidates = positions.tailMap(hash);
+
+ int numOwnersFound = 0;
+
+ for (Address a : candidates.values()) {
+ if (numOwnersFound < numCopiesToFind) {
+ owners.add(a);
+ numOwnersFound++;
+ } else {
+ break;
+ }
+ }
+
+ if (numOwnersFound < numCopiesToFind) {
+ for (Address a : positions.values()) {
+ if (numOwnersFound < numCopiesToFind) {
+ owners.add(a);
+ numOwnersFound++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ return owners;
+ }
+
+ @Override
+ public boolean isKeyLocalToAddress(Address target, Object key, int replCount) {
+ int hash = getNormalizedHash(key);
+ int numCopiesToFind = min(replCount, addresses.size());
+
+ SortedMap<Integer, Address> candidates = positions.tailMap(hash);
+ int nodesTested = 0;
+ for (Address a : candidates.values()) {
+ if (nodesTested < numCopiesToFind) {
+ if (a.equals(target)) return true;
+ nodesTested++;
+ } else {
+ break;
+ }
+ }
+
+ // start from the beginning
+ if (nodesTested < numCopiesToFind) {
+ for (Address a : positions.values()) {
+ if (nodesTested < numCopiesToFind) {
+ if (a.equals(target)) return true;
+ nodesTested++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ public int getDistance(Address a1, Address a2) {
+ if (a1 == null || a2 == null) throw new NullPointerException("Cannot deal with nulls as parameters!");
+
+ int p1 = addresses.indexOf(a1);
+ if (p1 < 0)
+ return -1;
+
+ int p2 = addresses.indexOf(a2);
+ if (p2 < 0)
+ return -1;
+
+ if (p1 <= p2)
+ return p2 - p1;
+ else
+ return addresses.size() - (p1 - p2);
+ }
+
+ public boolean isAdjacent(Address a1, Address a2) {
+ int distance = getDistance(a1, a2);
+ return distance == 1 || distance == addresses.size() - 1;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ DefaultConsistentHash that = (DefaultConsistentHash) o;
+
+ if (addresses != null ? !addresses.equals(that.addresses) : that.addresses != null) return false;
+ if (positions != null ? !positions.equals(that.positions) : that.positions != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = addresses != null ? addresses.hashCode() : 0;
+ result = 31 * result + (positions != null ? positions.hashCode() : 0);
+ return result;
+ }
+
+ public static class Externalizer implements org.infinispan.marshall.Externalizer {
+ public void writeObject(ObjectOutput output, Object subject) throws IOException {
+ DefaultConsistentHash dch = (DefaultConsistentHash) subject;
+ output.writeObject(dch.addresses);
+ output.writeObject(dch.positions);
+ output.writeObject(dch.addressToHashIds);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object readObject(ObjectInput unmarshaller) throws IOException, ClassNotFoundException {
+ DefaultConsistentHash dch = new DefaultConsistentHash();
+ dch.addresses = (ArrayList<Address>) unmarshaller.readObject();
+ dch.positions = (SortedMap<Integer, Address>) unmarshaller.readObject();
+ dch.addressToHashIds = (Map<Address, Integer>) unmarshaller.readObject();
+ return dch;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultConsistentHash{" +
+ "addresses =" + positions +
+ ", hash space =" + HASH_SPACE +
+ '}';
+ }
+
+ public List<Address> getAddressOnTheWheel() {
+ return addresses;
+ }
+
+ public List<Address> getStateProvidersOnJoin(Address self, int replCount) {
+ List<Address> l = new LinkedList<Address>();
+ List<Address> caches = getCaches();
+ int selfIdx = caches.indexOf(self);
+ if (selfIdx >= replCount - 1) {
+ l.addAll(caches.subList(selfIdx - replCount + 1, selfIdx));
+ } else {
+ l.addAll(caches.subList(0, selfIdx));
+ int alreadyCollected = l.size();
+ l.addAll(caches.subList(caches.size() - replCount + 1 + alreadyCollected, caches.size()));
+ }
+
+ Address plusOne;
+ if (selfIdx == caches.size() - 1)
+ plusOne = caches.get(0);
+ else
+ plusOne = caches.get(selfIdx + 1);
+
+ if (!l.contains(plusOne)) l.add(plusOne);
+ return l;
+ }
+
+ public List<Address> getStateProvidersOnLeave(Address leaver, int replCount) {
+ if (log.isTraceEnabled()) log.trace("List of addresses is: " + addresses + ". leaver is: " + leaver);
+ Set<Address> holders = new HashSet<Address>();
+ for (Address address : addresses) {
+ if (isAdjacent(leaver, address)) {
+ holders.add(address);
+ if (log.isTraceEnabled()) log.trace(address + " is state holder");
+ } else {
+ if (log.isTraceEnabled()) log.trace(address + " NOT state holder");
+ }
+ }
+ return new ArrayList<Address>(holders);
+ }
+}
\ No newline at end of file
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,392 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.Util;
-
-import javax.naming.OperationNotSupportedException;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import static java.lang.Math.min;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * <a href = "http://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html">Consistent hashing
- * algorithm</a>. Each target is entered into the pool <i>weight[i]</i>*<i>weightFactor</i> times. Where
- * <i>weight[i]</i> and <i>weightFactor</i> are integers greater than zero.
- * <p/>
- * Based on akluge's impl on <a href-="http://www.vizitsolutions.com/ConsistentHashingCaching.html">http://www.vizitsolutions.com/ConsistentHashingCaching.html</a>
- *
- * @author akluge
- * @author Manik Surtani
- */
- at Marshallable(externalizer = ExperimentalDefaultConsistentHash.Externalizer.class, id = Ids.DEFAULT_CONSISTENT_HASH)
-public class ExperimentalDefaultConsistentHash extends AbstractConsistentHash {
- /**
- * A Weight and weight factor of 1 gives one node per address. In future we may decide to make these configurable,
- * to allow for virtual nodes and a better spread of state across nodes, but we need to ensure we deal with backups
- * not falling on virtual nodes on the same cache instances first.
- */
- private static final int DEFAULT_WEIGHT = 1;
- private static final int DEFAULT_WEIGHTFACTOR = 1;
-
- private List<Address> nodes;
- private List<Entry> pool;
- private int poolSize;
-
- public static class Externalizer implements org.infinispan.marshall.Externalizer {
-
- public void writeObject(ObjectOutput output, Object object) throws IOException {
- ExperimentalDefaultConsistentHash gch = (ExperimentalDefaultConsistentHash) object;
- output.writeObject(gch.nodes);
- }
-
- @SuppressWarnings("unchecked")
- public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
- List<Address> addresses = (List<Address>) input.readObject();
- DefaultConsistentHash gch = new DefaultConsistentHash();
- gch.setCaches(addresses);
- return gch;
- }
- }
-
- public List<Address> getCaches() {
- return nodes;
- }
-
- public void setCaches(List<Address> caches) {
- nodes = caches;
- int numNodes = nodes.size();
-
- int poolSize = 0;
-
- for (int i = 0; i < numNodes; i++) {
- poolSize += DEFAULT_WEIGHT * DEFAULT_WEIGHTFACTOR;
- }
- this.poolSize = poolSize;
- pool = new ArrayList<Entry>(poolSize);
-
- int numEntries = 0;
- for (int i = 0; i < numNodes; i++) {
- numEntries = add(nodes.get(i), DEFAULT_WEIGHT * DEFAULT_WEIGHTFACTOR, numEntries);
- }
- Collections.sort(pool);
- nodes = getSortedCachesList();
- }
-
- private List<Address> getSortedCachesList() {
- ArrayList<Address> caches = new ArrayList<Address>();
- for (Entry e : pool) {
- if (!caches.contains(e.address)) caches.add(e.address);
- }
- caches.trimToSize();
- return caches;
- }
-
- /**
- * Adds an Address to the pool of available addresses.
- *
- * @param node Address to be added to the hash pool.
- * @param count An int giving the number of times the node is added to the pool. The count is greater than zero,
- * and is likely greater than 10 if weights are used. The count for the i-th node is usually the
- * <i>weights</i>[i]*<i>weightfactor</i>, if weights are used.
- * @param position The position in the pool to begin adding node entries.
- * @return position;
- */
- private int add(Address node, int count, int position) {
- int hash;
- String nodeName = node.toString();
- for (int i = 0; i < count; i++) {
- hash = hash((Integer.toString(i) + nodeName).getBytes());
- pool.add(position++, new Entry(node, nodeName, i, hash));
- }
- return position;
- }
-
- /**
- * The distance between the first entries in the address array for two caches, a1 and a2. Of questionable use when
- * virtual nodes are employed.
- *
- * @param a1 The address of the first cache.
- * @param a2 The address of the second cache.
- * @return Am int containing the difference between these two indices.
- */
- public int getDistance(Address a1, Address a2) {
- if (a1 == null || a2 == null) throw new NullPointerException("Cannot find the distance between null servers.");
-
- int p1 = nodes.indexOf(a1);
- if (p1 < 0)
- throw new IllegalArgumentException("Address " + a1 + " not in the addresses list of this consistent hash impl!");
-
- int p2 = nodes.indexOf(a2);
- if (p2 < 0)
- throw new IllegalArgumentException("Address " + a2 + " not in the addresses list of this consistent hash impl!");
-
- if (p1 <= p2)
- return p2 - p1;
- else
- return pool.size() - (p1 - p2);
- }
-
- /**
- * Two hashes are adjacent if they are next to each other in the consistent hash.
- *
- * @param a1 The address of the first cache.
- * @param a2 The address of the second cache.
- * @return A boolean, true if they are adjacent, false if not.
- */
- public boolean isAdjacent(Address a1, Address a2) {
- int distance = getDistance(a1, a2);
- return distance == 1 || distance == pool.size() - 1;
- }
-
- public List<Address> locate(Object key, int replCount) {
- if (key == null) throw new NullPointerException("Attempt to get with null key");
-
- int clusterSize = pool.size();
- int numCopiesToFind = min(replCount, clusterSize);
- int hashValue = hash(key);
- return locate(hashValue, numCopiesToFind, replCount);
- }
-
- /**
- * Returns a List of <i>numCopiesToFind</i> unique Addresses.
- *
- * @param hashValue An int, usually a hash, to be mapped to a bin via the CH.
- * @param numCopiesToFind number of copies to find
- * @param replCount replication count
- * @return Returns a List of <i>numCopiesToFind</i> unique Addresses.
- */
- private List<Address> locate(int hashValue, int numCopiesToFind, int replCount) {
- // Stop looking if we have checked the entire pool.
- int checked = 0;
- // Start looking at the first (primary) node for entries for this value.
- int inode = findNearestNodeInPool(hashValue);
- List<Address> nodes = new ArrayList<Address>(numCopiesToFind);
-
- while (nodes.size() < replCount && checked < poolSize) {
- Entry poolEntry;
- if ((poolEntry = pool.get(inode)) != null && nodes.indexOf(poolEntry.address) < 0) {
- nodes.add(poolEntry.address);
- }
- inode = (++inode) % poolSize;
- checked++;
- }
- return nodes;
- }
-
- /**
- * Find a target for a hash key within the pool of node Entries. We search within a slice of the array bounded by
- * lowerBound and upperBound. Further we assume that lowerBound and upperBound are small enough that their sum will
- * not overflow an int.
- * <p/>
- *
- * @param hash The desired hash to locate.
- * @return An int giving the index of the desired entry in the list of targets. If the target is not found, then
- * -(lowerBound +1) will be returned, where lowerBound is the lower bound of the search after possibly
- * several iterations.
- */
- private int binarySearch(int hash) {
- int lowerBound = 0;
- int upperBound = pool.size() - 1;
- while (lowerBound <= upperBound) {
- // Fast div by 2. We assume that the number of targets is small enough
- // that the sum will not overflow an int.
- int mid = (lowerBound + upperBound) >>> 1;
- int currentHash = pool.get(mid).hash;
-
- if (currentHash < hash) {
- lowerBound = mid + 1;
- } else if (currentHash > hash) {
- upperBound = mid - 1;
- } else {
- return mid;
- }
- }
- // The +1 ensures that the return value is negative, even when the hash
- // is off the left edge of the array.
- return -(lowerBound + 1);
- }
-
- /**
- * Finds the lowest index into the pool ArrayList such that the hash of the i-th entry >= hash.
- *
- * @param hash The hash being mapped to a bin via the consistent hash.
- * @return An int, the lowest index into the target array such that the hash of the i-th entry >= hash.
- */
- private int findNearestNodeInPool(int hash) {
- // Find the index of the node - or at least a near one.
- // We only search up to targets.length-1. If the element
- // is greater than the last entry in the list, then map
- // it to the first one.
- int nodeIndex = binarySearch(hash);
-
- // If the returned value is less than zero, then no exact match was found.
- if (nodeIndex < 0) {
- // The value returned is -(lowerBound +1), we want the lower bound back.
- nodeIndex = -(nodeIndex + 1);
-
- // If hash is greater than the last entry, wrap around to the first.
- if (nodeIndex >= pool.size()) {
- nodeIndex = 0;
- }
- }
-
- return nodeIndex;
- }
-
- /**
- * Use the objects built in hash to obtain an initial value, then use a second four byte hash to obtain a more
- * uniform distribution of hash values. This uses a <a href = "http://burtleburtle.net/bob/hash/integer.html">4-byte
- * (integer) hash</a>, which produces well distributed values even when the original hash produces thghtly clustered
- * values.
- * <p/>
- * It is important that the object implement its own hashcode, and not use the Object hashcode.
- *
- * @param object object to hash
- * @return an appropriately spread hash code
- */
- private int hash(Object object) {
- int hash = object.hashCode();
-
- hash = (hash + 0x7ED55D16) + (hash << 12);
- hash = (hash ^ 0xc761c23c) ^ (hash >> 19);
- hash = (hash + 0x165667b1) + (hash << 5);
- hash = (hash + 0xd3a2646c) ^ (hash << 9);
- hash = (hash + 0xfd7046c5) + (hash << 3);
- hash = (hash ^ 0xb55a4f09) ^ (hash >> 16);
-
- return hash;
- }
-
- @Override
- public int getHashId(Address a) {
- throw new RuntimeException("Not yet implemented");
- }
-
- @Override
- public int getHashSpace() {
- return Integer.MAX_VALUE; // Entire positive integer range
- }
-
- /**
- * @return A String representing the object pool.
- */
- @Override
- public String toString() {
- return " pool: " + pool;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == null
- || !(other instanceof ExperimentalDefaultConsistentHash)) {
- return false;
- }
-
- ExperimentalDefaultConsistentHash otherHash = (ExperimentalDefaultConsistentHash) other;
- return Util.safeEquals(pool, otherHash.pool);
- }
-
- @Override
- public int hashCode() {
- int hashCode = 1;
- for (Entry e : pool) hashCode = 31 * hashCode + e.hash;
- return hashCode;
- }
-
- /**
- * An entry into a consistent hash. It wraps the original object, the object's hash as used to generate the
- * consistent hash, the value extracted from the object used to generate the hash, and the modifier used to
- * differentiate the hash.
- */
- public static class Entry implements Comparable<Entry> {
- public final int differentiator;
- public final int hash;
- public final Address address;
- public final String string;
-
- public Entry(Address address, String string, int differentiator, int hash) {
- this.differentiator = differentiator;
- this.hash = hash;
- this.address = address;
- this.string = string;
- }
-
- /**
- * Compare this Entry with another Entry. First the hash values are compared, then the differentiator is compared.
- * if the hash values are equal.
- *
- * @param other An Entry object to be compared with this object. Returns <ul> <li>-1 if this Entry is less than
- * the other Entry.</li> <li>0 if they are equal.</li> <li>+1 if this Entry is greater than the
- * other Entry.</li> </ul>
- * @return
- */
- public int compareTo(Entry other) {
- if (this.hash < other.hash) {
- return -1;
- }
-
- if (this.hash > other.hash) {
- return 1;
- }
-
- if (this.differentiator < other.differentiator) {
- return -1;
- }
-
- if (this.differentiator > other.differentiator) {
- return +1;
- }
-
- return 0;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof Entry) {
- Entry otherEntry = (Entry) other;
-
- return hash == otherEntry.hash
- && differentiator == otherEntry.differentiator
- && address.equals(otherEntry.address);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return hash;
- }
-
-
- @Override
- public String toString() {
- return string + ":" + Integer.toHexString(hash);
- }
- }
-
- public List<Address> getStateProvidersOnLeave(Address leaver, int replCount) {
- Set<Address> holders = new HashSet<Address>();
- for (Address address : nodes) {
- if (isAdjacent(leaver, address)) {
- holders.add(address);
- }
- }
- return new ArrayList<Address>(holders);
- }
-
- public boolean isStateReceiverOnLeave(Address leaver, Address node, int replCount) {
- throw new RuntimeException("Not implemented!");
- }
-
- public List<Address> getStateProvidersOnJoin(Address joiner, int replCount) {
- throw new RuntimeException("Not implemented!");
- }
-}
\ No newline at end of file
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/ExperimentalDefaultConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,392 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.marshall.Ids;
+import org.infinispan.marshall.Marshallable;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.util.Util;
+
+import javax.naming.OperationNotSupportedException;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import static java.lang.Math.min;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * <a href = "http://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html">Consistent hashing
+ * algorithm</a>. Each target is entered into the pool <i>weight[i]</i>*<i>weightFactor</i> times. Where
+ * <i>weight[i]</i> and <i>weightFactor</i> are integers greater than zero.
+ * <p/>
+ * Based on akluge's impl on <a href-="http://www.vizitsolutions.com/ConsistentHashingCaching.html">http://www.vizitsolutions.com/ConsistentHashingCaching.html</a>
+ *
+ * @author akluge
+ * @author Manik Surtani
+ */
+ at Marshallable(externalizer = ExperimentalDefaultConsistentHash.Externalizer.class, id = Ids.DEFAULT_CONSISTENT_HASH)
+public class ExperimentalDefaultConsistentHash extends AbstractConsistentHash {
+ /**
+ * A Weight and weight factor of 1 gives one node per address. In future we may decide to make these configurable,
+ * to allow for virtual nodes and a better spread of state across nodes, but we need to ensure we deal with backups
+ * not falling on virtual nodes on the same cache instances first.
+ */
+ private static final int DEFAULT_WEIGHT = 1;
+ private static final int DEFAULT_WEIGHTFACTOR = 1;
+
+ private List<Address> nodes;
+ private List<Entry> pool;
+ private int poolSize;
+
+ public static class Externalizer implements org.infinispan.marshall.Externalizer {
+
+ public void writeObject(ObjectOutput output, Object object) throws IOException {
+ ExperimentalDefaultConsistentHash gch = (ExperimentalDefaultConsistentHash) object;
+ output.writeObject(gch.nodes);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
+ List<Address> addresses = (List<Address>) input.readObject();
+ DefaultConsistentHash gch = new DefaultConsistentHash();
+ gch.setCaches(addresses);
+ return gch;
+ }
+ }
+
+ public List<Address> getCaches() {
+ return nodes;
+ }
+
+ public void setCaches(List<Address> caches) {
+ nodes = caches;
+ int numNodes = nodes.size();
+
+ int poolSize = 0;
+
+ for (int i = 0; i < numNodes; i++) {
+ poolSize += DEFAULT_WEIGHT * DEFAULT_WEIGHTFACTOR;
+ }
+ this.poolSize = poolSize;
+ pool = new ArrayList<Entry>(poolSize);
+
+ int numEntries = 0;
+ for (int i = 0; i < numNodes; i++) {
+ numEntries = add(nodes.get(i), DEFAULT_WEIGHT * DEFAULT_WEIGHTFACTOR, numEntries);
+ }
+ Collections.sort(pool);
+ nodes = getSortedCachesList();
+ }
+
+ private List<Address> getSortedCachesList() {
+ ArrayList<Address> caches = new ArrayList<Address>();
+ for (Entry e : pool) {
+ if (!caches.contains(e.address)) caches.add(e.address);
+ }
+ caches.trimToSize();
+ return caches;
+ }
+
+ /**
+ * Adds an Address to the pool of available addresses.
+ *
+ * @param node Address to be added to the hash pool.
+ * @param count An int giving the number of times the node is added to the pool. The count is greater than zero,
+ * and is likely greater than 10 if weights are used. The count for the i-th node is usually the
+ * <i>weights</i>[i]*<i>weightfactor</i>, if weights are used.
+ * @param position The position in the pool to begin adding node entries.
+ * @return position;
+ */
+ private int add(Address node, int count, int position) {
+ int hash;
+ String nodeName = node.toString();
+ for (int i = 0; i < count; i++) {
+ hash = hash((Integer.toString(i) + nodeName).getBytes());
+ pool.add(position++, new Entry(node, nodeName, i, hash));
+ }
+ return position;
+ }
+
+ /**
+ * The distance between the first entries in the address array for two caches, a1 and a2. Of questionable use when
+ * virtual nodes are employed.
+ *
+ * @param a1 The address of the first cache.
+ * @param a2 The address of the second cache.
+ * @return Am int containing the difference between these two indices.
+ */
+ public int getDistance(Address a1, Address a2) {
+ if (a1 == null || a2 == null) throw new NullPointerException("Cannot find the distance between null servers.");
+
+ int p1 = nodes.indexOf(a1);
+ if (p1 < 0)
+ throw new IllegalArgumentException("Address " + a1 + " not in the addresses list of this consistent hash impl!");
+
+ int p2 = nodes.indexOf(a2);
+ if (p2 < 0)
+ throw new IllegalArgumentException("Address " + a2 + " not in the addresses list of this consistent hash impl!");
+
+ if (p1 <= p2)
+ return p2 - p1;
+ else
+ return pool.size() - (p1 - p2);
+ }
+
+ /**
+ * Two hashes are adjacent if they are next to each other in the consistent hash.
+ *
+ * @param a1 The address of the first cache.
+ * @param a2 The address of the second cache.
+ * @return A boolean, true if they are adjacent, false if not.
+ */
+ public boolean isAdjacent(Address a1, Address a2) {
+ int distance = getDistance(a1, a2);
+ return distance == 1 || distance == pool.size() - 1;
+ }
+
+ public List<Address> locate(Object key, int replCount) {
+ if (key == null) throw new NullPointerException("Attempt to get with null key");
+
+ int clusterSize = pool.size();
+ int numCopiesToFind = min(replCount, clusterSize);
+ int hashValue = hash(key);
+ return locate(hashValue, numCopiesToFind, replCount);
+ }
+
+ /**
+ * Returns a List of <i>numCopiesToFind</i> unique Addresses.
+ *
+ * @param hashValue An int, usually a hash, to be mapped to a bin via the CH.
+ * @param numCopiesToFind number of copies to find
+ * @param replCount replication count
+ * @return Returns a List of <i>numCopiesToFind</i> unique Addresses.
+ */
+ private List<Address> locate(int hashValue, int numCopiesToFind, int replCount) {
+ // Stop looking if we have checked the entire pool.
+ int checked = 0;
+ // Start looking at the first (primary) node for entries for this value.
+ int inode = findNearestNodeInPool(hashValue);
+ List<Address> nodes = new ArrayList<Address>(numCopiesToFind);
+
+ while (nodes.size() < replCount && checked < poolSize) {
+ Entry poolEntry;
+ if ((poolEntry = pool.get(inode)) != null && nodes.indexOf(poolEntry.address) < 0) {
+ nodes.add(poolEntry.address);
+ }
+ inode = (++inode) % poolSize;
+ checked++;
+ }
+ return nodes;
+ }
+
+ /**
+ * Find a target for a hash key within the pool of node Entries. We search within a slice of the array bounded by
+ * lowerBound and upperBound. Further we assume that lowerBound and upperBound are small enough that their sum will
+ * not overflow an int.
+ * <p/>
+ *
+ * @param hash The desired hash to locate.
+ * @return An int giving the index of the desired entry in the list of targets. If the target is not found, then
+ * -(lowerBound +1) will be returned, where lowerBound is the lower bound of the search after possibly
+ * several iterations.
+ */
+ private int binarySearch(int hash) {
+ int lowerBound = 0;
+ int upperBound = pool.size() - 1;
+ while (lowerBound <= upperBound) {
+ // Fast div by 2. We assume that the number of targets is small enough
+ // that the sum will not overflow an int.
+ int mid = (lowerBound + upperBound) >>> 1;
+ int currentHash = pool.get(mid).hash;
+
+ if (currentHash < hash) {
+ lowerBound = mid + 1;
+ } else if (currentHash > hash) {
+ upperBound = mid - 1;
+ } else {
+ return mid;
+ }
+ }
+ // The +1 ensures that the return value is negative, even when the hash
+ // is off the left edge of the array.
+ return -(lowerBound + 1);
+ }
+
+ /**
+ * Finds the lowest index into the pool ArrayList such that the hash of the i-th entry >= hash.
+ *
+ * @param hash The hash being mapped to a bin via the consistent hash.
+ * @return An int, the lowest index into the target array such that the hash of the i-th entry >= hash.
+ */
+ private int findNearestNodeInPool(int hash) {
+ // Find the index of the node - or at least a near one.
+ // We only search up to targets.length-1. If the element
+ // is greater than the last entry in the list, then map
+ // it to the first one.
+ int nodeIndex = binarySearch(hash);
+
+ // If the returned value is less than zero, then no exact match was found.
+ if (nodeIndex < 0) {
+ // The value returned is -(lowerBound +1), we want the lower bound back.
+ nodeIndex = -(nodeIndex + 1);
+
+ // If hash is greater than the last entry, wrap around to the first.
+ if (nodeIndex >= pool.size()) {
+ nodeIndex = 0;
+ }
+ }
+
+ return nodeIndex;
+ }
+
+ /**
+ * Use the objects built in hash to obtain an initial value, then use a second four byte hash to obtain a more
+ * uniform distribution of hash values. This uses a <a href = "http://burtleburtle.net/bob/hash/integer.html">4-byte
+ * (integer) hash</a>, which produces well distributed values even when the original hash produces thghtly clustered
+ * values.
+ * <p/>
+ * It is important that the object implement its own hashcode, and not use the Object hashcode.
+ *
+ * @param object object to hash
+ * @return an appropriately spread hash code
+ */
+ private int hash(Object object) {
+ int hash = object.hashCode();
+
+ hash = (hash + 0x7ED55D16) + (hash << 12);
+ hash = (hash ^ 0xc761c23c) ^ (hash >> 19);
+ hash = (hash + 0x165667b1) + (hash << 5);
+ hash = (hash + 0xd3a2646c) ^ (hash << 9);
+ hash = (hash + 0xfd7046c5) + (hash << 3);
+ hash = (hash ^ 0xb55a4f09) ^ (hash >> 16);
+
+ return hash;
+ }
+
+ @Override
+ public int getHashId(Address a) {
+ throw new RuntimeException("Not yet implemented");
+ }
+
+ @Override
+ public int getHashSpace() {
+ return Integer.MAX_VALUE; // Entire positive integer range
+ }
+
+ /**
+ * @return A String representing the object pool.
+ */
+ @Override
+ public String toString() {
+ return " pool: " + pool;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null
+ || !(other instanceof ExperimentalDefaultConsistentHash)) {
+ return false;
+ }
+
+ ExperimentalDefaultConsistentHash otherHash = (ExperimentalDefaultConsistentHash) other;
+ return Util.safeEquals(pool, otherHash.pool);
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = 1;
+ for (Entry e : pool) hashCode = 31 * hashCode + e.hash;
+ return hashCode;
+ }
+
+ /**
+ * An entry into a consistent hash. It wraps the original object, the object's hash as used to generate the
+ * consistent hash, the value extracted from the object used to generate the hash, and the modifier used to
+ * differentiate the hash.
+ */
+ public static class Entry implements Comparable<Entry> {
+ public final int differentiator;
+ public final int hash;
+ public final Address address;
+ public final String string;
+
+ public Entry(Address address, String string, int differentiator, int hash) {
+ this.differentiator = differentiator;
+ this.hash = hash;
+ this.address = address;
+ this.string = string;
+ }
+
+ /**
+ * Compare this Entry with another Entry. First the hash values are compared, then the differentiator is compared.
+ * if the hash values are equal.
+ *
+ * @param other An Entry object to be compared with this object. Returns <ul> <li>-1 if this Entry is less than
+ * the other Entry.</li> <li>0 if they are equal.</li> <li>+1 if this Entry is greater than the
+ * other Entry.</li> </ul>
+ * @return
+ */
+ public int compareTo(Entry other) {
+ if (this.hash < other.hash) {
+ return -1;
+ }
+
+ if (this.hash > other.hash) {
+ return 1;
+ }
+
+ if (this.differentiator < other.differentiator) {
+ return -1;
+ }
+
+ if (this.differentiator > other.differentiator) {
+ return +1;
+ }
+
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof Entry) {
+ Entry otherEntry = (Entry) other;
+
+ return hash == otherEntry.hash
+ && differentiator == otherEntry.differentiator
+ && address.equals(otherEntry.address);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return hash;
+ }
+
+
+ @Override
+ public String toString() {
+ return string + ":" + Integer.toHexString(hash);
+ }
+ }
+
+ public List<Address> getStateProvidersOnLeave(Address leaver, int replCount) {
+ Set<Address> holders = new HashSet<Address>();
+ for (Address address : nodes) {
+ if (isAdjacent(leaver, address)) {
+ holders.add(address);
+ }
+ }
+ return new ArrayList<Address>(holders);
+ }
+
+ public boolean isStateReceiverOnLeave(Address leaver, Address node, int replCount) {
+ throw new RuntimeException("Not implemented!");
+ }
+
+ public List<Address> getStateProvidersOnJoin(Address joiner, int replCount) {
+ throw new RuntimeException("Not implemented!");
+ }
+}
\ No newline at end of file
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,48 +0,0 @@
-package org.infinispan.distribution.ch;
-
-/**
- * Holds topology information about a a node.
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
-public class NodeTopologyInfo {
-
- private final String machineId;
- private final String rackId;
- private final String siteId;
-
- public NodeTopologyInfo(String machineId, String rackId, String siteId) {
- this.machineId = machineId;
- this.rackId = rackId;
- this.siteId = siteId;
- }
-
- public String getMachineId() {
- return machineId;
- }
-
- public String getRackId() {
- return rackId;
- }
-
- public String getSiteId() {
- return siteId;
- }
-
- public boolean sameSite(NodeTopologyInfo info2) {
- return equalObjects(siteId, info2.siteId);
- }
-
- public boolean sameRack(NodeTopologyInfo info2) {
- return sameSite(info2) && equalObjects(rackId, info2.rackId);
- }
-
- public boolean sameMachine(NodeTopologyInfo info2) {
- return sameRack(info2) && equalObjects(machineId, info2.machineId);
- }
-
- private boolean equalObjects(Object first, Object second) {
- return first == null ? second == null : first.equals(second);
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/NodeTopologyInfo.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,48 @@
+package org.infinispan.distribution.ch;
+
+/**
+ * Holds topology information about a a node.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+public class NodeTopologyInfo {
+
+ private final String machineId;
+ private final String rackId;
+ private final String siteId;
+
+ public NodeTopologyInfo(String machineId, String rackId, String siteId) {
+ this.machineId = machineId;
+ this.rackId = rackId;
+ this.siteId = siteId;
+ }
+
+ public String getMachineId() {
+ return machineId;
+ }
+
+ public String getRackId() {
+ return rackId;
+ }
+
+ public String getSiteId() {
+ return siteId;
+ }
+
+ public boolean sameSite(NodeTopologyInfo info2) {
+ return equalObjects(siteId, info2.siteId);
+ }
+
+ public boolean sameRack(NodeTopologyInfo info2) {
+ return sameSite(info2) && equalObjects(rackId, info2.rackId);
+ }
+
+ public boolean sameMachine(NodeTopologyInfo info2) {
+ return sameRack(info2) && equalObjects(machineId, info2.machineId);
+ }
+
+ private boolean equalObjects(Object first, Object second) {
+ return first == null ? second == null : first.equals(second);
+ }
+}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,122 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.remoting.transport.Address;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import static java.lang.Math.min;
-
-/**
- * Consistent hash that is aware of cluster topology.
- * Design described here: http://community.jboss.org/wiki/DesigningServerHinting.
- * <p>
- * Algorithm:
- * - place nodes on the hash wheel based address's hash code
- * - For selecting owner nodes:
- * - pick the first one based on key's hash code
- * - for subsequent nodes, walk clockwise and pick nodes that have a different site id
- * - if not enough nodes found repeat walk again and pick nodes that have different site id and rack id
- * - if not enough nodes found repeat walk again and pick nodes that have different site id, rack id and machine id
- * - Ultimately cycle back to the first node selected, don't discard any nodes, regardless of machine id/rack
- * id/site id match.
-
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
-public class TopologyAwareConsistentHash extends AbstractWheelConsistentHash {
-
- public List<Address> locate(Object key, int replCount) {
- Address owner = getOwner(key);
- int ownerCount = min(replCount, addresses.size());
- return getOwners(owner, ownerCount);
- }
-
- public List<Address> getStateProvidersOnLeave(Address leaver, int replCount) {
- Set<Address> result = new HashSet<Address>();
-
- //1. first get all the node that replicated on leaver
- for (Address address : addresses) {
- if (address.equals(leaver)) continue;
- if (getOwners(address, replCount).contains(leaver)) {
- result.add(address);
- }
- }
-
- //2. then get first leaver's backup
- List<Address> addressList = getOwners(leaver, replCount);
- if (addressList.size() > 1) {
- result.add(addressList.get(1));
- }
- return new ArrayList<Address>(result);
- }
-
-
- /**
- * In this situation are the same nodes providing state on join as the nodes that provide state on leave.
- */
- public List<Address> getStateProvidersOnJoin(Address joiner, int replCount) {
- return getStateProvidersOnLeave(joiner, replCount);
- }
-
- private List<Address> getOwners(Address address, int numOwners) {
- int ownerHash = getNormalizedHash(address);
- Collection<Address> beforeOnWheel = positions.headMap(ownerHash).values();
- Collection<Address> afterOnWheel = positions.tailMap(ownerHash).values();
- ArrayList<Address> processSequence = new ArrayList<Address>(afterOnWheel);
- processSequence.addAll(beforeOnWheel);
- List<Address> result = new ArrayList<Address>();
- result.add(processSequence.remove(0));
- int level = 0;
- while (result.size() < numOwners) {
- Iterator<Address> addrIt = processSequence.iterator();
- while (addrIt.hasNext()) {
- Address a = addrIt.next();
- switch (level) {
- case 0 : { //site level
- if (!topologyInfo.isSameSite(address, a)) {
- result.add(a);
- addrIt.remove();
- }
- break;
- }
- case 1 : { //rack level
- if (!topologyInfo.isSameRack(address, a)) {
- result.add(a);
- addrIt.remove();
- }
- break;
- }
- case 2 : { //machine level
- if (!topologyInfo.isSameMachine(address, a)) {
- result.add(a);
- addrIt.remove();
- }
- break;
- }
- case 3 : { //just add them in sequence
- result.add(a);
- addrIt.remove();
- break;
- }
- }
- if (result.size() == numOwners) break;
- }
- level++;
- }
- //assertion
- if (result.size() != numOwners) throw new AssertionError("This should not happen!");
- return result;
- }
-
- private Address getOwner(Object key) {
- int hash = getNormalizedHash(key);
- Integer ownerHash = positions.tailMap(hash).firstKey();
- return positions.get(ownerHash);
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyAwareConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,122 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.remoting.transport.Address;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static java.lang.Math.min;
+
+/**
+ * Consistent hash that is aware of cluster topology.
+ * Design described here: http://community.jboss.org/wiki/DesigningServerHinting.
+ * <p>
+ * Algorithm:
+ * - place nodes on the hash wheel based address's hash code
+ * - For selecting owner nodes:
+ * - pick the first one based on key's hash code
+ * - for subsequent nodes, walk clockwise and pick nodes that have a different site id
+ * - if not enough nodes found repeat walk again and pick nodes that have different site id and rack id
+ * - if not enough nodes found repeat walk again and pick nodes that have different site id, rack id and machine id
+ * - Ultimately cycle back to the first node selected, don't discard any nodes, regardless of machine id/rack
+ * id/site id match.
+
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+public class TopologyAwareConsistentHash extends AbstractWheelConsistentHash {
+
+ public List<Address> locate(Object key, int replCount) {
+ Address owner = getOwner(key);
+ int ownerCount = min(replCount, addresses.size());
+ return getOwners(owner, ownerCount);
+ }
+
+ public List<Address> getStateProvidersOnLeave(Address leaver, int replCount) {
+ Set<Address> result = new HashSet<Address>();
+
+ //1. first get all the node that replicated on leaver
+ for (Address address : addresses) {
+ if (address.equals(leaver)) continue;
+ if (getOwners(address, replCount).contains(leaver)) {
+ result.add(address);
+ }
+ }
+
+ //2. then get first leaver's backup
+ List<Address> addressList = getOwners(leaver, replCount);
+ if (addressList.size() > 1) {
+ result.add(addressList.get(1));
+ }
+ return new ArrayList<Address>(result);
+ }
+
+
+ /**
+ * In this situation are the same nodes providing state on join as the nodes that provide state on leave.
+ */
+ public List<Address> getStateProvidersOnJoin(Address joiner, int replCount) {
+ return getStateProvidersOnLeave(joiner, replCount);
+ }
+
+ private List<Address> getOwners(Address address, int numOwners) {
+ int ownerHash = getNormalizedHash(address);
+ Collection<Address> beforeOnWheel = positions.headMap(ownerHash).values();
+ Collection<Address> afterOnWheel = positions.tailMap(ownerHash).values();
+ ArrayList<Address> processSequence = new ArrayList<Address>(afterOnWheel);
+ processSequence.addAll(beforeOnWheel);
+ List<Address> result = new ArrayList<Address>();
+ result.add(processSequence.remove(0));
+ int level = 0;
+ while (result.size() < numOwners) {
+ Iterator<Address> addrIt = processSequence.iterator();
+ while (addrIt.hasNext()) {
+ Address a = addrIt.next();
+ switch (level) {
+ case 0 : { //site level
+ if (!topologyInfo.isSameSite(address, a)) {
+ result.add(a);
+ addrIt.remove();
+ }
+ break;
+ }
+ case 1 : { //rack level
+ if (!topologyInfo.isSameRack(address, a)) {
+ result.add(a);
+ addrIt.remove();
+ }
+ break;
+ }
+ case 2 : { //machine level
+ if (!topologyInfo.isSameMachine(address, a)) {
+ result.add(a);
+ addrIt.remove();
+ }
+ break;
+ }
+ case 3 : { //just add them in sequence
+ result.add(a);
+ addrIt.remove();
+ break;
+ }
+ }
+ if (result.size() == numOwners) break;
+ }
+ level++;
+ }
+ //assertion
+ if (result.size() != numOwners) throw new AssertionError("This should not happen!");
+ return result;
+ }
+
+ private Address getOwner(Object key) {
+ int hash = getNormalizedHash(key);
+ Integer ownerHash = positions.tailMap(hash).firstKey();
+ return positions.get(ownerHash);
+ }
+}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,39 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.remoting.transport.Address;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Aggregates topology information from all nodes within the cluster.
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
-public class TopologyInfo {
-
- private Map<Address, NodeTopologyInfo> address2TopologyInfo = new HashMap<Address, NodeTopologyInfo>();
-
- public void addNodeTopologyInfo(Address addr, NodeTopologyInfo ti) {
- address2TopologyInfo.put(addr, ti);
- }
-
- public boolean isSameSite(Address a1, Address a2) {
- NodeTopologyInfo info1 = address2TopologyInfo.get(a1);
- NodeTopologyInfo info2 = address2TopologyInfo.get(a2);
- return info1.sameSite(info2);
- }
-
- public boolean isSameRack(Address a1, Address a2) {
- NodeTopologyInfo info1 = address2TopologyInfo.get(a1);
- NodeTopologyInfo info2 = address2TopologyInfo.get(a2);
- return info1.sameRack(info2);
- }
-
- public boolean isSameMachine(Address a1, Address a2) {
- NodeTopologyInfo info1 = address2TopologyInfo.get(a1);
- NodeTopologyInfo info2 = address2TopologyInfo.get(a2);
- return info1.sameMachine(info2);
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/TopologyInfo.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,39 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.remoting.transport.Address;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Aggregates topology information from all nodes within the cluster.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+public class TopologyInfo {
+
+ private Map<Address, NodeTopologyInfo> address2TopologyInfo = new HashMap<Address, NodeTopologyInfo>();
+
+ public void addNodeTopologyInfo(Address addr, NodeTopologyInfo ti) {
+ address2TopologyInfo.put(addr, ti);
+ }
+
+ public boolean isSameSite(Address a1, Address a2) {
+ NodeTopologyInfo info1 = address2TopologyInfo.get(a1);
+ NodeTopologyInfo info2 = address2TopologyInfo.get(a2);
+ return info1.sameSite(info2);
+ }
+
+ public boolean isSameRack(Address a1, Address a2) {
+ NodeTopologyInfo info1 = address2TopologyInfo.get(a1);
+ NodeTopologyInfo info2 = address2TopologyInfo.get(a2);
+ return info1.sameRack(info2);
+ }
+
+ public boolean isSameMachine(Address a1, Address a2) {
+ NodeTopologyInfo info1 = address2TopologyInfo.get(a1);
+ NodeTopologyInfo info2 = address2TopologyInfo.get(a2);
+ return info1.sameMachine(info2);
+ }
+}
Deleted: trunk/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java
===================================================================
--- branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,104 +0,0 @@
-package org.infinispan.distribution.ch;
-
-import org.infinispan.CacheException;
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.Immutables;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A delegating wrapper that locates keys by getting a union of locations reported by two other ConsistentHash
- * implementations it delegates to.
- *
- * @author Manik Surtani
- * @since 4.0
- */
- at Marshallable(externalizer = UnionConsistentHash.Externalizer.class, id = Ids.UNION_CONSISTENT_HASH)
-public class UnionConsistentHash extends AbstractConsistentHash {
-
- ConsistentHash oldCH, newCH;
-
- public UnionConsistentHash(ConsistentHash oldCH, ConsistentHash newCH) {
- if ((oldCH instanceof UnionConsistentHash) || (newCH instanceof UnionConsistentHash))
- throw new CacheException("Expecting both newCH and oldCH to not be Unions!! oldCH=[" + oldCH.getClass() + "] and newCH=[" + newCH.getClass() + "]");
- this.oldCH = oldCH;
- this.newCH = newCH;
- }
-
- public void setCaches(List<Address> caches) {
- // no op
- }
-
- public List<Address> getCaches() {
- return Collections.emptyList();
- }
-
- public List<Address> locate(Object key, int replCount) {
- Set<Address> addresses = new LinkedHashSet<Address>();
- addresses.addAll(oldCH.locate(key, replCount));
- addresses.addAll(newCH.locate(key, replCount));
- return Immutables.immutableListConvert(addresses);
- }
-
- @Override
- public int getHashId(Address a) {
- throw new UnsupportedOperationException("Unsupported!");
- }
-
- public List<Address> getStateProvidersOnLeave(Address leaver, int replCount) {
- throw new UnsupportedOperationException("Unsupported!");
- }
-
- public boolean isStateReceiverOnLeave(Address leaver, Address node, int replCount) {
- throw new UnsupportedOperationException("Unsupported!");
- }
-
- public List<Address> getStateProvidersOnJoin(Address joiner, int replCount) {
- throw new UnsupportedOperationException("Unsupported!");
- }
-
- @Override
- public int getHashSpace() {
- int oldHashSpace = oldCH.getHashSpace();
- int newHashSpace = newCH.getHashSpace();
- // In a union, the hash space is the biggest of the hash spaces.
- return oldHashSpace > newHashSpace ? oldHashSpace : newHashSpace;
- }
-
- public ConsistentHash getNewConsistentHash() {
- return newCH;
- }
-
- public ConsistentHash getOldConsistentHash() {
- return oldCH;
- }
-
- public static class Externalizer implements org.infinispan.marshall.Externalizer {
-
- public void writeObject(ObjectOutput output, Object object) throws IOException {
- UnionConsistentHash uch = (UnionConsistentHash) object;
- output.writeObject(uch.oldCH);
- output.writeObject(uch.newCH);
- }
-
- public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
- return new UnionConsistentHash((ConsistentHash) input.readObject(), (ConsistentHash) input.readObject());
- }
- }
-
- public ConsistentHash getOldCH() {
- return oldCH;
- }
-
- public ConsistentHash getNewCH() {
- return newCH;
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java (from rev 2621, branches/4.2.x/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/distribution/ch/UnionConsistentHash.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,104 @@
+package org.infinispan.distribution.ch;
+
+import org.infinispan.CacheException;
+import org.infinispan.marshall.Ids;
+import org.infinispan.marshall.Marshallable;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.util.Immutables;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A delegating wrapper that locates keys by getting a union of locations reported by two other ConsistentHash
+ * implementations it delegates to.
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+ at Marshallable(externalizer = UnionConsistentHash.Externalizer.class, id = Ids.UNION_CONSISTENT_HASH)
+public class UnionConsistentHash extends AbstractConsistentHash {
+
+ ConsistentHash oldCH, newCH;
+
+ public UnionConsistentHash(ConsistentHash oldCH, ConsistentHash newCH) {
+ if ((oldCH instanceof UnionConsistentHash) || (newCH instanceof UnionConsistentHash))
+ throw new CacheException("Expecting both newCH and oldCH to not be Unions!! oldCH=[" + oldCH.getClass() + "] and newCH=[" + newCH.getClass() + "]");
+ this.oldCH = oldCH;
+ this.newCH = newCH;
+ }
+
+ public void setCaches(List<Address> caches) {
+ // no op
+ }
+
+ public List<Address> getCaches() {
+ return Collections.emptyList();
+ }
+
+ public List<Address> locate(Object key, int replCount) {
+ Set<Address> addresses = new LinkedHashSet<Address>();
+ addresses.addAll(oldCH.locate(key, replCount));
+ addresses.addAll(newCH.locate(key, replCount));
+ return Immutables.immutableListConvert(addresses);
+ }
+
+ @Override
+ public int getHashId(Address a) {
+ throw new UnsupportedOperationException("Unsupported!");
+ }
+
+ public List<Address> getStateProvidersOnLeave(Address leaver, int replCount) {
+ throw new UnsupportedOperationException("Unsupported!");
+ }
+
+ public boolean isStateReceiverOnLeave(Address leaver, Address node, int replCount) {
+ throw new UnsupportedOperationException("Unsupported!");
+ }
+
+ public List<Address> getStateProvidersOnJoin(Address joiner, int replCount) {
+ throw new UnsupportedOperationException("Unsupported!");
+ }
+
+ @Override
+ public int getHashSpace() {
+ int oldHashSpace = oldCH.getHashSpace();
+ int newHashSpace = newCH.getHashSpace();
+ // In a union, the hash space is the biggest of the hash spaces.
+ return oldHashSpace > newHashSpace ? oldHashSpace : newHashSpace;
+ }
+
+ public ConsistentHash getNewConsistentHash() {
+ return newCH;
+ }
+
+ public ConsistentHash getOldConsistentHash() {
+ return oldCH;
+ }
+
+ public static class Externalizer implements org.infinispan.marshall.Externalizer {
+
+ public void writeObject(ObjectOutput output, Object object) throws IOException {
+ UnionConsistentHash uch = (UnionConsistentHash) object;
+ output.writeObject(uch.oldCH);
+ output.writeObject(uch.newCH);
+ }
+
+ public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
+ return new UnionConsistentHash((ConsistentHash) input.readObject(), (ConsistentHash) input.readObject());
+ }
+ }
+
+ public ConsistentHash getOldCH() {
+ return oldCH;
+ }
+
+ public ConsistentHash getNewCH() {
+ return newCH;
+ }
+}
Modified: trunk/core/src/main/java/org/infinispan/marshall/jboss/ConstantObjectTable.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/ConstantObjectTable.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/ConstantObjectTable.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -53,8 +53,8 @@
import org.infinispan.container.entries.TransientCacheValue;
import org.infinispan.container.entries.TransientMortalCacheEntry;
import org.infinispan.container.entries.TransientMortalCacheValue;
-import org.infinispan.distribution.DefaultConsistentHash;
-import org.infinispan.distribution.UnionConsistentHash;
+import org.infinispan.distribution.ch.DefaultConsistentHash;
+import org.infinispan.distribution.ch.UnionConsistentHash;
import org.infinispan.loaders.bucket.Bucket;
import org.infinispan.marshall.Externalizer;
import org.infinispan.marshall.Marshallable;
@@ -84,7 +84,6 @@
import org.jboss.marshalling.Marshaller;
import org.jboss.marshalling.ObjectTable;
import org.jboss.marshalling.Unmarshaller;
-import org.jboss.marshalling.river.RiverUnmarshaller;
import java.io.IOException;
import java.util.ArrayList;
Modified: trunk/core/src/test/java/org/infinispan/affinity/BaseKeyAffinityServiceTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/affinity/BaseKeyAffinityServiceTest.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/test/java/org/infinispan/affinity/BaseKeyAffinityServiceTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,7 +1,7 @@
package org.infinispan.affinity;
import org.infinispan.distribution.BaseDistFunctionalTest;
-import org.infinispan.distribution.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.manager.CacheContainer;
import org.infinispan.remoting.transport.Address;
import org.infinispan.test.TestingUtil;
Modified: trunk/core/src/test/java/org/infinispan/affinity/KeyAffinityServiceTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/affinity/KeyAffinityServiceTest.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/test/java/org/infinispan/affinity/KeyAffinityServiceTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,7 +1,7 @@
package org.infinispan.affinity;
import org.infinispan.Cache;
-import org.infinispan.distribution.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
import org.testng.annotations.Test;
Modified: trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,6 +1,5 @@
package org.infinispan.config.parsing;
-import org.infinispan.Cache;
import org.infinispan.Version;
import org.infinispan.config.CacheLoaderManagerConfig;
import org.infinispan.config.Configuration;
@@ -8,20 +7,17 @@
import org.infinispan.config.GlobalConfiguration;
import org.infinispan.config.GlobalConfiguration.ShutdownHookBehavior;
import org.infinispan.config.InfinispanConfiguration;
-import org.infinispan.distribution.DefaultConsistentHash;
+import org.infinispan.distribution.ch.DefaultConsistentHash;
import org.infinispan.eviction.EvictionStrategy;
import org.infinispan.eviction.EvictionThreadPolicy;
import org.infinispan.loaders.file.FileCacheStoreConfig;
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
import org.infinispan.test.AbstractInfinispanTest;
import org.infinispan.test.TestingUtil;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.infinispan.util.concurrent.IsolationLevel;
import org.testng.annotations.Test;
import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
Modified: trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -8,6 +8,10 @@
import org.infinispan.container.entries.ImmortalCacheEntry;
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.container.entries.MortalCacheEntry;
+import org.infinispan.distribution.ch.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHashHelper;
+import org.infinispan.distribution.ch.DefaultConsistentHash;
+import org.infinispan.distribution.ch.UnionConsistentHash;
import org.infinispan.manager.CacheContainer;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
Modified: trunk/core/src/test/java/org/infinispan/distribution/ConsistentHashPerfTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/ConsistentHashPerfTest.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/test/java/org/infinispan/distribution/ConsistentHashPerfTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,5 +1,6 @@
package org.infinispan.distribution;
+import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.remoting.transport.Address;
import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
import org.infinispan.test.TestingUtil;
Modified: trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -1,5 +1,6 @@
package org.infinispan.distribution;
+import org.infinispan.distribution.ch.DefaultConsistentHash;
import org.infinispan.remoting.transport.Address;
import org.infinispan.test.AbstractInfinispanTest;
import org.testng.annotations.AfterTest;
@@ -17,7 +18,7 @@
public class DefaultConsistentHashTest extends AbstractInfinispanTest {
List<Address> servers;
- ConsistentHash ch;
+ DefaultConsistentHash ch;
@BeforeTest
public void setUp() {
@@ -27,7 +28,7 @@
servers.add(new TestAddress(i));
}
- ch = BaseDistFunctionalTest.createNewConsistentHash(servers);
+ ch = (DefaultConsistentHash) BaseDistFunctionalTest.createNewConsistentHash(servers);
}
@AfterTest
@@ -82,7 +83,7 @@
Address a3 = new TestAddress(3000);
Address a4 = new TestAddress(4000);
- ch = BaseDistFunctionalTest.createNewConsistentHash(Arrays.asList(a1, a2, a3, a4));
+ ch = (DefaultConsistentHash) BaseDistFunctionalTest.createNewConsistentHash(Arrays.asList(a1, a2, a3, a4));
// the CH may reorder the addresses. Get the new order.
List<Address> adds = ch.getCaches();
@@ -109,7 +110,7 @@
Address a3 = new TestAddress(3000);
Address a4 = new TestAddress(4000);
- ch = BaseDistFunctionalTest.createNewConsistentHash(Arrays.asList(a1, a2, a3, a4));
+ ch = (DefaultConsistentHash) BaseDistFunctionalTest.createNewConsistentHash(Arrays.asList(a1, a2, a3, a4));
String[] keys = new String[10000];
Random r = new Random();
@@ -126,6 +127,12 @@
class TestAddress implements Address {
int addressNum;
+ String name;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
TestAddress(int addressNum) {
this.addressNum = addressNum;
}
@@ -157,7 +164,7 @@
@Override
public String toString() {
- return "TestAddress#"+addressNum;
+ return "TestAddress#"+addressNum + (name != null? (" " + name) : "");
}
public int compareTo(Object o) {
Copied: trunk/core/src/test/java/org/infinispan/distribution/DistributionManagerImplTest.java (from rev 2621, branches/4.2.x/core/src/test/java/org/infinispan/distribution/DistributionManagerImplTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DistributionManagerImplTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/distribution/DistributionManagerImplTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,85 @@
+package org.infinispan.distribution;
+
+import org.infinispan.config.Configuration;
+import org.infinispan.distribution.ch.DefaultConsistentHash;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.test.AbstractInfinispanTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test (groups = "functional", testName = "distribution.DistributionManagerImplTest")
+public class DistributionManagerImplTest extends AbstractInfinispanTest {
+ List<Address> servers;
+ DefaultConsistentHash ch;
+ Address a0;
+ Address a1;
+ Address a2;
+ Address a3;
+ Address a4;
+
+ @BeforeTest
+ public void setUp() {
+ servers = new LinkedList<Address>();
+ int numServers = 5;
+ for (int i = 0; i < numServers; i++) {
+ servers.add(new TestAddress(i));
+ }
+ ch = (DefaultConsistentHash) BaseDistFunctionalTest.createNewConsistentHash(servers);
+ a0 = ch.getAddressOnTheWheel().get(0);
+ a1 = ch.getAddressOnTheWheel().get(1);
+ a2 = ch.getAddressOnTheWheel().get(2);
+ a3 = ch.getAddressOnTheWheel().get(3);
+ a4 = ch.getAddressOnTheWheel().get(4);
+ }
+
+
+ /**
+ * numOwners = 3. Let's a a2 leaves.
+ */
+ public void testLeaver() {
+ DistributionManagerImpl dm = newDM(3);
+ dm.setSelf(a0);
+ assert dm.willReceiveLeaverState(a2) : " a0 will be the 2nd backup for a3's state";
+ dm.setSelf(a1);
+ assert !dm.willReceiveLeaverState(a2) : " a1 is not affected";
+ dm.setSelf(a3);
+ assert dm.willReceiveLeaverState(a2) : "this needs to receive state from a0";
+ dm.setSelf(a4);
+ assert dm.willReceiveLeaverState(a2) : "this needs to receive state from a1";
+ }
+
+ private DistributionManagerImpl newDM(int numOwners) {
+ DistributionManagerImpl dm = new DistributionManagerImpl();
+ Configuration configuration = new Configuration();
+ configuration.setNumOwners(numOwners);
+ dm.setConfiguration(configuration);
+ dm.setOldConsistentHash(ch);
+ return dm;
+ }
+
+
+ public void testHoldersOfLeaversState() {
+ DistributionManagerImpl dm = newDM(3);
+ dm.setSelf(a0);
+ List<Address> addressList = dm.holdersOfLeaversState(a2);
+ assert addressList.size() == 2;
+ assert addressList.contains(a1);
+ assert addressList.contains(a3);
+ }
+
+ public void testHoldersOfLeaversState2() {
+ DistributionManagerImpl dm = newDM(2);
+ dm.setSelf(a0);
+ List<Address> addressList = dm.holdersOfLeaversState(a1);
+ assert addressList.size() == 2;
+ assert addressList.contains(a0);
+ assert addressList.contains(a2);
+ }
+}
Copied: trunk/core/src/test/java/org/infinispan/distribution/TopologyAwareConsistentHashTest.java (from rev 2621, branches/4.2.x/core/src/test/java/org/infinispan/distribution/TopologyAwareConsistentHashTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/TopologyAwareConsistentHashTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/distribution/TopologyAwareConsistentHashTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -0,0 +1,528 @@
+package org.infinispan.distribution;
+
+import org.infinispan.distribution.ch.NodeTopologyInfo;
+import org.infinispan.distribution.ch.TopologyAwareConsistentHash;
+import org.infinispan.distribution.ch.TopologyInfo;
+
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test(groups = "functional", testName = "distribution.TopologyAwareConsistentHashTest")
+public class TopologyAwareConsistentHashTest {
+
+ private static Log log = LogFactory.getLog(TopologyAwareConsistentHashTest.class);
+
+ TopologyInfo ti;
+ TopologyAwareConsistentHash ch;
+ ArrayList<Address> addresses;
+ TestAddress a0;
+ TestAddress a1;
+ TestAddress a2;
+ TestAddress a3;
+ TestAddress a4;
+ TestAddress a5;
+ TestAddress a6;
+ TestAddress a7;
+ TestAddress a8;
+ TestAddress a9;
+ private TestAddress[] staticAddresses;
+
+
+ @BeforeMethod
+ public void setUp() {
+ ti = new TopologyInfo();
+ ch = new TopologyAwareConsistentHash();
+ addresses = new ArrayList<Address>();
+ for (int i = 0; i < 10; i++) {
+ addresses.add(new TestAddress(i * 100));
+ }
+ ch.setCaches(addresses);
+ addresses = new ArrayList(ch.getCaches());
+ for (int i = 0; i < addresses.size(); i++) {
+ TestingUtil.replaceField(addresses.get(i), "a"+i, this, TopologyAwareConsistentHashTest.class);
+ }
+
+ addresses.clear();
+ ch = new TopologyAwareConsistentHash();
+ ch.setTopologyInfo(ti);
+ }
+
+ public void testIsStateReceiverOnLeave() {
+ addNode(a0, "m0", null, null);
+ addNode(a1, "m1", null, null);
+ addNode(a2, "m0", null, null);
+ addNode(a3, "m1", null, null);
+ setAddresses();
+
+ assert !ch.isStateReceiverOnLeave(a0, a1, 2);
+ assert ch.isStateReceiverOnLeave(a0, a2, 2);
+ assert !ch.isStateReceiverOnLeave(a0, a1, 2);
+ }
+
+ public void testDifferentMachines() {
+ addNode(a0, "m0", null, null);
+ addNode(a1, "m1", null, null);
+ addNode(a2, "m0", null, null);
+ addNode(a3, "m1", null, null);
+ setAddresses();
+
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+
+ assertLocation(ch.getStateProvidersOnLeave(a0, 1), false);
+ assertLocation(ch.getStateProvidersOnLeave(a1, 1), false);
+ assertLocation(ch.getStateProvidersOnLeave(a2, 1), false);
+ assertLocation(ch.getStateProvidersOnLeave(a3, 1), false);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a1);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a3);
+ assertLocation(ch.locate(a3, 2), true, a3, a0);
+
+ assertLocation(ch.getStateProvidersOnLeave(a0, 2), false, a1, a3);
+ assertLocation(ch.getStateProvidersOnLeave(a1, 2), false, a0, a2);
+ assertLocation(ch.getStateProvidersOnLeave(a2, 2), false, a3, a1);
+ assertLocation(ch.getStateProvidersOnLeave(a3, 2), false, a0, a2);
+
+
+
+ assertLocation(ch.locate(a0, 3), true, a0, a1, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a0);
+ assertLocation(ch.locate(a2, 3), true, a2, a3, a1);
+ assertLocation(ch.locate(a3, 3), true, a3, a0, a2);
+
+ assertLocation(ch.getStateProvidersOnLeave(a0, 3), false, a1, a3);
+ assertLocation(ch.getStateProvidersOnLeave(a1, 3), false, a0, a2);
+ assertLocation(ch.getStateProvidersOnLeave(a2, 3), false, a3, a1);
+ assertLocation(ch.getStateProvidersOnLeave(a3, 3), false, a0, a2);
+ }
+
+ public void testDifferentMachines2() {
+ addNode(a0, "m0", null, null);
+ addNode(a1, "m0", null, null);
+ addNode(a2, "m1", null, null);
+ addNode(a3, "m1", null, null);
+ addNode(a4, "m2", null, null);
+ addNode(a5, "m2", null, null);
+ setAddresses();
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+ assertLocation(ch.locate(a4, 1), true, a4);
+ assertLocation(ch.locate(a5, 1), true, a5);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a2);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a4);
+ assertLocation(ch.locate(a3, 2), true, a3, a4);
+ assertLocation(ch.locate(a4, 2), true, a4, a0);
+ assertLocation(ch.locate(a5, 2), true, a5, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a2, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a4, a5);
+ assertLocation(ch.locate(a3, 3), true, a3, a4, a5);
+ assertLocation(ch.locate(a4, 3), true, a4, a0, a1);
+ assertLocation(ch.locate(a5, 3), true, a5, a0, a1);
+ }
+
+ public void testDifferentRacksAndMachines() {
+ addNode(a0, "m0", "r0", null);
+ addNode(a1, "m0", "r0", null);
+ addNode(a2, "m1", "r1", null);
+ addNode(a3, "m2", "r2", null);
+ addNode(a4, "m1", "r1", null);
+ addNode(a5, "m2", "r3", null);
+ setAddresses();
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+ assertLocation(ch.locate(a4, 1), true, a4);
+ assertLocation(ch.locate(a5, 1), true, a5);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a2);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a3);
+ assertLocation(ch.locate(a3, 2), true, a3, a4);
+ assertLocation(ch.locate(a4, 2), true, a4, a5);
+ assertLocation(ch.locate(a5, 2), true, a5, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a2, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a3, a5);
+ assertLocation(ch.locate(a3, 3), true, a3, a4, a5);
+ assertLocation(ch.locate(a4, 3), true, a4, a5, a0);
+ assertLocation(ch.locate(a5, 3), true, a5, a0, a1);
+ }
+
+ public void testAllSameMachine() {
+ addNode(a0, "m0", null, null);
+ addNode(a1, "m0", null, null);
+ addNode(a2, "m0", null, null);
+ addNode(a3, "m0", null, null);
+ addNode(a4, "m0", null, null);
+ addNode(a5, "m0", null, null);
+ setAddresses();
+
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+ assertLocation(ch.locate(a4, 1), true, a4);
+ assertLocation(ch.locate(a5, 1), true, a5);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a1);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a3);
+ assertLocation(ch.locate(a3, 2), true, a3, a4);
+ assertLocation(ch.locate(a4, 2), true, a4, a5);
+ assertLocation(ch.locate(a5, 2), true, a5, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a1, a2);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a3, a4);
+ assertLocation(ch.locate(a3, 3), true, a3, a4, a5);
+ assertLocation(ch.locate(a4, 3), true, a4, a5, a0);
+ assertLocation(ch.locate(a5, 3), true, a5, a0, a1);
+ }
+
+ public void testDifferentSites() {
+ addNode(a0, "m0", null, "s0");
+ addNode(a1, "m1", null, "s0");
+ addNode(a2, "m2", null, "s1");
+ addNode(a3, "m3", null, "s1");
+ setAddresses();
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a2);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a0);
+ assertLocation(ch.locate(a3, 2), true, a3, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a2, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a0, a1);
+ assertLocation(ch.locate(a3, 3), true, a3, a0, a1);
+ }
+
+ public void testSitesMachines2() {
+ addNode(a0, "m0", null, "s0");
+ addNode(a1, "m1", null, "s1");
+ addNode(a2, "m2", null, "s0");
+ addNode(a3, "m3", null, "s2");
+ addNode(a4, "m4", null, "s1");
+ addNode(a5, "m5", null, "s1");
+
+ setAddresses();
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+ assertLocation(ch.locate(a4, 1), true, a4);
+ assertLocation(ch.locate(a5, 1), true, a5);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a1);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a3);
+ assertLocation(ch.locate(a3, 2), true, a3, a4);
+ assertLocation(ch.locate(a4, 2), true, a4, a0);
+ assertLocation(ch.locate(a5, 2), true, a5, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a1, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a3, a4);
+ assertLocation(ch.locate(a3, 3), true, a3, a4, a5);
+ assertLocation(ch.locate(a4, 3), true, a4, a0, a2);
+ assertLocation(ch.locate(a5, 3), true, a5, a0, a2);
+ }
+
+ public void testSitesMachinesSameMachineName() {
+ addNode(a0, "m0", null, "r0");
+ addNode(a1, "m0", null, "r1");
+ addNode(a2, "m0", null, "r0");
+ addNode(a3, "m0", null, "r2");
+ addNode(a4, "m0", null, "r1");
+ addNode(a5, "m0", null, "r1");
+
+ setAddresses();
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+ assertLocation(ch.locate(a4, 1), true, a4);
+ assertLocation(ch.locate(a5, 1), true, a5);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a1);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a3);
+ assertLocation(ch.locate(a3, 2), true, a3, a4);
+ assertLocation(ch.locate(a4, 2), true, a4, a0);
+ assertLocation(ch.locate(a5, 2), true, a5, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a1, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a3, a4);
+ assertLocation(ch.locate(a3, 3), true, a3, a4, a5);
+ assertLocation(ch.locate(a4, 3), true, a4, a0, a2);
+ assertLocation(ch.locate(a5, 3), true, a5, a0, a2);
+ }
+
+ public void testDifferentRacks() {
+ addNode(a0, "m0", "r0", null);
+ addNode(a1, "m1", "r0", null);
+ addNode(a2, "m2", "r1", null);
+ addNode(a3, "m3", "r1", null);
+ setAddresses();
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a2);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a0);
+ assertLocation(ch.locate(a3, 2), true, a3, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a2, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a0, a1);
+ assertLocation(ch.locate(a3, 3), true, a3, a0, a1);
+ }
+
+ public void testRacksMachines2() {
+ addNode(a0, "m0", "r0", null);
+ addNode(a1, "m1", "r1", null);
+ addNode(a2, "m2", "r0", null);
+ addNode(a3, "m3", "r2", null);
+ addNode(a4, "m4", "r1", null);
+ addNode(a5, "m5", "r1", null);
+
+ setAddresses();
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+ assertLocation(ch.locate(a4, 1), true, a4);
+ assertLocation(ch.locate(a5, 1), true, a5);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a1);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a3);
+ assertLocation(ch.locate(a3, 2), true, a3, a4);
+ assertLocation(ch.locate(a4, 2), true, a4, a0);
+ assertLocation(ch.locate(a5, 2), true, a5, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a1, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a3, a4);
+ assertLocation(ch.locate(a3, 3), true, a3, a4, a5);
+ assertLocation(ch.locate(a4, 3), true, a4, a0, a2);
+ assertLocation(ch.locate(a5, 3), true, a5, a0, a2);
+ }
+
+ public void testRacksMachinesSameMachineName() {
+ addNode(a0, "m0", "r0", null);
+ addNode(a1, "m0", "r1", null);
+ addNode(a2, "m0", "r0", null);
+ addNode(a3, "m0", "r2", null);
+ addNode(a4, "m0", "r1", null);
+ addNode(a5, "m0", "r1", null);
+
+ setAddresses();
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+ assertLocation(ch.locate(a4, 1), true, a4);
+ assertLocation(ch.locate(a5, 1), true, a5);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a1);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a3);
+ assertLocation(ch.locate(a3, 2), true, a3, a4);
+ assertLocation(ch.locate(a4, 2), true, a4, a0);
+ assertLocation(ch.locate(a5, 2), true, a5, a0);
+
+ assertLocation(ch.locate(a0, 3), true, a0, a1, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a3);
+ assertLocation(ch.locate(a2, 3), true, a2, a3, a4);
+ assertLocation(ch.locate(a3, 3), true, a3, a4, a5);
+ assertLocation(ch.locate(a4, 3), true, a4, a0, a2);
+ assertLocation(ch.locate(a5, 3), true, a5, a0, a2);
+ }
+
+ public void testComplexScenario() {
+ addNode(a0, "m2", "r0", "s1");
+ addNode(a1, "m1", "r0", "s0");
+ addNode(a2, "m1", "r0", "s1");
+ addNode(a3, "m1", "r1", "s0");
+ addNode(a4, "m0", "r0", "s1");
+ addNode(a5, "m0", "r1", "s1");
+ addNode(a6, "m0", "r1", "s0");
+ addNode(a7, "m0", "r0", "s3");
+ addNode(a8, "m0", "r0", "s2");
+ addNode(a9, "m0", "r0", "s0");
+ setAddresses();
+
+ assertLocation(ch.locate(a0, 1), true, a0);
+ assertLocation(ch.locate(a1, 1), true, a1);
+ assertLocation(ch.locate(a2, 1), true, a2);
+ assertLocation(ch.locate(a3, 1), true, a3);
+ assertLocation(ch.locate(a4, 1), true, a4);
+ assertLocation(ch.locate(a5, 1), true, a5);
+ assertLocation(ch.locate(a6, 1), true, a6);
+ assertLocation(ch.locate(a7, 1), true, a7);
+ assertLocation(ch.locate(a8, 1), true, a8);
+ assertLocation(ch.locate(a9, 1), true, a9);
+
+ assertLocation(ch.locate(a0, 2), true, a0, a1);
+ assertLocation(ch.locate(a1, 2), true, a1, a2);
+ assertLocation(ch.locate(a2, 2), true, a2, a3);
+ assertLocation(ch.locate(a3, 2), true, a3, a4);
+ assertLocation(ch.locate(a4, 2), true, a4, a6);
+ assertLocation(ch.locate(a5, 2), true, a5, a6);
+ assertLocation(ch.locate(a6, 2), true, a6, a7);
+ assertLocation(ch.locate(a7, 2), true, a7, a8);
+ assertLocation(ch.locate(a8, 2), true, a8, a9);
+ assertLocation(ch.locate(a9, 2), true, a9, a0);
+
+
+ assertLocation(ch.getStateProvidersOnLeave(a0, 2), false, a1, a9);
+ assertLocation(ch.getStateProvidersOnLeave(a1, 2), false, a0, a2);
+ assertLocation(ch.getStateProvidersOnLeave(a2, 2), false, a3, a1);
+ assertLocation(ch.getStateProvidersOnLeave(a3, 2), false, a4, a2);
+ assertLocation(ch.getStateProvidersOnLeave(a4, 2), false, a6, a3);
+ assertLocation(ch.getStateProvidersOnLeave(a5, 2), false, a6);
+ assertLocation(ch.getStateProvidersOnLeave(a6, 2), false, a4, a7, a5);
+ assertLocation(ch.getStateProvidersOnLeave(a7, 2), false, a8, a6);
+ assertLocation(ch.getStateProvidersOnLeave(a8, 2), false, a9, a7);
+ assertLocation(ch.getStateProvidersOnLeave(a9, 2), false, a0, a8);
+
+ assertLocation(ch.getStateProvidersOnJoin(a0, 2), false, a1, a9);
+ assertLocation(ch.getStateProvidersOnJoin(a1, 2), false, a0, a2);
+ assertLocation(ch.getStateProvidersOnJoin(a2, 2), false, a3, a1);
+ assertLocation(ch.getStateProvidersOnJoin(a3, 2), false, a4, a2);
+ assertLocation(ch.getStateProvidersOnJoin(a4, 2), false, a6, a3);
+ assertLocation(ch.getStateProvidersOnJoin(a5, 2), false, a6);
+ assertLocation(ch.getStateProvidersOnJoin(a6, 2), false, a4, a7, a5);
+ assertLocation(ch.getStateProvidersOnJoin(a7, 2), false, a8, a6);
+ assertLocation(ch.getStateProvidersOnJoin(a8, 2), false, a9, a7);
+ assertLocation(ch.getStateProvidersOnJoin(a9, 2), false, a0, a8);
+
+
+ assertLocation(ch.locate(a0, 3), true, a0, a1, a3);
+ assertLocation(ch.locate(a1, 3), true, a1, a2, a4);
+ assertLocation(ch.locate(a2, 3), true, a2, a3, a6);
+ assertLocation(ch.locate(a3, 3), true, a3, a4, a5);
+ assertLocation(ch.locate(a4, 3), true, a4, a6, a7);
+ assertLocation(ch.locate(a5, 3), true, a5, a6, a7);
+ assertLocation(ch.locate(a6, 3), true, a6, a7, a8);
+ assertLocation(ch.locate(a7, 3), true, a7, a8, a9);
+ assertLocation(ch.locate(a8, 3), true, a8, a9, a0);
+ assertLocation(ch.locate(a9, 3), true, a9, a0, a2);
+ }
+
+ public void testConsistencyWhenNodeLeaves() {
+ addNode(a0, "m2", "r0", "s1");
+ addNode(a1, "m1", "r0", "s0");
+ addNode(a2, "m1", "r0", "s1");
+ addNode(a3, "m1", "r1", "s0");
+ addNode(a4, "m0", "r0", "s1");
+ addNode(a5, "m0", "r1", "s1");
+ addNode(a6, "m0", "r1", "s0");
+ addNode(a7, "m0", "r0", "s3");
+ addNode(a8, "m0", "r0", "s2");
+ addNode(a9, "m0", "r0", "s0");
+ setAddresses();
+
+ List<Address> a0List = ch.locate(a0, 3);
+ List<Address> a1List = ch.locate(a1, 3);
+ List<Address> a2List = ch.locate(a2, 3);
+ List<Address> a3List = ch.locate(a3, 3);
+ List<Address> a4List = ch.locate(a4, 3);
+ List<Address> a5List = ch.locate(a5, 3);
+ List<Address> a6List = ch.locate(a6, 3);
+ List<Address> a7List = ch.locate(a7, 3);
+ List<Address> a8List = ch.locate(a8, 3);
+ List<Address> a9List = ch.locate(a9, 3);
+
+ for (Address addr: addresses) {
+ System.out.println("addr = " + addr);
+ List<Address> addressCopy = (List<Address>) addresses.clone();
+ addressCopy.remove(addr);
+ ch.setCaches(addressCopy);
+ checkConsistency(a0List, a0, addr, 3);
+ checkConsistency(a1List, a1, addr, 3);
+ checkConsistency(a2List, a2, addr, 3);
+ checkConsistency(a3List, a3, addr, 3);
+ checkConsistency(a4List, a4, addr, 3);
+ checkConsistency(a5List, a5, addr, 3);
+ checkConsistency(a6List, a6, addr, 3);
+ checkConsistency(a7List, a7, addr, 3);
+ checkConsistency(a8List, a8, addr, 3);
+ checkConsistency(a9List, a9, addr, 3);
+ }
+ }
+
+ private void checkConsistency(List<Address> a0List, TestAddress a0, Address addr, int replCount) {
+ a0List = new ArrayList(a0List);
+ a0List.remove(addr);
+ if (a0.equals(addr)) return;
+ List<Address> currentBackupList = ch.locate(a0, replCount);
+ assertEquals(replCount, currentBackupList.size(), currentBackupList.toString());
+ assert currentBackupList.containsAll(a0List) : "Current backups are: " + currentBackupList + "Previous: " + a0List;
+ }
+
+
+ private void assertLocation(List<Address> received, boolean enforceSequence, TestAddress... expected) {
+ if (expected == null) {
+ assert received.isEmpty();
+ }
+ assertEquals(expected.length, received.size());
+ if (enforceSequence) {
+ assert received.equals(Arrays.asList(expected)) : "Received: " + received + " Expected: " + Arrays.toString(expected);
+ } else {
+ assert received.containsAll(Arrays.asList(expected)) : "Received: " + received + " Expected: " + Arrays.toString(expected);
+ }
+ }
+
+ private void addNode(TestAddress address, String machineId, String rackId, String siteId) {
+ addresses.add(address);
+ NodeTopologyInfo nti = new NodeTopologyInfo(machineId, rackId, siteId);
+ ti.addNodeTopologyInfo(address, nti);
+ }
+
+ private void setAddresses() {
+ ch.setCaches(addresses);
+ staticAddresses = new TestAddress[]{a0, a1, a2, a3, a4, a5, a6, a7, a8, a9};
+ for (int i = 0; i < staticAddresses.length; i++) {
+ if (staticAddresses[i] != null) staticAddresses[i].setName("a" + i);
+ }
+ log.info("Static addresses: " + Arrays.toString(staticAddresses));
+ }
+
+ public TestAddress address(int hashCode) {
+ return new TestAddress(hashCode);
+ }
+}
Modified: trunk/core/src/test/java/org/infinispan/distribution/rehash/RehashTestBase.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/rehash/RehashTestBase.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/test/java/org/infinispan/distribution/rehash/RehashTestBase.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -44,7 +44,7 @@
TestingUtil.sleepThread(1000);
}
- private List<MagicKey> init() {
+ protected List<MagicKey> init() {
List<MagicKey> keys = new ArrayList<MagicKey>(Arrays.asList(
new MagicKey(c1, "k1"), new MagicKey(c2, "k2"),
new MagicKey(c3, "k3"), new MagicKey(c4, "k4")
Modified: trunk/core/src/test/java/org/infinispan/distribution/rehash/WorkDuringJoinTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/rehash/WorkDuringJoinTest.java 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/core/src/test/java/org/infinispan/distribution/rehash/WorkDuringJoinTest.java 2010-10-27 21:00:52 UTC (rev 2622)
@@ -2,8 +2,8 @@
import org.infinispan.Cache;
import org.infinispan.distribution.BaseDistFunctionalTest;
-import org.infinispan.distribution.ConsistentHash;
-import org.infinispan.distribution.ConsistentHashHelper;
+import org.infinispan.distribution.ch.ConsistentHash;
+import org.infinispan.distribution.ch.ConsistentHashHelper;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
import org.testng.annotations.Test;
Modified: trunk/server/hotrod/src/test/scala/org/infinispan/server/hotrod/HotRodDistributionTest.scala
===================================================================
--- trunk/server/hotrod/src/test/scala/org/infinispan/server/hotrod/HotRodDistributionTest.scala 2010-10-27 20:44:10 UTC (rev 2621)
+++ trunk/server/hotrod/src/test/scala/org/infinispan/server/hotrod/HotRodDistributionTest.scala 2010-10-27 21:00:52 UTC (rev 2622)
@@ -9,7 +9,7 @@
import test.HotRodTestingUtil._
import org.testng.Assert._
import org.infinispan.test.TestingUtil
-import org.infinispan.distribution.UnionConsistentHash
+import org.infinispan.distribution.ch.UnionConsistentHash
import collection.mutable.ListBuffer
import org.infinispan.test.AbstractCacheTest._ // Do not remove, otherwise getDefaultClusteredConfig is not found
More information about the infinispan-commits
mailing list