package org.infinispan.distribution.ch.impl;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.infinispan.commons.hash.Hash;
import org.infinispan.commons.marshall.AbstractExternalizer;
import org.infinispan.distribution.ch.ConsistentHashFactory;
import org.infinispan.globalstate.ScopedPersistentState;
import org.infinispan.marshall.core.Ids;
import org.infinispan.remoting.transport.Address;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
/**
* {@link SyncConsistentHashFactory} adapted for replicated caches, so that the primary owner of a key
* is the same in replicated and distributed caches.
*
* @author Dan Berindei
* @since 8.2
*/
public class SyncReplicatedConsistentHashFactory implements ConsistentHashFactory<ReplicatedConsistentHash> {
private static final Log log = LogFactory.getLog(SyncReplicatedConsistentHashFactory.class);
public static final float OWNED_SEGMENTS_ALLOWED_VARIATION = 1.10f;
public static final float PRIMARY_SEGMENTS_ALLOWED_VARIATION = 1.20f;
private static final SyncConsistentHashFactory syncCHF = new SyncConsistentHashFactory();
@Override
public ReplicatedConsistentHash create(Hash hashFunction, int numOwners, int numSegments,
List<Address> members, Map<Address, Float> capacityFactors) {
DefaultConsistentHash dch = syncCHF.create(hashFunction, 1, numSegments, members, null);
return replicatedFromDefault(dch);
}
@Override
public ReplicatedConsistentHash fromPersistentState(ScopedPersistentState state) {
String consistentHashClass = state.getProperty("consistentHash");
if (!ReplicatedConsistentHash.class.getName().equals(consistentHashClass))
throw log.persistentConsistentHashMismatch(this.getClass().getName(), consistentHashClass);
return new ReplicatedConsistentHash(state);
}
private ReplicatedConsistentHash replicatedFromDefault(DefaultConsistentHash dch) {
int numSegments = dch.getNumSegments();
List<Address> members = dch.getMembers();
int[] primaryOwners = new int[numSegments];
for (int segment = 0; segment < numSegments; segment++) {
primaryOwners[segment] = members.indexOf(dch.locatePrimaryOwnerForSegment(segment));
}
return new ReplicatedConsistentHash(dch.getHashFunction(), members, primaryOwners);
}
@Override
public ReplicatedConsistentHash updateMembers(ReplicatedConsistentHash baseCH, List<Address> newMembers,
Map<Address, Float> actualCapacityFactors) {
DefaultConsistentHash baseDCH = defaultFromReplicated(baseCH);
DefaultConsistentHash dch = syncCHF.updateMembers(baseDCH, newMembers, null);
return replicatedFromDefault(dch);
}
private DefaultConsistentHash defaultFromReplicated(ReplicatedConsistentHash baseCH) {
int numSegments = baseCH.getNumSegments();
List<Address>[] baseSegmentOwners = new List[numSegments];
for (int segment = 0; segment < numSegments; segment++) {
baseSegmentOwners[segment] = Collections.singletonList(baseCH.locatePrimaryOwnerForSegment(segment));
}
return new DefaultConsistentHash(baseCH.getHashFunction(), 1,
numSegments, baseCH.getMembers(), null, baseSegmentOwners);
}
@Override
public ReplicatedConsistentHash rebalance(ReplicatedConsistentHash baseCH) {
DefaultConsistentHash baseDCH = defaultFromReplicated(baseCH);
DefaultConsistentHash dch = syncCHF.rebalance(baseDCH);
return replicatedFromDefault(dch);
}
@Override
public ReplicatedConsistentHash union(ReplicatedConsistentHash ch1, ReplicatedConsistentHash ch2) {
return ch1.union(ch2);
}
public static class Externalizer extends AbstractExternalizer<SyncReplicatedConsistentHashFactory> {
@Override
public void writeObject(ObjectOutput output, SyncReplicatedConsistentHashFactory chf) {
}
@Override
@SuppressWarnings("unchecked")
public SyncReplicatedConsistentHashFactory readObject(ObjectInput unmarshaller) {
return new SyncReplicatedConsistentHashFactory();
}
@Override
public Integer getId() {
return Ids.SYNC_REPLICATED_CONSISTENT_HASH_FACTORY;
}
@Override
public Set<Class<? extends SyncReplicatedConsistentHashFactory>> getTypeClasses() {
return Collections.<Class<? extends SyncReplicatedConsistentHashFactory>>singleton(
SyncReplicatedConsistentHashFactory.class);
}
}
}