Search in sources :

Example 1 with CacheJoinInfo

use of org.infinispan.topology.CacheJoinInfo in project infinispan by infinispan.

the class StateTransferManagerImpl method start.

@Start(priority = 60)
@Override
public void start() throws Exception {
    if (log.isTraceEnabled()) {
        log.tracef("Starting StateTransferManager of cache %s on node %s", cacheName, rpcManager.getAddress());
    }
    Optional<Integer> persistentStateChecksum;
    if (globalStateManager != null) {
        persistentStateChecksum = globalStateManager.readScopedState(cacheName).map(ScopedPersistentState::getChecksum);
    } else {
        persistentStateChecksum = Optional.empty();
    }
    float capacityFactor = globalConfiguration.isZeroCapacityNode() && !CONFIG_STATE_CACHE_NAME.equals(cacheName) ? 0.0f : configuration.clustering().hash().capacityFactor();
    CacheJoinInfo joinInfo = new CacheJoinInfo(pickConsistentHashFactory(globalConfiguration, configuration), configuration.clustering().hash().numSegments(), configuration.clustering().hash().numOwners(), configuration.clustering().stateTransfer().timeout(), configuration.clustering().cacheMode(), capacityFactor, localTopologyManager.getPersistentUUID(), persistentStateChecksum);
    CompletionStage<CacheTopology> stage = localTopologyManager.join(cacheName, joinInfo, new CacheTopologyHandler() {

        @Override
        public CompletionStage<Void> updateConsistentHash(CacheTopology cacheTopology) {
            return doTopologyUpdate(cacheTopology, false);
        }

        @Override
        public CompletionStage<Void> rebalance(CacheTopology cacheTopology) {
            return doTopologyUpdate(cacheTopology, true);
        }
    }, partitionHandlingManager);
    CacheTopology initialTopology = CompletionStages.join(stage);
    if (log.isTraceEnabled()) {
        log.tracef("StateTransferManager of cache %s on node %s received initial topology %s", cacheName, rpcManager.getAddress(), initialTopology);
    }
}
Also used : CacheJoinInfo(org.infinispan.topology.CacheJoinInfo) CacheTopology(org.infinispan.topology.CacheTopology) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) CacheTopologyHandler(org.infinispan.topology.CacheTopologyHandler) CompletionStage(java.util.concurrent.CompletionStage) Start(org.infinispan.factories.annotations.Start)

Example 2 with CacheJoinInfo

use of org.infinispan.topology.CacheJoinInfo in project infinispan by infinispan.

the class PreferConsistencyStrategy method onPartitionMerge.

