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