/* * Copyright 2011 Red Hat, Inc. and/or its affiliates. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ package org.infinispan.configuration.cache; import org.infinispan.commons.hash.Hash; import org.infinispan.commons.hash.MurmurHash3; import org.infinispan.config.ConfigurationException; import org.infinispan.distribution.ch.ConsistentHash; /** * Allows fine-tuning of rehashing characteristics. Must only used with 'distributed' cache mode. * * @author pmuir * */ public class HashConfigurationBuilder extends AbstractClusteringConfigurationChildBuilder<HashConfiguration> { private ConsistentHash consistentHash; private Hash hash = new MurmurHash3(); private int numOwners = 2; // See VNodesKeyDistributionTest for an explanation of how we came up with the number of nodes private int numVirtualNodes = 48; private boolean activated = false; private final GroupsConfigurationBuilder groupsConfigurationBuilder; HashConfigurationBuilder(ClusteringConfigurationBuilder builder) { super(builder); this.groupsConfigurationBuilder = new GroupsConfigurationBuilder(builder); } /** * The consistent hash in use. * * NOTE: Currently Infinispan will not use the object instance, but instead instantiate a new * instance of the class. Therefore, do not expect any state to survive, and provide a no-args * constructor to any instance. This will be resolved in Infinispan 5.2.0 */ public HashConfigurationBuilder consistentHash(ConsistentHash consistentHash) { this.consistentHash = consistentHash; activated = true; return this; } /** * Number of cluster-wide replicas for each cache entry. */ public HashConfigurationBuilder numOwners(int numOwners) { if (numOwners < 1) throw new IllegalArgumentException("numOwners cannot be less than 1"); this.numOwners = numOwners; activated = true; return this; } /** * <p> * Controls the number of virtual nodes per "real" node. You can read more about virtual nodes in Infinispan's * <a href="https://docs.jboss.org/author/display/ISPN51">online user guide</a>. * </p> * * <p> * If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash * must be used if you wish to take advnatage of virtual nodes. * </p> * * <p> * A default of 1 is used. * </p> * * @param numVirtualNodes the number of virtual nodes. Must be > 0. * @throws IllegalArgumentException if numVirtualNodes < 1 */ public HashConfigurationBuilder numVirtualNodes(int numVirtualNodes) { if (numVirtualNodes < 1) throw new IllegalArgumentException("numVirtualNodes cannot be less than 1"); this.numVirtualNodes = numVirtualNodes; activated = true; return this; } /** * Enable rebalancing and rehashing, which will take place when a new node joins the cluster or a * node leaves * @deprecated Use {@link StateTransferConfigurationBuilder#fetchInMemoryState(boolean)} instead. */ @Deprecated public HashConfigurationBuilder rehashEnabled() { stateTransfer().fetchInMemoryState(true); activated = true; return this; } /** * Enable rebalancing and rehashing, which will take place when a new node joins the cluster or a * node leaves * @deprecated Use {@link StateTransferConfigurationBuilder#fetchInMemoryState(boolean)} instead. */ @Deprecated public HashConfigurationBuilder rehashEnabled(boolean enabled) { stateTransfer().fetchInMemoryState(enabled); return this; } /** * Disable rebalancing and rehashing, which would have taken place when a new node joins the * cluster or a node leaves * @deprecated Use {@link StateTransferConfigurationBuilder#fetchInMemoryState(boolean)} instead. */ @Deprecated public HashConfigurationBuilder rehashDisabled() { stateTransfer().fetchInMemoryState(false); return this; } /** * Rehashing timeout * @deprecated Use {@link StateTransferConfigurationBuilder#timeout(long)} instead. */ @Deprecated public HashConfigurationBuilder rehashRpcTimeout(long rehashRpcTimeout) { stateTransfer().timeout(rehashRpcTimeout); return this; } /** * @deprecated No longer used. */ @Deprecated public HashConfigurationBuilder rehashWait(long rehashWait) { return this; } /** * The hash function in use. Used as a bit spreader and a general hash code generator. Typically * used in conjunction with the many default * {@link org.infinispan.distribution.ch.ConsistentHash} implementations shipped. * * NOTE: Currently Infinispan will not use the object instance, but instead instantiate a new * instance of the class. Therefore, do not expect any state to survive, and provide a no-args * constructor to any instance. This will be resolved in Infinispan 5.2.0 */ public HashConfigurationBuilder hash(Hash hash) { this.hash = hash; activated = true; return this; } public GroupsConfigurationBuilder groups() { activated = true; return groupsConfigurationBuilder; } @Override void validate() { if (activated && !clustering().cacheMode().isDistributed()) throw new ConfigurationException("Configuring the hashing behavior of entries is only supported when using DISTRIBUTED as a cache mode. Your cache mode is set to " + clustering().cacheMode().friendlyCacheModeString()); groupsConfigurationBuilder.validate(); } @Override HashConfiguration create() { // TODO stateTransfer().create() will create a duplicate StateTransferConfiguration instance. That's ok as long as none of the stateTransfer settings are modifiable at runtime. return new HashConfiguration(consistentHash, hash, numOwners, numVirtualNodes, groupsConfigurationBuilder.create(), stateTransfer().create(), activated); } @Override public HashConfigurationBuilder read(HashConfiguration template) { this.consistentHash = template.consistentHash(); this.hash = template.hash(); this.numOwners = template.numOwners(); this.numVirtualNodes = template.numVirtualNodes(); this.activated = template.activated; this.groupsConfigurationBuilder.read(template.groups()); return this; } @Override public String toString() { return "HashConfigurationBuilder{" + "activated=" + activated + ", consistentHash=" + consistentHash + ", hash=" + hash + ", numOwners=" + numOwners + ", numVirtualNodes=" + numVirtualNodes + ", groups=" + groupsConfigurationBuilder + '}'; } }