/**
   * Blocking function which completes the migration of one store
   *
   * @param storeName The name of the store
   * @param adminClient Admin client used to initiate the copying of data
   * @param stealInfo The steal information
   * @param isReadOnlyStore Boolean indicating that this is a read-only store
   */
  private void rebalanceStore(
      String storeName,
      final AdminClient adminClient,
      RebalancePartitionsInfo stealInfo,
      boolean isReadOnlyStore) {
    logger.info(
        getHeader(stealInfo)
            + "Starting partitions migration for store "
            + storeName
            + " from donor node "
            + stealInfo.getDonorId());
    updateStatus(
        getHeader(stealInfo)
            + "Started partition migration for store "
            + storeName
            + " from donor node "
            + stealInfo.getDonorId());

    int asyncId =
        adminClient.migratePartitions(
            stealInfo.getDonorId(),
            metadataStore.getNodeId(),
            storeName,
            stealInfo.getReplicaToAddPartitionList(storeName),
            null,
            stealInfo.getInitialCluster());
    rebalanceStatusList.add(asyncId);

    if (logger.isDebugEnabled()) {
      logger.debug(
          getHeader(stealInfo)
              + "Waiting for completion for "
              + storeName
              + " with async id "
              + asyncId);
    }
    adminClient.waitForCompletion(
        metadataStore.getNodeId(),
        asyncId,
        voldemortConfig.getRebalancingTimeoutSec(),
        TimeUnit.SECONDS,
        getStatus());

    rebalanceStatusList.remove((Object) asyncId);

    logger.info(
        getHeader(stealInfo)
            + "Completed partition migration for store "
            + storeName
            + " from donor node "
            + stealInfo.getDonorId());
    updateStatus(
        getHeader(stealInfo)
            + "Completed partition migration for store "
            + storeName
            + " from donor node "
            + stealInfo.getDonorId());

    if (stealInfo.getReplicaToDeletePartitionList(storeName) != null
        && stealInfo.getReplicaToDeletePartitionList(storeName).size() > 0
        && !isReadOnlyStore) {
      logger.info(
          getHeader(stealInfo)
              + "Deleting partitions for store "
              + storeName
              + " on donor node "
              + stealInfo.getDonorId());
      updateStatus(
          getHeader(stealInfo)
              + "Deleting partitions for store "
              + storeName
              + " on donor node "
              + stealInfo.getDonorId());

      adminClient.deletePartitions(
          stealInfo.getDonorId(),
          storeName,
          stealInfo.getReplicaToDeletePartitionList(storeName),
          stealInfo.getInitialCluster(),
          null);
      logger.info(
          getHeader(stealInfo)
              + "Deleted partitions for store "
              + storeName
              + " on donor node "
              + stealInfo.getDonorId());
      updateStatus(
          getHeader(stealInfo)
              + "Deleted partitions for store "
              + storeName
              + " on donor node "
              + stealInfo.getDonorId());
    }

    logger.info(getHeader(stealInfo) + "Finished all migration for store " + storeName);
    updateStatus(getHeader(stealInfo) + "Finished all migration for store " + storeName);
  }