All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.distribution.LocalizedCacheTopology Maven / Gradle / Ivy

There is a newer version: 15.1.0.Dev04
Show newest version
package org.infinispan.distribution;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.infinispan.commons.hash.MurmurHash3;
import org.infinispan.commons.util.Immutables;
import org.infinispan.commons.util.SmallIntSet;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.distribution.ch.KeyPartitioner;
import org.infinispan.distribution.ch.impl.ReplicatedConsistentHash;
import org.infinispan.remoting.transport.Address;
import org.infinispan.topology.CacheTopology;

/**
 * Extends {@link CacheTopology} with information about keys owned by the local node.
 *
 * @author Dan Berindei
 * @since 9.0
 */
public class LocalizedCacheTopology extends CacheTopology {

   private final Address localAddress;
   private final KeyPartitioner keyPartitioner;
   private final boolean isDistributed;
   private final boolean allLocal;
   private final boolean isSegmented;
   private final int numSegments;
   private final int maxOwners;
   private final DistributionInfo[] distributionInfos;
   private final boolean isScattered;

   public static LocalizedCacheTopology makeSingletonTopology(CacheMode cacheMode, Address localAddress) {
      List
members = Collections.singletonList(localAddress); ConsistentHash ch = new ReplicatedConsistentHash(MurmurHash3.getInstance(), members, new int[]{0}); CacheTopology cacheTopology = new CacheTopology(0, 0, ch, null, Phase.NO_REBALANCE, members, null); return new LocalizedCacheTopology(cacheMode, cacheTopology, key -> 0, localAddress); } public LocalizedCacheTopology(CacheMode cacheMode, CacheTopology cacheTopology, KeyPartitioner keyPartitioner, Address localAddress) { super(cacheTopology.getTopologyId(), cacheTopology.getRebalanceId(), cacheTopology.getCurrentCH(), cacheTopology.getPendingCH(), cacheTopology.getUnionCH(), cacheTopology.getPhase(), cacheTopology.getActualMembers(), cacheTopology.getMembersPersistentUUIDs()); ConsistentHash readCH = getReadConsistentHash(); ConsistentHash writeCH = getWriteConsistentHash(); this.localAddress = localAddress; this.keyPartitioner = keyPartitioner; this.isDistributed = cacheMode.isDistributed(); isScattered = cacheMode.isScattered(); boolean isReplicated = cacheMode.isReplicated(); this.isSegmented = isDistributed || isReplicated || isScattered; this.numSegments = readCH.getNumSegments(); if (isDistributed || isScattered) { this.distributionInfos = new DistributionInfo[numSegments]; int maxOwners = 1; for (int segmentId = 0; segmentId < numSegments; segmentId++) { Address primary = readCH.locatePrimaryOwnerForSegment(segmentId); List
readOwners = readCH.locateOwnersForSegment(segmentId); List
writeOwners = writeCH.locateOwnersForSegment(segmentId); Collection
writeBackups = isScattered ? Collections.emptyList() : writeOwners.subList(1, writeOwners.size()); this.distributionInfos[segmentId] = new DistributionInfo(segmentId, primary, readOwners, writeOwners, writeBackups, localAddress); maxOwners = Math.max(maxOwners, writeOwners.size()); } this.maxOwners = maxOwners; this.allLocal = false; } else if (isReplicated) { // Writes must be broadcast to the entire cluster Map> readOwnersMap = new HashMap<>(); Map> writeOwnersMap = new HashMap<>(); this.distributionInfos = new DistributionInfo[numSegments]; for (int segmentId = 0; segmentId < numSegments; segmentId++) { int segmentCopy = segmentId; Address primary = readCH.locatePrimaryOwnerForSegment(segmentId); List
readOwners = readOwnersMap.computeIfAbsent(primary, p -> Immutables.immutableListCopy(readCH.locateOwnersForSegment(segmentCopy))); List
writeOwners = writeOwnersMap.computeIfAbsent(primary, p -> Immutables.immutableListCopy(writeCH.locateOwnersForSegment(segmentCopy))); List
writeBackups = writeOwners.subList(1, writeOwners.size()); this.distributionInfos[segmentId] = new DistributionInfo(segmentId, primary, readOwners, writeOwners, writeBackups, localAddress); } this.maxOwners = cacheTopology.getMembers().size(); this.allLocal = readOwnersMap.containsKey(localAddress); } else { // Invalidation/Local assert cacheMode.isInvalidation() || cacheMode == CacheMode.LOCAL; // Reads and writes are local, only the invalidation is replicated List
owners = Collections.singletonList(localAddress); List
writeBackups = Collections.emptyList(); this.distributionInfos = new DistributionInfo[]{ new DistributionInfo(0, localAddress, owners, owners, writeBackups, localAddress) }; this.maxOwners = 1; this.allLocal = true; } } /** * @return {@code true} iff key {@code key} can be read without going remote. */ public boolean isReadOwner(Object key) { if (allLocal) return true; int segmentId = keyPartitioner.getSegment(key); return distributionInfos[segmentId].isReadOwner(); } /** * @return {@code true} iff writing a value for key {@code key} will update it on the local node. */ public boolean isWriteOwner(Object key) { if (allLocal) return true; int segmentId = keyPartitioner.getSegment(key); return distributionInfos[segmentId].isWriteOwner(); } /** * @return The consistent hash segment of key {@code key} */ public int getSegment(Object key) { return keyPartitioner.getSegment(key); } /** * @return Information about the ownership of segment {@code segment}, including the primary owner. */ public DistributionInfo getDistributionForSegment(int segmentId) { return distributionInfos[segmentId]; } /** * @return Information about the ownership of key {@code key}, including the primary owner. */ public DistributionInfo getDistribution(Object key) { int segmentId = isSegmented ? keyPartitioner.getSegment(key) : 0; return distributionInfos[segmentId]; } /** * @return An unordered collection with the write owners of {@code key}. */ public Collection
getWriteOwners(Object key) { int segmentId = isDistributed || isScattered ? keyPartitioner.getSegment(key) : 0; return distributionInfos[segmentId].writeOwners(); } /** * @return An unordered collection with the write owners of {@code keys}. */ public Collection
getWriteOwners(Collection keys) { if (keys.isEmpty()) { return Collections.emptySet(); } if (isDistributed || isScattered) { if (keys.size() == 1) { Object singleKey = keys.iterator().next(); return getDistribution(singleKey).writeOwners(); } else { SmallIntSet segments = new SmallIntSet(numSegments); // Expecting some overlap between keys Set
owners = new HashSet<>(2 * maxOwners); for (Object key : keys) { int segment = keyPartitioner.getSegment(key); if (segments.add(segment)) { owners.addAll(getDistributionForSegment(segment).writeOwners()); } } return owners; } } else { return getDistributionForSegment(0).writeOwners(); } } /** * @return The address of the local node. */ public Address getLocalAddress() { return localAddress; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy