private void recoverClusterStatus( int newViewId, final boolean isMergeView, final List<Address> clusterMembers) throws Exception { log.debugf("Recovering cluster status for view %d", newViewId); ReplicableCommand command = new CacheTopologyControlCommand( null, CacheTopologyControlCommand.Type.GET_STATUS, transport.getAddress(), newViewId); Map<Address, Object> statusResponses = executeOnClusterSync( command, getGlobalTimeout(), false, false, new CacheTopologyFilterReuser()); log.debugf("Got %d status responses. members are %s", statusResponses.size(), clusterMembers); Map<String, Map<Address, CacheStatusResponse>> responsesByCache = new HashMap<>(); boolean recoveredRebalancingStatus = true; for (Map.Entry<Address, Object> responseEntry : statusResponses.entrySet()) { Address sender = responseEntry.getKey(); ManagerStatusResponse nodeStatus = (ManagerStatusResponse) responseEntry.getValue(); recoveredRebalancingStatus &= nodeStatus.isRebalancingEnabled(); for (Map.Entry<String, CacheStatusResponse> statusEntry : nodeStatus.getCaches().entrySet()) { String cacheName = statusEntry.getKey(); Map<Address, CacheStatusResponse> cacheResponses = responsesByCache.get(cacheName); if (cacheResponses == null) { cacheResponses = new HashMap<>(); responsesByCache.put(cacheName, cacheResponses); } cacheResponses.put(sender, statusEntry.getValue()); } } globalRebalancingEnabled = recoveredRebalancingStatus; // Compute the new consistent hashes on separate threads int maxThreads = Runtime.getRuntime().availableProcessors() / 2 + 1; CompletionService<Void> cs = new SemaphoreCompletionService<>(asyncTransportExecutor, maxThreads); for (final Map.Entry<String, Map<Address, CacheStatusResponse>> e : responsesByCache.entrySet()) { final ClusterCacheStatus cacheStatus = initCacheStatusIfAbsent(e.getKey()); cs.submit( new Callable<Void>() { @Override public Void call() throws Exception { cacheStatus.doMergePartitions(e.getValue(), clusterMembers, isMergeView); return null; } }); } for (int i = 0; i < responsesByCache.size(); i++) { cs.take(); } }
@Override public boolean isAcceptable(Response response, Address sender) { if (response.isSuccessful() && response.isValid()) { ManagerStatusResponse value = (ManagerStatusResponse) ((SuccessfulResponse) response).getResponseValue(); for (Entry<String, CacheStatusResponse> entry : value.getCaches().entrySet()) { CacheStatusResponse csr = entry.getValue(); CacheTopology cacheTopology = csr.getCacheTopology(); CacheTopology stableTopology = csr.getStableTopology(); CacheTopology replaceCacheTopology = seenTopologies.get(cacheTopology); if (replaceCacheTopology == null) { seenTopologies.put(cacheTopology, cacheTopology); replaceCacheTopology = cacheTopology; } CacheTopology replaceStableTopology = null; // If the don't equal check if we replace - note stableTopology can be null if (!cacheTopology.equals(stableTopology)) { replaceStableTopology = seenTopologies.get(stableTopology); if (replaceStableTopology == null) { seenTopologies.put(stableTopology, stableTopology); } } else { // Since they were equal replace it with the cache topology we are going to use replaceStableTopology = replaceCacheTopology != null ? replaceCacheTopology : cacheTopology; } CacheJoinInfo info = csr.getCacheJoinInfo(); CacheJoinInfo replaceInfo = seenInfos.get(info); if (replaceInfo == null) { seenInfos.put(info, info); } if (replaceCacheTopology != null || replaceStableTopology != null || replaceInfo != null) { entry.setValue( new CacheStatusResponse( replaceInfo != null ? replaceInfo : info, replaceCacheTopology != null ? replaceCacheTopology : cacheTopology, replaceStableTopology != null ? replaceStableTopology : stableTopology, csr.getAvailabilityMode())); } } } return true; }