Repository: hadoop
Updated Branches:
refs/heads/branch-2 bd3364e07 -> b088eee29
HDFS-9188. Make block corruption related tests FsDataset-agnostic. (lei)
(cherry picked from commit c80b3a804f5222f95a266f84424af9cb9c229483)
Conflicts:
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShell.java
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestFileAppend3.java
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/b088eee2
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/b088eee2
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/b088eee2
Branch: refs/heads/branch-2
Commit: b088eee2971b42a054f4d4735e7aafb7ffa35a56
Parents: bd3364e
Author: Lei Xu <[email protected]>
Authored: Wed Oct 14 20:18:43 2015 -0700
Committer: Lei Xu <[email protected]>
Committed: Wed Oct 14 20:30:09 2015 -0700
----------------------------------------------------------------------
hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt | 2 +
.../org/apache/hadoop/hdfs/MiniDFSCluster.java | 124 ++++++++-----
.../hadoop/hdfs/TestClientReportBadBlock.java | 29 +--
.../org/apache/hadoop/hdfs/TestDFSShell.java | 41 +++--
.../org/apache/hadoop/hdfs/TestFileAppend3.java | 12 +-
.../hadoop/hdfs/TestMissingBlocksAlert.java | 4 +-
.../TestBlocksWithNotEnoughRacks.java | 2 +-
.../TestOverReplicatedBlocks.java | 2 +-
.../TestRBWBlockInvalidation.java | 18 +-
.../hdfs/server/datanode/DataNodeTestUtils.java | 14 --
.../datanode/FsDatasetImplTestUtilsFactory.java | 32 ++++
.../server/datanode/FsDatasetTestUtils.java | 140 +++++++++++++++
.../fsdataset/impl/FsDatasetImplTestUtils.java | 179 +++++++++++++++++++
.../fsdataset/impl/TestScrLazyPersistFiles.java | 7 +-
.../namenode/TestProcessCorruptBlocks.java | 6 +-
15 files changed, 473 insertions(+), 139 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt
b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt
index 820de3b..18aee53 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt
+++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt
@@ -699,6 +699,8 @@ Release 2.8.0 - UNRELEASED
HDFS-9223. Code cleanup for DatanodeDescriptor and HeartbeatManager.
(jing9)
+ HDFS-9188. Make block corruption related tests FsDataset-agnostic. (lei)
+
OPTIMIZATIONS
HDFS-8026. Trace FSOutputSummer#writeChecksumChunks rather than
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java
index 5033d57..3d87bbf 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java
@@ -51,17 +51,14 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
-import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
-import java.nio.channels.FileChannel;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
-import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeoutException;
@@ -96,6 +93,9 @@ import org.apache.hadoop.hdfs.server.datanode.DataNode;
import org.apache.hadoop.hdfs.server.datanode.DataNodeTestUtils;
import org.apache.hadoop.hdfs.server.datanode.DataStorage;
import org.apache.hadoop.hdfs.server.datanode.DatanodeUtil;
+import org.apache.hadoop.hdfs.server.datanode.FsDatasetTestUtils;
+import
org.apache.hadoop.hdfs.server.datanode.FsDatasetTestUtils.MaterializedReplica;
+import org.apache.hadoop.hdfs.server.datanode.ReplicaNotFoundException;
import org.apache.hadoop.hdfs.server.datanode.SecureDataNodeStarter;
import
org.apache.hadoop.hdfs.server.datanode.SecureDataNodeStarter.SecureResources;
import org.apache.hadoop.hdfs.server.datanode.SimulatedFSDataset;
@@ -1719,7 +1719,29 @@ public class MiniDFSCluster {
}
/**
- * Gets the rpc port used by the NameNode, because the caller
+ * Returns the corresponding FsDatasetTestUtils for a DataNode.
+ * @param dnIdx the index of DataNode.
+ * @return a FsDatasetTestUtils for the given DataNode.
+ */
+ public FsDatasetTestUtils getFsDatasetTestUtils(int dnIdx) {
+ Preconditions.checkArgument(dnIdx < dataNodes.size());
+ return FsDatasetTestUtils.Factory.getFactory(conf)
+ .newInstance(dataNodes.get(dnIdx).datanode);
+ }
+
+ /**
+ * Returns the corresponding FsDatasetTestUtils for a DataNode.
+ * @param dn a DataNode
+ * @return a FsDatasetTestUtils for the given DataNode.
+ */
+ public FsDatasetTestUtils getFsDatasetTestUtils(DataNode dn) {
+ Preconditions.checkArgument(dn != null);
+ return FsDatasetTestUtils.Factory.getFactory(conf)
+ .newInstance(dn);
+ }
+
+ /**
+ * Gets the rpc port used by the NameNode, because the caller
* supplied port is not necessarily the actual port used.
* Assumption: cluster has a single namenode
*/
@@ -1900,11 +1922,18 @@ public class MiniDFSCluster {
private int corruptBlockOnDataNodesHelper(ExtendedBlock block,
boolean deleteBlockFile) throws IOException {
int blocksCorrupted = 0;
- File[] blockFiles = getAllBlockFiles(block);
- for (File f : blockFiles) {
- if ((deleteBlockFile && corruptBlockByDeletingBlockFile(f)) ||
- (!deleteBlockFile && corruptBlock(f))) {
+ for (DataNode dn : getDataNodes()) {
+ try {
+ MaterializedReplica replica =
+ getFsDatasetTestUtils(dn).getMaterializedReplica(block);
+ if (deleteBlockFile) {
+ replica.deleteData();
+ } else {
+ replica.corruptData();
+ }
blocksCorrupted++;
+ } catch (ReplicaNotFoundException e) {
+ // Ignore.
}
}
return blocksCorrupted;
@@ -1946,46 +1975,33 @@ public class MiniDFSCluster {
*
* @param i index of the datanode
* @param blk name of the block
- * @throws IOException on error accessing the given block or if
- * the contents of the block (on the same datanode) differ.
- * @return true if a replica was corrupted, false otherwise
- * Types: delete, write bad data, truncate
+ * @throws IOException on error accessing the given block file.
*/
- public boolean corruptReplica(int i, ExtendedBlock blk)
+ public void corruptReplica(int i, ExtendedBlock blk)
throws IOException {
- File blockFile = getBlockFile(i, blk);
- return corruptBlock(blockFile);
+ getMaterializedReplica(i, blk).corruptData();
}
- /*
- * Corrupt a block on a particular datanode
+ /**
+ * Corrupt a block on a particular datanode.
+ *
+ * @param dn the datanode
+ * @param blk name of the block
+ * @throws IOException on error accessing the given block file.
*/
- public static boolean corruptBlock(File blockFile) throws IOException {
- if (blockFile == null || !blockFile.exists()) {
- return false;
- }
- // Corrupt replica by writing random bytes into replica
- Random random = new Random();
- RandomAccessFile raFile = new RandomAccessFile(blockFile, "rw");
- FileChannel channel = raFile.getChannel();
- String badString = "BADBAD";
- int rand = random.nextInt((int)channel.size()/2);
- raFile.seek(rand);
- raFile.write(badString.getBytes());
- raFile.close();
- LOG.warn("Corrupting the block " + blockFile);
- return true;
+ public void corruptReplica(DataNode dn, ExtendedBlock blk)
+ throws IOException {
+ getMaterializedReplica(dn, blk).corruptData();
}
- /*
- * Corrupt a block on a particular datanode by deleting the block file
+ /**
+ * Corrupt the metadata of a block on a datanode.
+ * @param i the index of the datanode
+ * @param blk name of the block
+ * @throws IOException on error accessing the given metadata file.
*/
- public static boolean corruptBlockByDeletingBlockFile(File blockFile)
- throws IOException {
- if (blockFile == null || !blockFile.exists()) {
- return false;
- }
- return blockFile.delete();
+ public void corruptMeta(int i, ExtendedBlock blk) throws IOException {
+ getMaterializedReplica(i, blk).corruptMeta();
}
public boolean changeGenStampOfBlock(int dnIndex, ExtendedBlock blk,
@@ -2665,7 +2681,33 @@ public class MiniDFSCluster {
return new File(getBPDir(storageDir, bpid, Storage.STORAGE_DIR_CURRENT)
+ DataStorage.STORAGE_DIR_FINALIZED );
}
-
+
+ /**
+ * Get materialized replica that can be corrupted later.
+ * @param i the index of DataNode.
+ * @param blk name of the block.
+ * @return a materialized replica.
+ * @throws ReplicaNotFoundException if the replica does not exist on the
+ * DataNode.
+ */
+ public MaterializedReplica getMaterializedReplica(
+ int i, ExtendedBlock blk) throws ReplicaNotFoundException {
+ return getFsDatasetTestUtils(i).getMaterializedReplica(blk);
+ }
+
+ /**
+ * Get materialized replica that can be corrupted later.
+ * @param dn the index of DataNode.
+ * @param blk name of the block.
+ * @return a materialized replica.
+ * @throws ReplicaNotFoundException if the replica does not exist on the
+ * DataNode.
+ */
+ public MaterializedReplica getMaterializedReplica(
+ DataNode dn, ExtendedBlock blk) throws ReplicaNotFoundException {
+ return getFsDatasetTestUtils(dn).getMaterializedReplica(blk);
+ }
+
/**
* Get file correpsonding to a block
* @param storageDir storage directory
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestClientReportBadBlock.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestClientReportBadBlock.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestClientReportBadBlock.java
index b3580b2..6b2eb3c 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestClientReportBadBlock.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestClientReportBadBlock.java
@@ -18,11 +18,9 @@
package org.apache.hadoop.hdfs;
import java.io.ByteArrayOutputStream;
-import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
-import java.io.RandomAccessFile;
import java.util.Random;
import java.util.concurrent.TimeoutException;
@@ -39,7 +37,6 @@ 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.datanode.DataNode;
-import org.apache.hadoop.hdfs.server.datanode.DataNodeTestUtils;
import org.apache.hadoop.hdfs.server.namenode.NamenodeFsck;
import org.apache.hadoop.hdfs.tools.DFSck;
import org.apache.hadoop.security.AccessControlException;
@@ -217,7 +214,7 @@ public class TestClientReportBadBlock {
for (int i = 0; i < corruptBlockCount; i++) {
DatanodeInfo dninfo = datanodeinfos[i];
final DataNode dn = cluster.getDataNode(dninfo.getIpcPort());
- corruptBlock(block, dn);
+ cluster.corruptReplica(dn, block);
LOG.debug("Corrupted block " + block.getBlockName() + " on data node "
+ dninfo);
@@ -292,30 +289,6 @@ public class TestClientReportBadBlock {
}
}
- /**
- * Corrupt a block on a data node. Replace the block file content with
content
- * of 1, 2, ...BLOCK_SIZE.
- *
- * @param block
- * the ExtendedBlock to be corrupted
- * @param dn
- * the data node where the block needs to be corrupted
- * @throws FileNotFoundException
- * @throws IOException
- */
- private static void corruptBlock(final ExtendedBlock block, final DataNode
dn)
- throws FileNotFoundException, IOException {
- final File f = DataNodeTestUtils.getBlockFile(
- dn, block.getBlockPoolId(), block.getLocalBlock());
- final RandomAccessFile raFile = new RandomAccessFile(f, "rw");
- final byte[] bytes = new byte[(int) BLOCK_SIZE];
- for (int i = 0; i < BLOCK_SIZE; i++) {
- bytes[i] = (byte) (i);
- }
- raFile.write(bytes);
- raFile.close();
- }
-
private static void verifyFsckHealth(String expected) throws Exception {
// Fsck health has error code 0.
// Make sure filesystem is in healthy state
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShell.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShell.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShell.java
index e5a25a4..f0e29fd 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShell.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSShell.java
@@ -39,8 +39,8 @@ import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.client.HdfsClientConfigKeys;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.BlockListAsLongs;
-import org.apache.hadoop.hdfs.server.datanode.DataNode;
-import org.apache.hadoop.hdfs.server.datanode.DataNodeTestUtils;
+import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
+import
org.apache.hadoop.hdfs.server.datanode.FsDatasetTestUtils.MaterializedReplica;
import org.apache.hadoop.hdfs.server.protocol.DatanodeStorage;
import org.apache.hadoop.hdfs.tools.DFSAdmin;
import org.apache.hadoop.io.IOUtils;
@@ -1454,32 +1454,31 @@ public class TestDFSShell {
}
}
- static List<File> getBlockFiles(MiniDFSCluster cluster) throws IOException {
- List<File> files = new ArrayList<File>();
- List<DataNode> datanodes = cluster.getDataNodes();
+ private static List<MaterializedReplica> getMaterializedReplicas(
+ MiniDFSCluster cluster) throws IOException {
+ List<MaterializedReplica> replicas = new ArrayList<>();
String poolId = cluster.getNamesystem().getBlockPoolId();
- List<Map<DatanodeStorage, BlockListAsLongs>> blocks =
cluster.getAllBlockReports(poolId);
+ List<Map<DatanodeStorage, BlockListAsLongs>> blocks =
+ cluster.getAllBlockReports(poolId);
for(int i = 0; i < blocks.size(); i++) {
- DataNode dn = datanodes.get(i);
Map<DatanodeStorage, BlockListAsLongs> map = blocks.get(i);
for(Map.Entry<DatanodeStorage, BlockListAsLongs> e : map.entrySet()) {
for(Block b : e.getValue()) {
- files.add(DataNodeTestUtils.getFile(dn, poolId, b.getBlockId()));
+ replicas.add(cluster.getMaterializedReplica(i,
+ new ExtendedBlock(poolId, b)));
}
}
}
- return files;
+ return replicas;
}
- static void corrupt(List<File> files) throws IOException {
- for(File f : files) {
- StringBuilder content = new StringBuilder(DFSTestUtil.readFile(f));
- char c = content.charAt(0);
- content.setCharAt(0, ++c);
- PrintWriter out = new PrintWriter(f);
- out.print(content);
- out.flush();
- out.close();
+ private static void corrupt(
+ List<MaterializedReplica> replicas, String content) throws IOException {
+ StringBuilder sb = new StringBuilder(content);
+ char c = content.charAt(0);
+ sb.setCharAt(0, ++c);
+ for(MaterializedReplica replica : replicas) {
+ replica.corruptData(sb.toString().getBytes("UTF8"));
}
}
@@ -1583,7 +1582,7 @@ public class TestDFSShell {
assertEquals(localfcontent, runner.run(0, "-ignoreCrc"));
// find block files to modify later
- List<File> files = getBlockFiles(cluster);
+ List<MaterializedReplica> replicas = getMaterializedReplicas(cluster);
// Shut down cluster and then corrupt the block files by overwriting a
// portion with junk data. We must shut down the cluster so that threads
@@ -1596,8 +1595,8 @@ public class TestDFSShell {
dfs.close();
cluster.shutdown();
- show("files=" + files);
- corrupt(files);
+ show("replicas=" + replicas);
+ corrupt(replicas, localfcontent);
// Start the cluster again, but do not reformat, so prior files remain.
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(2).format(false)
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestFileAppend3.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestFileAppend3.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestFileAppend3.java
index 6fbe37f..2876cf9 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestFileAppend3.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestFileAppend3.java
@@ -21,14 +21,12 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import java.io.File;
import java.io.IOException;
-import java.io.RandomAccessFile;
import java.util.EnumSet;
import java.util.List;
-import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.fs.CreateFlag;
+import org.apache.hadoop.test.GenericTestUtils;
import org.mockito.invocation.InvocationOnMock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -314,13 +312,7 @@ public class TestFileAppend3 {
DatanodeInfo[] datanodeinfos = lb.getLocations();
assertEquals(repl, datanodeinfos.length);
final DataNode dn = cluster.getDataNode(datanodeinfos[0].getIpcPort());
- final File f = DataNodeTestUtils.getBlockFile(
- dn, blk.getBlockPoolId(), blk.getLocalBlock());
- final RandomAccessFile raf = new RandomAccessFile(f, "rw");
- AppendTestUtil.LOG.info("dn=" + dn + ", blk=" + blk + " (length=" +
blk.getNumBytes() + ")");
- assertEquals(len1, raf.length());
- raf.setLength(0);
- raf.close();
+ cluster.getMaterializedReplica(dn, blk).truncateData(0);
//c. Open file in "append mode". Append a new block worth of data. Close
file.
final int len2 = (int)BLOCK_SIZE;
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestMissingBlocksAlert.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestMissingBlocksAlert.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestMissingBlocksAlert.java
index 578b2cf..90d42b6 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestMissingBlocksAlert.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestMissingBlocksAlert.java
@@ -81,7 +81,7 @@ public class TestMissingBlocksAlert {
// Corrupt the block
ExtendedBlock block = DFSTestUtil.getFirstBlock(dfs, corruptFile);
- assertTrue(cluster.corruptReplica(0, block));
+ cluster.corruptReplica(0, block);
// read the file so that the corrupt block is reported to NN
FSDataInputStream in = dfs.open(corruptFile);
@@ -126,7 +126,7 @@ public class TestMissingBlocksAlert {
DFSTestUtil.createFile(dfs, replOneFile, fileLen, (short)1, 0);
ExtendedBlock replOneBlock = DFSTestUtil.getFirstBlock(
dfs, replOneFile);
- assertTrue(cluster.corruptReplica(0, replOneBlock));
+ cluster.corruptReplica(0, replOneBlock);
// read the file so that the corrupt block is reported to NN
in = dfs.open(replOneFile);
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlocksWithNotEnoughRacks.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlocksWithNotEnoughRacks.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlocksWithNotEnoughRacks.java
index 9011748..7676f2e 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlocksWithNotEnoughRacks.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlocksWithNotEnoughRacks.java
@@ -209,7 +209,7 @@ public class TestBlocksWithNotEnoughRacks {
// Corrupt a replica of the block
int dnToCorrupt = DFSTestUtil.firstDnWithBlock(cluster, b);
- assertTrue(cluster.corruptReplica(dnToCorrupt, b));
+ cluster.corruptReplica(dnToCorrupt, b);
// Restart the datanode so blocks are re-scanned, and the corrupt
// block is detected.
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestOverReplicatedBlocks.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestOverReplicatedBlocks.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestOverReplicatedBlocks.java
index 2d7bb44..b32312b 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestOverReplicatedBlocks.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestOverReplicatedBlocks.java
@@ -69,7 +69,7 @@ public class TestOverReplicatedBlocks {
// corrupt the block on datanode 0
ExtendedBlock block = DFSTestUtil.getFirstBlock(fs, fileName);
- assertTrue(cluster.corruptReplica(0, block));
+ cluster.corruptReplica(0, block);
DataNodeProperties dnProps = cluster.stopDataNode(0);
// remove block scanner log to trigger block scanning
File scanCursor = new File(new File(MiniDFSCluster.getFinalizedDir(
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestRBWBlockInvalidation.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestRBWBlockInvalidation.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestRBWBlockInvalidation.java
index 1a32892..744e9fa 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestRBWBlockInvalidation.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestRBWBlockInvalidation.java
@@ -22,7 +22,6 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import java.io.Closeable;
-import java.io.File;
import java.io.IOException;
import java.util.List;
@@ -37,10 +36,8 @@ import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.MiniDFSCluster.DataNodeProperties;
-import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.server.datanode.DataNode;
-import org.apache.hadoop.hdfs.server.datanode.DataNodeTestUtils;
+import
org.apache.hadoop.hdfs.server.datanode.FsDatasetTestUtils.MaterializedReplica;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.hdfs.server.namenode.ha.HATestUtil;
import
org.apache.hadoop.hdfs.server.namenode.ha.TestDNFencing.RandomDeleterPolicy;
@@ -91,19 +88,14 @@ public class TestRBWBlockInvalidation {
out.writeBytes("HDFS-3157: " + testPath);
out.hsync();
cluster.startDataNodes(conf, 1, true, null, null, null);
- String bpid = namesystem.getBlockPoolId();
ExtendedBlock blk = DFSTestUtil.getFirstBlock(fs, testPath);
- Block block = blk.getLocalBlock();
- DataNode dn = cluster.getDataNodes().get(0);
// Delete partial block and its meta information from the RBW folder
// of first datanode.
- File blockFile = DataNodeTestUtils.getBlockFile(dn, bpid, block);
- File metaFile = DataNodeTestUtils.getMetaFile(dn, bpid, block);
- assertTrue("Could not delete the block file from the RBW folder",
- blockFile.delete());
- assertTrue("Could not delete the block meta file from the RBW folder",
- metaFile.delete());
+ MaterializedReplica replica = cluster.getMaterializedReplica(0, blk);
+
+ replica.deleteData();
+ replica.deleteMeta();
out.close();
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/DataNodeTestUtils.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/DataNodeTestUtils.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/DataNodeTestUtils.java
index 8b43787..ec45dac 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/DataNodeTestUtils.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/DataNodeTestUtils.java
@@ -158,20 +158,6 @@ public class DataNodeTestUtils {
return dn.getFSDataset();
}
- public static File getFile(DataNode dn, String bpid, long bid) {
- return FsDatasetTestUtil.getFile(dn.getFSDataset(), bpid, bid);
- }
-
- public static File getBlockFile(DataNode dn, String bpid, Block b
- ) throws IOException {
- return FsDatasetTestUtil.getBlockFile(dn.getFSDataset(), bpid, b);
- }
-
- public static File getMetaFile(DataNode dn, String bpid, Block b)
- throws IOException {
- return FsDatasetTestUtil.getMetaFile(dn.getFSDataset(), bpid, b);
- }
-
public static long getPendingAsyncDeletions(DataNode dn) {
return FsDatasetTestUtil.getPendingAsyncDeletions(dn.getFSDataset());
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/FsDatasetImplTestUtilsFactory.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/FsDatasetImplTestUtilsFactory.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/FsDatasetImplTestUtilsFactory.java
new file mode 100644
index 0000000..f283f5a
--- /dev/null
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/FsDatasetImplTestUtilsFactory.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hdfs.server.datanode;
+
+import
org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetImplTestUtils;
+
+/**
+ * A factory for creating {@link FsDatasetImplTestUtils} objects.
+ */
+public final class FsDatasetImplTestUtilsFactory
+ extends FsDatasetTestUtils.Factory<FsDatasetTestUtils> {
+ @Override
+ public FsDatasetTestUtils newInstance(DataNode datanode) {
+ return new FsDatasetImplTestUtils(datanode);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/FsDatasetTestUtils.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/FsDatasetTestUtils.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/FsDatasetTestUtils.java
new file mode 100644
index 0000000..e7bc514
--- /dev/null
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/FsDatasetTestUtils.java
@@ -0,0 +1,140 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.datanode;
+
+import com.google.common.base.Preconditions;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hdfs.DFSConfigKeys;
+import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
+import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetFactory;
+import org.apache.hadoop.util.ReflectionUtils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Provide block access for FsDataset white box tests.
+ */
[email protected]
[email protected]
+public interface FsDatasetTestUtils {
+
+ abstract class Factory<D extends FsDatasetTestUtils> {
+ /**
+ * By default, it returns FsDatasetImplTestUtilsFactory.
+ *
+ * @return The configured Factory.
+ */
+ public static Factory<?> getFactory(Configuration conf) {
+ String className = conf.get(
+ DFSConfigKeys.DFS_DATANODE_FSDATASET_FACTORY_KEY,
+ FsDatasetFactory.class.getName());
+ Preconditions.checkState(className.contains("Factory"));
+ className = className.replaceFirst("(\\$)?Factory$", "TestUtilsFactory");
+ final Class<? extends Factory> clazz = conf.getClass(
+ className,
+ FsDatasetImplTestUtilsFactory.class,
+ Factory.class);
+ return ReflectionUtils.newInstance(clazz, conf);
+ }
+
+ /**
+ * Create a new instance of FsDatasetTestUtils.
+ */
+ public abstract D newInstance(DataNode datanode);
+
+ /**
+ * @return True for SimulatedFsDataset
+ */
+ public boolean isSimulated() {
+ return false;
+ }
+ }
+
+ /**
+ * A replica to be corrupted.
+ *
+ * It is safe to corrupt this replica even if the MiniDFSCluster is shutdown.
+ */
+ interface MaterializedReplica {
+
+ /**
+ * Corrupt the block file of the replica.
+ * @throws FileNotFoundException if the block file does not exist.
+ * @throws IOException if I/O error.
+ */
+ void corruptData() throws IOException;
+
+ /**
+ * Corrupt the block file with the given content.
+ * @param newContent the new content written to the block file.
+ * @throws FileNotFoundException if the block file does not exist.
+ * @throws IOException if I/O error.
+ */
+ void corruptData(byte[] newContent) throws IOException;
+
+ /**
+ * Truncate the block file of the replica to the newSize.
+ * @param newSize the new size of the block file.
+ * @throws FileNotFoundException if the block file does not exist.
+ * @throws IOException if I/O error.
+ */
+ void truncateData(long newSize) throws IOException;
+
+ /**
+ * Delete the block file of the replica.
+ * @throws FileNotFoundException if the block file does not exist.
+ * @throws IOException if I/O error.
+ */
+ void deleteData() throws IOException;
+
+ /**
+ * Corrupt the metadata file of the replica.
+ * @throws FileNotFoundException if the block file does not exist.
+ * @throws IOException if I/O error.
+ */
+ void corruptMeta() throws IOException;
+
+ /**
+ * Delete the metadata file of the replcia.
+ * @throws FileNotFoundException if the block file does not exist.
+ * @throws IOException I/O error.
+ */
+ void deleteMeta() throws IOException;
+
+ /**
+ * Truncate the metadata file of the replica to the newSize.
+ * @throws FileNotFoundException if the block file does not exist.
+ * @throws IOException I/O error.
+ */
+ void truncateMeta(long newSize) throws IOException;
+ }
+
+ /**
+ * Get a materialized replica to corrupt its block / crc later.
+ * @param block the block of this replica begone to.
+ * @return a replica to corrupt. Return null if the replica does not exist
+ * in this dataset.
+ * @throws ReplicaNotFoundException if the replica does not exists on the
+ * dataset.
+ */
+ MaterializedReplica getMaterializedReplica(ExtendedBlock block)
+ throws ReplicaNotFoundException;
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImplTestUtils.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImplTestUtils.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImplTestUtils.java
new file mode 100644
index 0000000..8c8e4b6
--- /dev/null
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/FsDatasetImplTestUtils.java
@@ -0,0 +1,179 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hdfs.server.datanode.fsdataset.impl;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
+import org.apache.hadoop.hdfs.server.datanode.DataNode;
+import org.apache.hadoop.hdfs.server.datanode.FsDatasetTestUtils;
+import org.apache.hadoop.hdfs.server.datanode.ReplicaNotFoundException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.util.Random;
+
+/**
+ * Test-related utilities to access blocks in {@link FsDatasetImpl}.
+ */
[email protected]
[email protected]
+public class FsDatasetImplTestUtils implements FsDatasetTestUtils {
+ private static final Log LOG =
+ LogFactory.getLog(FsDatasetImplTestUtils.class);
+ private final FsDatasetImpl dataset;
+
+ /**
+ * A reference to the replica that is used to corrupt block / meta later.
+ */
+ private static class FsDatasetImplMaterializedReplica
+ implements MaterializedReplica {
+ /** Block file of the replica. */
+ private final File blockFile;
+ private final File metaFile;
+
+ /** Check the existence of the file. */
+ private static void checkFile(File file) throws FileNotFoundException {
+ if (file == null || !file.exists()) {
+ throw new FileNotFoundException(
+ "The block file or metadata file " + file + " does not exist.");
+ }
+ }
+
+ /** Corrupt a block / crc file by truncating it to a newSize */
+ private static void truncate(File file, long newSize)
+ throws IOException {
+ Preconditions.checkArgument(newSize >= 0);
+ checkFile(file);
+ try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
+ raf.setLength(newSize);
+ }
+ }
+
+ /** Corrupt a block / crc file by deleting it. */
+ private static void delete(File file) throws IOException {
+ checkFile(file);
+ Files.delete(file.toPath());
+ }
+
+ FsDatasetImplMaterializedReplica(File blockFile, File metaFile) {
+ this.blockFile = blockFile;
+ this.metaFile = metaFile;
+ }
+
+ @Override
+ public void corruptData() throws IOException {
+ checkFile(blockFile);
+ LOG.info("Corrupting block file: " + blockFile);
+ final int BUF_SIZE = 32;
+ byte[] buf = new byte[BUF_SIZE];
+ try (RandomAccessFile raf = new RandomAccessFile(blockFile, "rw")) {
+ int nread = raf.read(buf);
+ for (int i = 0; i < nread; i++) {
+ buf[i]++;
+ }
+ raf.seek(0);
+ raf.write(buf);
+ }
+ }
+
+ @Override
+ public void corruptData(byte[] newContent) throws IOException {
+ checkFile(blockFile);
+ LOG.info("Corrupting block file with new content: " + blockFile);
+ try (RandomAccessFile raf = new RandomAccessFile(blockFile, "rw")) {
+ raf.write(newContent);
+ }
+ }
+
+ @Override
+ public void truncateData(long newSize) throws IOException {
+ LOG.info("Truncating block file: " + blockFile);
+ truncate(blockFile, newSize);
+ }
+
+ @Override
+ public void deleteData() throws IOException {
+ LOG.info("Deleting block file: " + blockFile);
+ delete(blockFile);
+ }
+
+ @Override
+ public void corruptMeta() throws IOException {
+ checkFile(metaFile);
+ LOG.info("Corrupting meta file: " + metaFile);
+ Random random = new Random();
+ try (RandomAccessFile raf = new RandomAccessFile(metaFile, "rw")) {
+ FileChannel channel = raf.getChannel();
+ int offset = random.nextInt((int)channel.size() / 2);
+ raf.seek(offset);
+ raf.write("BADBAD".getBytes());
+ }
+ }
+
+ @Override
+ public void deleteMeta() throws IOException {
+ LOG.info("Deleting metadata file: " + metaFile);
+ delete(metaFile);
+ }
+
+ @Override
+ public void truncateMeta(long newSize) throws IOException {
+ LOG.info("Truncating metadata file: " + metaFile);
+ truncate(metaFile, newSize);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("MaterializedReplica: file=%s", blockFile);
+ }
+ }
+
+ public FsDatasetImplTestUtils(DataNode datanode) {
+ Preconditions.checkArgument(
+ datanode.getFSDataset() instanceof FsDatasetImpl);
+ dataset = (FsDatasetImpl) datanode.getFSDataset();
+ }
+
+ /**
+ * Return a materialized replica from the FsDatasetImpl.
+ */
+ @Override
+ public MaterializedReplica getMaterializedReplica(ExtendedBlock block)
+ throws ReplicaNotFoundException {
+ File blockFile;
+ try {
+ blockFile = dataset.getBlockFile(
+ block.getBlockPoolId(), block.getBlockId());
+ } catch (IOException e) {
+ LOG.error("Block file for " + block + " does not existed:", e);
+ throw new ReplicaNotFoundException(block);
+ }
+ File metaFile = FsDatasetUtil.getMetaFile(
+ blockFile, block.getGenerationStamp());
+ return new FsDatasetImplMaterializedReplica(blockFile, metaFile);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/TestScrLazyPersistFiles.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/TestScrLazyPersistFiles.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/TestScrLazyPersistFiles.java
index 2512588..f598a07 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/TestScrLazyPersistFiles.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/TestScrLazyPersistFiles.java
@@ -19,12 +19,9 @@ package
org.apache.hadoop.hdfs.server.datanode.fsdataset.impl;
import com.google.common.base.Preconditions;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.fs.ChecksumException;
-import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.hdfs.ClientContext;
import org.apache.hadoop.hdfs.DFSTestUtil;
-import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.client.HdfsDataInputStream;
import org.apache.hadoop.hdfs.server.datanode.BlockMetadataHeader;
import org.apache.hadoop.io.nativeio.NativeIO;
@@ -264,9 +261,7 @@ public class TestScrLazyPersistFiles extends
LazyPersistTestCase {
// Corrupt the lazy-persisted checksum file, and verify that checksum
// verification catches it.
ensureFileReplicasOnStorageType(path1, DEFAULT);
- File metaFile = cluster.getBlockMetadataFile(0,
- DFSTestUtil.getFirstBlock(fs, path1));
- MiniDFSCluster.corruptBlock(metaFile);
+ cluster.corruptMeta(0, DFSTestUtil.getFirstBlock(fs, path1));
exception.expect(ChecksumException.class);
DFSTestUtil.readFileBuffer(fs, path1);
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/b088eee2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestProcessCorruptBlocks.java
----------------------------------------------------------------------
diff --git
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestProcessCorruptBlocks.java
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestProcessCorruptBlocks.java
index 228a667..bc7a0ef4 100644
---
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestProcessCorruptBlocks.java
+++
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestProcessCorruptBlocks.java
@@ -268,10 +268,12 @@ public class TestProcessCorruptBlocks {
private void corruptBlock(MiniDFSCluster cluster, FileSystem fs, final Path
fileName,
int dnIndex, ExtendedBlock block) throws IOException {
- // corrupt the block on datanode dnIndex
+ // Truncate the block on the first datanode that has not been corrupted,
+ // so that directory scanner can discover the corruption from file size
+ // change.
// the indexes change once the nodes are restarted.
// But the datadirectory will not change
- assertTrue(cluster.corruptReplica(dnIndex, block));
+ cluster.getMaterializedReplica(0, block).truncateData(10);
// Run directory scanner to update the DN's volume map
DataNodeTestUtils.runDirectoryScanner(cluster.getDataNodes().get(0));