From 57369a678c4c51627fe9a654e697a906a6bef123 Mon Sep 17 00:00:00 2001 From: Kihwal Lee Date: Thu, 4 Aug 2016 14:55:21 -0500 Subject: [PATCH] HDFS-10343. BlockManager#createLocatedBlocks may return blocks on failed storages. Contributed by Kuhu Shukla. --- .../server/blockmanagement/BlockManager.java | 11 ++- .../blockmanagement/TestBlockManager.java | 78 +++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java index 6c25d6414d..7411a6a695 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.BitSet; import java.util.Collection; import java.util.Collections; @@ -1045,14 +1046,15 @@ private LocatedBlock createLocatedBlock(final BlockInfo blk, final long pos) final boolean isCorrupt = numCorruptReplicas != 0 && numCorruptReplicas == numNodes; final int numMachines = isCorrupt ? numNodes: numNodes - numCorruptReplicas; - final DatanodeStorageInfo[] machines = new DatanodeStorageInfo[numMachines]; + DatanodeStorageInfo[] machines = new DatanodeStorageInfo[numMachines]; final byte[] blockIndices = blk.isStriped() ? new byte[numMachines] : null; int j = 0, i = 0; if (numMachines > 0) { for(DatanodeStorageInfo storage : blocksMap.getStorages(blk)) { final DatanodeDescriptor d = storage.getDatanodeDescriptor(); final boolean replicaCorrupt = corruptReplicas.isReplicaCorrupt(blk, d); - if (isCorrupt || (!replicaCorrupt)) { + if ((isCorrupt || (!replicaCorrupt)) && + storage.getState() != State.FAILED) { machines[j++] = storage; // TODO this can be more efficient if (blockIndices != null) { @@ -1063,6 +1065,11 @@ private LocatedBlock createLocatedBlock(final BlockInfo blk, final long pos) } } } + + if(j < machines.length) { + machines = Arrays.copyOf(machines, j); + } + assert j == machines.length : "isCorrupt: " + isCorrupt + " numMachines: " + numMachines + diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlockManager.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlockManager.java index 394fae9655..bbaf91f338 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlockManager.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlockManager.java @@ -72,8 +72,10 @@ import org.apache.hadoop.hdfs.protocol.BlockListAsLongs; import org.apache.hadoop.hdfs.protocol.ExtendedBlock; import org.apache.hadoop.hdfs.protocol.LocatedBlock; +import org.apache.hadoop.hdfs.protocol.LocatedBlocks; import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor.BlockTargetPair; import org.apache.hadoop.hdfs.server.common.HdfsServerConstants; +import org.apache.hadoop.hdfs.server.datanode.DataNode; import org.apache.hadoop.hdfs.server.datanode.InternalDataNodeTestUtils; import org.apache.hadoop.hdfs.server.datanode.FinalizedReplica; import org.apache.hadoop.hdfs.server.datanode.ReplicaBeingWritten; @@ -88,6 +90,7 @@ import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols; import org.apache.hadoop.hdfs.server.protocol.ReceivedDeletedBlockInfo; import org.apache.hadoop.hdfs.server.protocol.StorageReceivedDeletedBlocks; +import org.apache.hadoop.hdfs.server.protocol.StorageReport; import org.apache.hadoop.io.EnumSetWritable; import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.ipc.RemoteException; @@ -1152,6 +1155,81 @@ public void run() { } } + @Test + public void testBlockManagerMachinesArray() throws Exception { + final Configuration conf = new HdfsConfiguration(); + final MiniDFSCluster cluster = + new MiniDFSCluster.Builder(conf).numDataNodes(4).build(); + cluster.waitActive(); + BlockManager blockManager = cluster.getNamesystem().getBlockManager(); + FileSystem fs = cluster.getFileSystem(); + final Path filePath = new Path("/tmp.txt"); + final long fileLen = 1L; + DFSTestUtil.createFile(fs, filePath, fileLen, (short) 3, 1L); + ArrayList datanodes = cluster.getDataNodes(); + assertEquals(datanodes.size(), 4); + FSNamesystem ns = cluster.getNamesystem(); + // get the block + final String bpid = cluster.getNamesystem().getBlockPoolId(); + File storageDir = cluster.getInstanceStorageDir(0, 0); + File dataDir = MiniDFSCluster.getFinalizedDir(storageDir, bpid); + assertTrue("Data directory does not exist", dataDir.exists()); + BlockInfo blockInfo = blockManager.blocksMap.getBlocks().iterator().next(); + ExtendedBlock blk = new ExtendedBlock(bpid, blockInfo.getBlockId(), + blockInfo.getNumBytes(), blockInfo.getGenerationStamp()); + DatanodeDescriptor failedStorageDataNode = + blockManager.getStoredBlock(blockInfo).getDatanode(0); + DatanodeDescriptor corruptStorageDataNode = + blockManager.getStoredBlock(blockInfo).getDatanode(1); + + ArrayList reports = new ArrayList(); + for(int i=0; i origStorages = getStorages(0, 1);