code: private boolean isGoodBlockCandidate(Source source,
        BalancerDatanode target, BalancerBlock block) {
      // check if the block is moved or not
      if (movedBlocks.contains(block)) {
          return false;
      }
      if (block.isLocatedOnDatanode(target)) {
        return false;
      }
  
      boolean goodBlock = false;
      if (plan.cluster.isOnSameRack(source.getDatanode(), target.getDatanode())) {
        // good if source and target are on the same rack
        goodBlock = true;
      } else {
        boolean notOnSameRack = true;
        synchronized (block) {
          for (BalancerDatanode loc : block.locations) {
            if (plan.cluster.isOnSameRack(loc.datanode, target.datanode)) {
              notOnSameRack = false;
              break;
            }
          }
        }
        if (notOnSameRack) {
          // good if target is target is not on the same rack as any replica
          goodBlock = true;
        } else {
          // good if source is on the same rack as on of the replicas
          for (BalancerDatanode loc : block.locations) {
            if (loc != source &&
                plan.cluster.isOnSameRack(loc.datanode, source.datanode)) {
              goodBlock = true;
              break;
            }
          }
        }
      }
      return goodBlock;
    }
docs: /* Decide if it is OK to move the given block from source to target
  A block is a good candidate if
  1. the block is not in the process of being moved/has not been moved;
  2. the block does not have a replica on the target;
  3. doing the move does not reduce the number of racks that the block has