@Override
public void onPartitionMerge(AvailabilityStrategyContext context, Map<Address, CacheStatusResponse> statusResponseMap) {
    // Because of the majority check in onAbruptLeave, we assume that at most one partition was able to evolve
    // and install new cache topologies. The other(s) would have entered degraded mode, and they would keep
    // the original topology.
    int maxTopologyId = 0;
    int maxRebalanceId = 0;
    CacheTopology maxStableTopology = null;
    CacheTopology maxActiveTopology = null;
    Set<CacheTopology> degradedTopologies = new HashSet<>();
    CacheTopology maxDegradedTopology = null;
    CacheJoinInfo joinInfo = null;
    for (CacheStatusResponse response : statusResponseMap.values()) {
        CacheTopology partitionStableTopology = response.getStableTopology();
        if (partitionStableTopology == null) {
            // The node hasn't properly joined yet.
            continue;
        }
        if (maxStableTopology == null || maxStableTopology.getTopologyId() < partitionStableTopology.getTopologyId()) {
            maxStableTopology = partitionStableTopology;
            joinInfo = response.getCacheJoinInfo();
        }
        CacheTopology partitionTopology = response.getCacheTopology();
        if (partitionTopology == null) {
            // The node hasn't properly joined yet.
            continue;
        }
        if (partitionTopology.getTopologyId() > maxTopologyId) {
            maxTopologyId = partitionTopology.getTopologyId();
        }
        if (partitionTopology.getRebalanceId() > maxRebalanceId) {
            maxRebalanceId = partitionTopology.getRebalanceId();
        }
        if (response.getAvailabilityMode() == AvailabilityMode.AVAILABLE) {
            if (maxActiveTopology == null || maxActiveTopology.getTopologyId() < partitionTopology.getTopologyId()) {
                maxActiveTopology = partitionTopology;
            }
        } else if (response.getAvailabilityMode() == AvailabilityMode.DEGRADED_MODE) {
            degradedTopologies.add(partitionTopology);
            if (maxDegradedTopology == null || maxDegradedTopology.getTopologyId() < partitionTopology.getTopologyId()) {
                maxDegradedTopology = partitionTopology;
            }
        } else {
            eventLogManager.getEventLogger().context(context.getCacheName()).error(EventLogCategory.CLUSTER, MESSAGES.unexpectedAvailabilityMode(context.getAvailabilityMode(), response.getCacheTopology()));
        }
    }
    if (maxStableTopology != null) {
        log.tracef("Max stable partition topology: %s", maxStableTopology);
    }
    if (maxActiveTopology != null) {
        log.tracef("Max active partition topology: %s", maxActiveTopology);
    }
    if (maxDegradedTopology != null) {
        log.tracef("Max degraded partition topology: %s, all degraded: %s", maxDegradedTopology, degradedTopologies);
    }
    List<Address> expectedMembers = context.getExpectedMembers();
    List<Address> actualMembers = new ArrayList<>(expectedMembers);
    CacheTopology mergedTopology;
    AvailabilityMode mergedAvailabilityMode;
    if (maxActiveTopology != null) {
        log.debugf("One of the partitions is available, using that partition's topology");
        mergedTopology = maxActiveTopology;
        mergedAvailabilityMode = AvailabilityMode.AVAILABLE;
    } else if (!degradedTopologies.isEmpty()) {
        log.debugf("No active partitions, so all the partitions must be in degraded mode.");
        // Once a partition enters degraded mode its CH won't change, but it could be that a partition managed to
        // rebalance before losing another member and entering degraded mode.
        mergedTopology = maxDegradedTopology;
        if (maxStableTopology != null) {
            actualMembers.retainAll(maxStableTopology.getMembers());
        } else {
            actualMembers.retainAll(mergedTopology.getMembers());
        }
        mergedAvailabilityMode = AvailabilityMode.DEGRADED_MODE;
    } else {
        log.debugf("No current topology, recovered only joiners for cache %s. Skipping availability update.", context.getCacheName());
        return;
    }
    // Increment the topology id so that it's bigger than any topology that might have been sent by the old
    // coordinator.
    // +1 is enough because nodes wait for the new JGroups view before answering the
    // status request, and then they can't process topology updates from the old view.
    // Also cancel any pending rebalance by removing the pending CH, because we don't recover the rebalance
    // confirmation status (yet).
    AvailabilityMode newAvailabilityMode = computeAvailabilityAfterMerge(context, maxStableTopology, actualMembers);
    if (mergedTopology != null) {
        boolean resolveConflicts = context.resolveConflictsOnMerge() && actualMembers.size() > 1 && newAvailabilityMode == AvailabilityMode.AVAILABLE;
        if (resolveConflicts) {
            // Record all distinct read owners and hashes
            Set<ConsistentHash> distinctHashes = new HashSet<>();
            for (CacheStatusResponse response : statusResponseMap.values()) {
                CacheTopology cacheTopology = response.getCacheTopology();
                if (cacheTopology != null) {
                    ConsistentHash readCH = ownersConsistentHash(cacheTopology, joinInfo.getConsistentHashFactory());
                    if (readCH != null && !readCH.getMembers().isEmpty()) {
                        distinctHashes.add(readCH);
                    }
                }
            }
            ConsistentHash preferredHash = ownersConsistentHash(mergedTopology, joinInfo.getConsistentHashFactory());
            ConsistentHash conflictHash = context.calculateConflictHash(preferredHash, distinctHashes, expectedMembers);
            mergedTopology = new CacheTopology(++maxTopologyId, maxRebalanceId + 1, conflictHash, null, CacheTopology.Phase.CONFLICT_RESOLUTION, actualMembers, persistentUUIDManager.mapAddresses(actualMembers));
            // Update the currentTopology and try to resolve conflicts
            context.updateTopologiesAfterMerge(mergedTopology, maxStableTopology, mergedAvailabilityMode);
            context.queueConflictResolution(mergedTopology, new HashSet<>(preferredHash.getMembers()));
            return;
        }
        // There's no pendingCH, therefore the topology is in stable phase
        actualMembers.retainAll(mergedTopology.getMembers());
        mergedTopology = new CacheTopology(maxTopologyId + 1, mergedTopology.getRebalanceId(), mergedTopology.getCurrentCH(), null, CacheTopology.Phase.NO_REBALANCE, actualMembers, persistentUUIDManager.mapAddresses(actualMembers));
    }
    context.updateTopologiesAfterMerge(mergedTopology, maxStableTopology, mergedAvailabilityMode);
    // It shouldn't be possible to recover from unavailable mode without user action
    if (newAvailabilityMode == AvailabilityMode.DEGRADED_MODE) {
        log.debugf("After merge, cache %s is staying in degraded mode", context.getCacheName());
        context.updateAvailabilityMode(actualMembers, newAvailabilityMode, true);
    } else {
        // AVAILABLE
        log.debugf("After merge, cache %s has recovered and is entering available mode", context.getCacheName());
        updateMembersAndRebalance(context, actualMembers, context.getExpectedMembers());
    }
}
Also used : AvailabilityStrategy.ownersConsistentHash(org.infinispan.partitionhandling.impl.AvailabilityStrategy.ownersConsistentHash) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) Address(org.infinispan.remoting.transport.Address) ArrayList(java.util.ArrayList) CacheStatusResponse(org.infinispan.topology.CacheStatusResponse) CacheJoinInfo(org.infinispan.topology.CacheJoinInfo) CacheTopology(org.infinispan.topology.CacheTopology) AvailabilityMode(org.infinispan.partitionhandling.AvailabilityMode) HashSet(java.util.HashSet)

Aggregations

CacheJoinInfo (org.infinispan.topology.CacheJoinInfo)2 CacheTopology (org.infinispan.topology.CacheTopology)2 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 CompletionStage (java.util.concurrent.CompletionStage)1 LocalizedCacheTopology (org.infinispan.distribution.LocalizedCacheTopology)1 ConsistentHash (org.infinispan.distribution.ch.ConsistentHash)1 Start (org.infinispan.factories.annotations.Start)1 AvailabilityMode (org.infinispan.partitionhandling.AvailabilityMode)1 AvailabilityStrategy.ownersConsistentHash (org.infinispan.partitionhandling.impl.AvailabilityStrategy.ownersConsistentHash)1 Address (org.infinispan.remoting.transport.Address)1 CacheStatusResponse (org.infinispan.topology.CacheStatusResponse)1 CacheTopologyHandler (org.infinispan.topology.CacheTopologyHandler)1