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);
}
}
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());
}
}
Aggregations