/**
* 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;
import java.io.IOException;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockAndLocation;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocatedBlockFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.apache.log4j.Level;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.BeforeClass;
/**
* This class tests the FileStatus API.
*/
public class TestLocatedBlockStatus {
{
((Log4JLogger)FileSystem.LOG).getLogger().setLevel(Level.ALL);
}
static final long seed = 0xDEADBEEFL;
final protected static Configuration conf = new Configuration();
protected static DistributedFileSystem fs;
final protected static Path TEST_DIR = getTestDir();
final private static int BLOCK_LEN = 512;
final private static int FILE_LEN = BLOCK_LEN + 1;
final private static Path FILE1 = new Path(TEST_DIR, "file1");
final private static Path DIR1 = new Path(TEST_DIR, "dir1");
final private static Path FILE2 = new Path(DIR1, "file2");
final private static Path FILE3 = new Path(DIR1, "file3");
final private static Path FILE4 = new Path(TEST_DIR, "file4");
protected static Path getTestDir() {
return new Path(
System.getProperty("test.build.data","build/test/data/work-dir/localfs"),
"main_");
}
@BeforeClass
public static void testSetUp() throws Exception {
conf.setLong("dfs.block.size", BLOCK_LEN);
MiniDFSCluster cluster = new MiniDFSCluster(conf, 3, true, null);
cluster.waitActive();
fs = DFSUtil.convertToDFS(cluster.getFileSystem());
fs.delete(TEST_DIR, true);
}
private static void writeFile(FileSystem fileSys, Path name, int fileSize)
throws IOException {
// Create and write a file that contains three blocks of data
FSDataOutputStream stm = fileSys.create(name);
byte[] buffer = new byte[fileSize];
Random rand = new Random(seed);
rand.nextBytes(buffer);
stm.write(buffer);
stm.close();
}
/** Test when input path is a file */
@Test
public void testFile() throws IOException {
fs.mkdirs(TEST_DIR);
writeFile(fs, FILE1, FILE_LEN);
RemoteIterator<LocatedBlockFileStatus> itor = fs.listLocatedBlockStatus(
FILE1);
LocatedBlockFileStatus stat = itor.next();
assertFalse(itor.hasNext());
// check file status
assertFalse(stat.isDir());
assertEquals(FILE_LEN, stat.getLen());
assertEquals(fs.makeQualified(FILE1), stat.getPath());
assertEquals(-1, stat.getChildrenCount());
// check block and locations
BlockAndLocation[] locations = stat.getBlockLocations();
assertEquals(2, locations.length);
assertEquals(BLOCK_LEN, locations[0].getLength());
assertEquals(0L, locations[0].getOffset());
String[] hostNames = locations[0].getNames();
assertEquals(3, hostNames.length);
for (String hostName : hostNames) {
assertTrue("Hostname is " + hostName, hostName.startsWith("127.0.0.1:"));
}
assertEquals(FILE_LEN-BLOCK_LEN, locations[1].getLength());
assertEquals(BLOCK_LEN, locations[1].getOffset());
fs.delete(FILE1, true);
}
/** Test when input path is a directory */
@Test
public void testDirectory() throws IOException {
fs.mkdirs(DIR1);
// test empty directory
RemoteIterator<LocatedBlockFileStatus> itor = fs.listLocatedBlockStatus(DIR1);
assertFalse(itor.hasNext());
// testing directory with 1 file
writeFile(fs, FILE2, FILE_LEN);
itor = fs.listLocatedBlockStatus(DIR1);
LocatedBlockFileStatus stat = itor.next();
assertFalse(itor.hasNext());
assertFalse(stat.isDir());
assertEquals(FILE_LEN, stat.getLen());
assertEquals(-1, stat.getChildrenCount());
assertEquals(fs.makeQualified(FILE2), stat.getPath());
assertEquals(2, stat.getBlockLocations().length);
// test more complicated directory
writeFile(fs, FILE1, FILE_LEN);
writeFile(fs, FILE3, FILE_LEN);
writeFile(fs, FILE4, FILE_LEN);
Set<Path> expectedResults = new TreeSet<Path>();
expectedResults.add(fs.makeQualified(FILE2));
expectedResults.add(fs.makeQualified(FILE3));
for (itor = fs.listLocatedBlockStatus(DIR1); itor.hasNext(); ) {
stat = itor.next();
assertFalse(stat.isDir());
assertTrue(expectedResults.remove(stat.getPath()));
}
assertTrue(expectedResults.isEmpty());
final Path qualifiedDir1 = fs.makeQualified(DIR1);
expectedResults.add(qualifiedDir1);
expectedResults.add(fs.makeQualified(FILE1));
expectedResults.add(fs.makeQualified(FILE4));
for (itor = fs.listLocatedBlockStatus(TEST_DIR); itor.hasNext(); ) {
stat = itor.next();
assertTrue(expectedResults.remove(stat.getPath()));
if (qualifiedDir1.equals(stat.getPath())) {
assertTrue(stat.isDir());
assertEquals(2, stat.getChildrenCount());
} else {
assertFalse(stat.isDir());
assertEquals(-1, stat.getChildrenCount());
}
}
assertTrue(expectedResults.isEmpty());
fs.delete(TEST_DIR, true);
}
}