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