/**
     * 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);
    }