HDFS-10691. FileDistribution fails in hdfs oiv command due to ArrayIndexOutOfBoundsException. Contributed by Yiqun Lin.

(cherry picked from commit 204a2055b1)
(cherry picked from commit 0cff416c35)
This commit is contained in:
Akira Ajisaka 2016-07-29 15:39:48 +09:00
parent ac510e5cd0
commit e467f838bb
3 changed files with 59 additions and 0 deletions

View File

@ -128,6 +128,12 @@ final class FileDistributionCalculator {
int bucket = fileSize > maxSize ? distribution.length - 1 : (int) Math
.ceil((double)fileSize / steps);
// Compare the bucket value with distribution's length again,
// because sometimes the bucket value will be equal to
// the length when maxSize can't be divided completely by step.
if (bucket >= distribution.length) {
bucket = distribution.length - 1;
}
++distribution[bucket];
} else if (p.getType() == INodeSection.INode.Type.DIRECTORY) {

View File

@ -145,6 +145,10 @@ class FileDistributionVisitor extends TextWriterImageVisitor {
high = distribution.length-1;
else
high = (int)Math.ceil((double)current.fileSize / step);
if (high >= distribution.length) {
high = distribution.length - 1;
}
distribution[high]++;
if(totalFiles % 1000000 == 1)
System.out.println("Files processed: " + totalFiles

View File

@ -70,6 +70,7 @@ import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileSystemTestHelper;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
@ -552,4 +553,52 @@ public class TestOfflineImageViewer {
GenericTestUtils.assertExceptionContains("Layout version mismatch.", t);
}
}
@Test
public void testFileDistributionCalculatorForException() throws Exception {
File fsimageFile = null;
Configuration conf = new Configuration();
HashMap<String, FileStatus> files = Maps.newHashMap();
// Create a initial fsimage file
try (MiniDFSCluster cluster =
new MiniDFSCluster.Builder(conf).numDataNodes(1).build()) {
cluster.waitActive();
DistributedFileSystem hdfs = cluster.getFileSystem();
// Create a reasonable namespace
Path dir = new Path("/dir");
hdfs.mkdirs(dir);
files.put(dir.toString(), pathToFileEntry(hdfs, dir.toString()));
// Create files with byte size that can't be divided by step size,
// the byte size for here are 3, 9, 15, 21.
for (int i = 0; i < FILES_PER_DIR; i++) {
Path file = new Path(dir, "file" + i);
DFSTestUtil.createFile(hdfs, file, 6 * i + 3, (short) 1, 0);
files.put(file.toString(),
pathToFileEntry(hdfs, file.toString()));
}
// Write results to the fsimage file
hdfs.setSafeMode(SafeModeAction.SAFEMODE_ENTER, false);
hdfs.saveNamespace();
// Determine location of fsimage file
fsimageFile =
FSImageTestUtil.findLatestImageFile(FSImageTestUtil
.getFSImage(cluster.getNameNode()).getStorage().getStorageDir(0));
if (fsimageFile == null) {
throw new RuntimeException("Didn't generate or can't find fsimage");
}
}
// Run the test with params -maxSize 23 and -step 4, it will not throw
// ArrayIndexOutOfBoundsException with index 6 when deals with
// 21 byte size file.
int status =
OfflineImageViewerPB.run(new String[] {"-i",
fsimageFile.getAbsolutePath(), "-o", "-", "-p",
"FileDistribution", "-maxSize", "23", "-step", "4"});
assertEquals(0, status);
}
}