private void checkSlotsMigration(Collection<ClusterPartition> newPartitions) {
    List<ClusterPartition> currentPartitions =
        new ArrayList<ClusterPartition>(lastPartitions.values());
    for (ClusterPartition currentPartition : currentPartitions) {
      for (ClusterPartition newPartition : newPartitions) {
        if (!currentPartition.getNodeId().equals(newPartition.getNodeId())) {
          continue;
        }

        Set<ClusterSlotRange> addedSlots =
            new HashSet<ClusterSlotRange>(newPartition.getSlotRanges());
        addedSlots.removeAll(currentPartition.getSlotRanges());
        MasterSlaveEntry entry = getEntry(currentPartition.getSlotRanges().iterator().next());
        currentPartition.addSlotRanges(addedSlots);
        for (ClusterSlotRange slot : addedSlots) {
          entry.addSlotRange(slot);
          addEntry(slot, entry);
          log.info("{} slot added for {}", slot, entry.getClient().getAddr());
          lastPartitions.put(slot, currentPartition);
        }

        Set<ClusterSlotRange> removedSlots =
            new HashSet<ClusterSlotRange>(currentPartition.getSlotRanges());
        removedSlots.removeAll(newPartition.getSlotRanges());
        lastPartitions.keySet().removeAll(removedSlots);
        currentPartition.removeSlotRanges(removedSlots);

        for (ClusterSlotRange slot : removedSlots) {
          log.info("{} slot removed for {}", slot, entry.getClient().getAddr());
          entry.removeSlotRange(slot);
          removeMaster(slot);
        }
      }
    }
  }
  private void checkSlotsChange(
      ClusterServersConfig cfg, Collection<ClusterPartition> newPartitions) {
    checkSlotsMigration(newPartitions);

    Collection<ClusterSlotRange> newPartitionsSlots = slots(newPartitions);
    Set<ClusterSlotRange> removedSlots = new HashSet<ClusterSlotRange>(lastPartitions.keySet());
    removedSlots.removeAll(newPartitionsSlots);
    lastPartitions.keySet().removeAll(removedSlots);
    if (!removedSlots.isEmpty()) {
      log.info("{} slot ranges found to remove", removedSlots);
    }

    for (ClusterSlotRange slot : removedSlots) {
      MasterSlaveEntry entry = removeMaster(slot);
      entry.removeSlotRange(slot);
      if (entry.getSlotRanges().isEmpty()) {
        entry.shutdownMasterAsync();
        log.info("{} master and slaves for it removed", entry.getClient().getAddr());
      }
    }

    Set<ClusterSlotRange> addedSlots = new HashSet<ClusterSlotRange>(newPartitionsSlots);
    addedSlots.removeAll(lastPartitions.keySet());
    if (!addedSlots.isEmpty()) {
      log.info("{} slots found to add", addedSlots);
    }
    for (final ClusterSlotRange slot : addedSlots) {
      ClusterPartition partition = find(newPartitions, slot);
      boolean masterFound = false;
      for (MasterSlaveEntry entry : getEntries().values()) {
        if (entry.getClient().getAddr().equals(partition.getMasterAddr())) {
          addEntry(slot, entry);
          lastPartitions.put(slot, partition);
          masterFound = true;
          break;
        }
      }
      if (!masterFound) {
        Future<Collection<Future<Void>>> future = addMasterEntry(partition, cfg);
        future.addListener(
            new FutureListener<Collection<Future<Void>>>() {
              @Override
              public void operationComplete(Future<Collection<Future<Void>>> future)
                  throws Exception {
                if (!future.isSuccess()) {
                  log.error(
                      "New cluster slot range " + slot + " without master node detected",
                      future.cause());
                }
              }
            });
      }
    }
  }