private static void logBlockReplicationInfo(
     Block block,
     BlockCollection bc,
     DatanodeDescriptor srcNode,
     NumberReplicas num,
     Iterable<DatanodeStorageInfo> storages) {
   int curReplicas = num.liveReplicas();
   int curExpectedReplicas = bc.getPreferredBlockReplication();
   StringBuilder nodeList = new StringBuilder();
   for (DatanodeStorageInfo storage : storages) {
     final DatanodeDescriptor node = storage.getDatanodeDescriptor();
     nodeList.append(node);
     nodeList.append(" ");
   }
   LOG.info(
       "Block: "
           + block
           + ", Expected Replicas: "
           + curExpectedReplicas
           + ", live replicas: "
           + curReplicas
           + ", corrupt replicas: "
           + num.corruptReplicas()
           + ", decommissioned replicas: "
           + num.decommissioned()
           + ", decommissioning replicas: "
           + num.decommissioning()
           + ", excess replicas: "
           + num.excessReplicas()
           + ", Is Open File: "
           + bc.isUnderConstruction()
           + ", Datanodes having this block: "
           + nodeList
           + ", Current Datanode: "
           + srcNode
           + ", Is current datanode decommissioning: "
           + srcNode.isDecommissionInProgress());
 }
  /**
   * Checks whether a block is sufficiently replicated for decommissioning. Full-strength
   * replication is not always necessary, hence "sufficient".
   *
   * @return true if sufficient, else false.
   */
  private boolean isSufficientlyReplicated(
      BlockInfo block, BlockCollection bc, NumberReplicas numberReplicas) {
    final int numExpected = bc.getPreferredBlockReplication();
    final int numLive = numberReplicas.liveReplicas();
    if (!blockManager.isNeededReplication(block, numExpected, numLive)) {
      // Block doesn't need replication. Skip.
      LOG.trace("Block {} does not need replication.", block);
      return true;
    }

    // Block is under-replicated
    LOG.trace("Block {} numExpected={}, numLive={}", block, numExpected, numLive);
    if (numExpected > numLive) {
      if (bc.isUnderConstruction() && block.equals(bc.getLastBlock())) {
        // Can decom a UC block as long as there will still be minReplicas
        if (numLive >= blockManager.minReplication) {
          LOG.trace(
              "UC block {} sufficiently-replicated since numLive ({}) " + ">= minR ({})",
              block,
              numLive,
              blockManager.minReplication);
          return true;
        } else {
          LOG.trace(
              "UC block {} insufficiently-replicated since numLive " + "({}) < minR ({})",
              block,
              numLive,
              blockManager.minReplication);
        }
      } else {
        // Can decom a non-UC as long as the default replication is met
        if (numLive >= blockManager.defaultReplication) {
          return true;
        }
      }
    }
    return false;
  }
    /**
     * Used while checking if decommission-in-progress datanodes can be marked as decommissioned.
     * Combines shared logic of pruneSufficientlyReplicated and handleInsufficientlyReplicated.
     *
     * @param datanode Datanode
     * @param it Iterator over the blocks on the datanode
     * @param insufficientlyReplicated Return parameter. If it's not null, will contain the
     *     insufficiently replicated-blocks from the list.
     * @param pruneSufficientlyReplicated whether to remove sufficiently replicated blocks from the
     *     iterator
     * @return true if there are under-replicated blocks in the provided block iterator, else false.
     */
    private void processBlocksForDecomInternal(
        final DatanodeDescriptor datanode,
        final Iterator<BlockInfo> it,
        final List<BlockInfo> insufficientlyReplicated,
        boolean pruneSufficientlyReplicated) {
      boolean firstReplicationLog = true;
      int underReplicatedBlocks = 0;
      int decommissionOnlyReplicas = 0;
      int underReplicatedInOpenFiles = 0;
      while (it.hasNext()) {
        numBlocksChecked++;
        final BlockInfo block = it.next();
        // Remove the block from the list if it's no longer in the block map,
        // e.g. the containing file has been deleted
        if (blockManager.blocksMap.getStoredBlock(block) == null) {
          LOG.trace("Removing unknown block {}", block);
          it.remove();
          continue;
        }
        BlockCollection bc = blockManager.blocksMap.getBlockCollection(block);
        if (bc == null) {
          // Orphan block, will be invalidated eventually. Skip.
          continue;
        }

        final NumberReplicas num = blockManager.countNodes(block);
        final int liveReplicas = num.liveReplicas();
        final int curReplicas = liveReplicas;

        // Schedule under-replicated blocks for replication if not already
        // pending
        if (blockManager.isNeededReplication(
            block, bc.getPreferredBlockReplication(), liveReplicas)) {
          if (!blockManager.neededReplications.contains(block)
              && blockManager.pendingReplications.getNumReplicas(block) == 0
              && namesystem.isPopulatingReplQueues()) {
            // Process these blocks only when active NN is out of safe mode.
            blockManager.neededReplications.add(
                block,
                curReplicas,
                num.decommissionedAndDecommissioning(),
                bc.getPreferredBlockReplication());
          }
        }

        // Even if the block is under-replicated,
        // it doesn't block decommission if it's sufficiently replicated
        if (isSufficientlyReplicated(block, bc, num)) {
          if (pruneSufficientlyReplicated) {
            it.remove();
          }
          continue;
        }

        // We've found an insufficiently replicated block.
        if (insufficientlyReplicated != null) {
          insufficientlyReplicated.add(block);
        }
        // Log if this is our first time through
        if (firstReplicationLog) {
          logBlockReplicationInfo(
              block, bc, datanode, num, blockManager.blocksMap.getStorages(block));
          firstReplicationLog = false;
        }
        // Update various counts
        underReplicatedBlocks++;
        if (bc.isUnderConstruction()) {
          underReplicatedInOpenFiles++;
        }
        if ((curReplicas == 0) && (num.decommissionedAndDecommissioning() > 0)) {
          decommissionOnlyReplicas++;
        }
      }

      datanode.decommissioningStatus.set(
          underReplicatedBlocks, decommissionOnlyReplicas, underReplicatedInOpenFiles);
    }