HDFS-4772. Add number of children in HdfsFileStatus. Contributed by Brandon Li

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1495253 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Brandon Li 2013-06-21 00:32:23 +00:00
parent 1a06175440
commit 6ecf78a99b
15 changed files with 67 additions and 18 deletions

View File

@ -122,6 +122,8 @@ Trunk (Unreleased)
HDFS-4904. Remove JournalService. (Arpit Agarwal via cnauroth) HDFS-4904. Remove JournalService. (Arpit Agarwal via cnauroth)
HDFS-4772. Add number of children in HdfsFileStatus. (brandonli)
OPTIMIZATIONS OPTIMIZATIONS
BUG FIXES BUG FIXES

View File

@ -42,6 +42,9 @@ public class HdfsFileStatus {
private String group; private String group;
private long fileId; private long fileId;
// Used by dir, not including dot and dotdot. Always zero for a regular file.
private int childrenNum;
public static final byte[] EMPTY_NAME = new byte[0]; public static final byte[] EMPTY_NAME = new byte[0];
/** /**
@ -61,7 +64,7 @@ public class HdfsFileStatus {
public HdfsFileStatus(long length, boolean isdir, int block_replication, public HdfsFileStatus(long length, boolean isdir, int block_replication,
long blocksize, long modification_time, long access_time, long blocksize, long modification_time, long access_time,
FsPermission permission, String owner, String group, FsPermission permission, String owner, String group,
byte[] symlink, byte[] path, long fileId) { byte[] symlink, byte[] path, long fileId, int childrenNum) {
this.length = length; this.length = length;
this.isdir = isdir; this.isdir = isdir;
this.block_replication = (short)block_replication; this.block_replication = (short)block_replication;
@ -78,6 +81,7 @@ public HdfsFileStatus(long length, boolean isdir, int block_replication,
this.symlink = symlink; this.symlink = symlink;
this.path = path; this.path = path;
this.fileId = fileId; this.fileId = fileId;
this.childrenNum = childrenNum;
} }
/** /**
@ -230,4 +234,8 @@ final public byte[] getSymlinkInBytes() {
final public long getFileId() { final public long getFileId() {
return fileId; return fileId;
} }
final public int getChildrenNum() {
return childrenNum;
}
} }

View File

@ -50,9 +50,11 @@ public class HdfsLocatedFileStatus extends HdfsFileStatus {
public HdfsLocatedFileStatus(long length, boolean isdir, public HdfsLocatedFileStatus(long length, boolean isdir,
int block_replication, long blocksize, long modification_time, int block_replication, long blocksize, long modification_time,
long access_time, FsPermission permission, String owner, String group, long access_time, FsPermission permission, String owner, String group,
byte[] symlink, byte[] path, long fileId, LocatedBlocks locations) { byte[] symlink, byte[] path, long fileId, LocatedBlocks locations,
int childrenNum) {
super(length, isdir, block_replication, blocksize, modification_time, super(length, isdir, block_replication, blocksize, modification_time,
access_time, permission, owner, group, symlink, path, fileId); access_time, permission, owner, group, symlink, path, fileId,
childrenNum);
this.locations = locations; this.locations = locations;
} }

View File

@ -57,10 +57,11 @@ public int compare(SnapshottableDirectoryStatus left,
public SnapshottableDirectoryStatus(long modification_time, long access_time, public SnapshottableDirectoryStatus(long modification_time, long access_time,
FsPermission permission, String owner, String group, byte[] localName, FsPermission permission, String owner, String group, byte[] localName,
long inodeId, long inodeId, int childrenNum,
int snapshotNumber, int snapshotQuota, byte[] parentFullPath) { int snapshotNumber, int snapshotQuota, byte[] parentFullPath) {
this.dirStatus = new HdfsFileStatus(0, true, 0, 0, modification_time, this.dirStatus = new HdfsFileStatus(0, true, 0, 0, modification_time,
access_time, permission, owner, group, null, localName, inodeId); access_time, permission, owner, group, null, localName, inodeId,
childrenNum);
this.snapshotNumber = snapshotNumber; this.snapshotNumber = snapshotNumber;
this.snapshotQuota = snapshotQuota; this.snapshotQuota = snapshotQuota;
this.parentFullPath = parentFullPath; this.parentFullPath = parentFullPath;

View File

@ -1055,7 +1055,8 @@ public static HdfsFileStatus convert(HdfsFileStatusProto fs) {
fs.getSymlink().toByteArray() : null, fs.getSymlink().toByteArray() : null,
fs.getPath().toByteArray(), fs.getPath().toByteArray(),
fs.hasFileId()? fs.getFileId(): INodeId.GRANDFATHER_INODE_ID, fs.hasFileId()? fs.getFileId(): INodeId.GRANDFATHER_INODE_ID,
fs.hasLocations() ? PBHelper.convert(fs.getLocations()) : null); fs.hasLocations() ? PBHelper.convert(fs.getLocations()) : null,
fs.hasChildrenNum() ? fs.getChildrenNum() : 0);
} }
public static SnapshottableDirectoryStatus convert( public static SnapshottableDirectoryStatus convert(
@ -1072,6 +1073,7 @@ public static SnapshottableDirectoryStatus convert(
status.getGroup(), status.getGroup(),
status.getPath().toByteArray(), status.getPath().toByteArray(),
status.getFileId(), status.getFileId(),
status.getChildrenNum(),
sdirStatusProto.getSnapshotNumber(), sdirStatusProto.getSnapshotNumber(),
sdirStatusProto.getSnapshotQuota(), sdirStatusProto.getSnapshotQuota(),
sdirStatusProto.getParentFullpath().toByteArray()); sdirStatusProto.getParentFullpath().toByteArray());
@ -1099,6 +1101,7 @@ public static HdfsFileStatusProto convert(HdfsFileStatus fs) {
setOwner(fs.getOwner()). setOwner(fs.getOwner()).
setGroup(fs.getGroup()). setGroup(fs.getGroup()).
setFileId(fs.getFileId()). setFileId(fs.getFileId()).
setChildrenNum(fs.getChildrenNum()).
setPath(ByteString.copyFrom(fs.getLocalNameInBytes())); setPath(ByteString.copyFrom(fs.getLocalNameInBytes()));
if (fs.isSymlink()) { if (fs.isSymlink()) {
builder.setSymlink(ByteString.copyFrom(fs.getSymlinkInBytes())); builder.setSymlink(ByteString.copyFrom(fs.getSymlinkInBytes()));

View File

@ -1582,6 +1582,13 @@ HdfsFileStatus getFileInfo(String src, boolean resolveLink)
} }
} }
/**
* Currently we only support "ls /xxx/.snapshot" which will return all the
* snapshots of a directory. The FSCommand Ls will first call getFileInfo to
* make sure the file/directory exists (before the real getListing call).
* Since we do not have a real INode for ".snapshot", we return an empty
* non-null HdfsFileStatus here.
*/
private HdfsFileStatus getFileInfo4DotSnapshot(String src) private HdfsFileStatus getFileInfo4DotSnapshot(String src)
throws UnresolvedLinkException { throws UnresolvedLinkException {
Preconditions.checkArgument( Preconditions.checkArgument(
@ -1596,7 +1603,7 @@ private HdfsFileStatus getFileInfo4DotSnapshot(String src)
&& node.isDirectory() && node.isDirectory()
&& node.asDirectory() instanceof INodeDirectorySnapshottable) { && node.asDirectory() instanceof INodeDirectorySnapshottable) {
return new HdfsFileStatus(0, true, 0, 0, 0, 0, null, null, null, null, return new HdfsFileStatus(0, true, 0, 0, 0, 0, null, null, null, null,
HdfsFileStatus.EMPTY_NAME, -1L); HdfsFileStatus.EMPTY_NAME, -1L, 0);
} }
return null; return null;
} }
@ -2521,6 +2528,9 @@ private HdfsFileStatus createFileStatus(byte[] path, INode node,
replication = fileNode.getFileReplication(snapshot); replication = fileNode.getFileReplication(snapshot);
blocksize = fileNode.getPreferredBlockSize(); blocksize = fileNode.getPreferredBlockSize();
} }
int childrenNum = node.isDirectory() ?
node.asDirectory().getChildrenNum(snapshot) : 0;
return new HdfsFileStatus( return new HdfsFileStatus(
size, size,
node.isDirectory(), node.isDirectory(),
@ -2533,7 +2543,8 @@ private HdfsFileStatus createFileStatus(byte[] path, INode node,
node.getGroupName(snapshot), node.getGroupName(snapshot),
node.isSymlink() ? node.asSymlink().getSymlink() : null, node.isSymlink() ? node.asSymlink().getSymlink() : null,
path, path,
node.getId()); node.getId(),
childrenNum);
} }
/** /**
@ -2563,12 +2574,15 @@ private HdfsLocatedFileStatus createLocatedFileStatus(byte[] path,
loc = new LocatedBlocks(); loc = new LocatedBlocks();
} }
} }
int childrenNum = node.isDirectory() ?
node.asDirectory().getChildrenNum(snapshot) : 0;
return new HdfsLocatedFileStatus(size, node.isDirectory(), replication, return new HdfsLocatedFileStatus(size, node.isDirectory(), replication,
blocksize, node.getModificationTime(snapshot), blocksize, node.getModificationTime(snapshot),
node.getAccessTime(snapshot), node.getFsPermission(snapshot), node.getAccessTime(snapshot), node.getFsPermission(snapshot),
node.getUserName(snapshot), node.getGroupName(snapshot), node.getUserName(snapshot), node.getGroupName(snapshot),
node.isSymlink() ? node.asSymlink().getSymlink() : null, path, node.isSymlink() ? node.asSymlink().getSymlink() : null, path,
node.getId(), loc); node.getId(), loc, childrenNum);
} }

View File

@ -655,4 +655,8 @@ public SnapshotAndINode(Snapshot snapshot) {
this(snapshot, snapshot.getRoot()); this(snapshot, snapshot.getRoot());
} }
} }
public final int getChildrenNum(final Snapshot snapshot) {
return getChildrenList(snapshot).size();
}
} }

View File

@ -130,6 +130,7 @@ public LinkedElement getNext() {
} }
/** Get inode id */ /** Get inode id */
@Override
public final long getId() { public final long getId() {
return this.id; return this.id;
} }
@ -226,6 +227,7 @@ final long getModificationTime(Snapshot snapshot) {
/** Update modification time if it is larger than the current value. */ /** Update modification time if it is larger than the current value. */
@Override
public final INode updateModificationTime(long mtime, Snapshot latest, public final INode updateModificationTime(long mtime, Snapshot latest,
final INodeMap inodeMap) throws QuotaExceededException { final INodeMap inodeMap) throws QuotaExceededException {
Preconditions.checkState(isDirectory()); Preconditions.checkState(isDirectory());
@ -256,6 +258,7 @@ final long getAccessTime(Snapshot snapshot) {
/** /**
* Set last access time of inode. * Set last access time of inode.
*/ */
@Override
public final void setAccessTime(long accessTime) { public final void setAccessTime(long accessTime) {
this.accessTime = accessTime; this.accessTime = accessTime;
} }

View File

@ -325,7 +325,8 @@ public SnapshottableDirectoryStatus[] getSnapshottableDirListing(
SnapshottableDirectoryStatus status = new SnapshottableDirectoryStatus( SnapshottableDirectoryStatus status = new SnapshottableDirectoryStatus(
dir.getModificationTime(), dir.getAccessTime(), dir.getModificationTime(), dir.getAccessTime(),
dir.getFsPermission(), dir.getUserName(), dir.getGroupName(), dir.getFsPermission(), dir.getUserName(), dir.getGroupName(),
dir.getLocalNameBytes(), dir.getId(), dir.getNumSnapshots(), dir.getLocalNameBytes(), dir.getId(), dir.getChildrenNum(null),
dir.getNumSnapshots(),
dir.getSnapshotQuota(), dir.getParent() == null ? dir.getSnapshotQuota(), dir.getParent() == null ?
DFSUtil.EMPTY_BYTES : DFSUtil.EMPTY_BYTES :
DFSUtil.string2Bytes(dir.getParent().getFullPathName())); DFSUtil.string2Bytes(dir.getParent().getFullPathName()));

View File

@ -221,6 +221,7 @@ public static String toJsonString(final HdfsFileStatus status,
m.put("blockSize", status.getBlockSize()); m.put("blockSize", status.getBlockSize());
m.put("replication", status.getReplication()); m.put("replication", status.getReplication());
m.put("fileId", status.getFileId()); m.put("fileId", status.getFileId());
m.put("childrenNum", status.getChildrenNum());
return includeType ? toJsonString(FileStatus.class, m): JSON.toString(m); return includeType ? toJsonString(FileStatus.class, m): JSON.toString(m);
} }
@ -247,9 +248,10 @@ public static HdfsFileStatus toFileStatus(final Map<?, ?> json, boolean includes
final short replication = (short) (long) (Long) m.get("replication"); final short replication = (short) (long) (Long) m.get("replication");
final long fileId = m.containsKey("fileId") ? (Long) m.get("fileId") final long fileId = m.containsKey("fileId") ? (Long) m.get("fileId")
: INodeId.GRANDFATHER_INODE_ID; : INodeId.GRANDFATHER_INODE_ID;
final int childrenNum = (int) (long) (Long) m.get("childrenNum");
return new HdfsFileStatus(len, type == PathType.DIRECTORY, replication, return new HdfsFileStatus(len, type == PathType.DIRECTORY, replication,
blockSize, mTime, aTime, permission, owner, group, blockSize, mTime, aTime, permission, owner, group,
symlink, DFSUtil.string2Bytes(localName), fileId); symlink, DFSUtil.string2Bytes(localName), fileId, childrenNum);
} }
/** Convert an ExtendedBlock to a Json map. */ /** Convert an ExtendedBlock to a Json map. */

View File

@ -173,6 +173,7 @@ message HdfsFileStatusProto {
// Optional field for fileId // Optional field for fileId
optional uint64 fileId = 13 [default = 0]; // default as an invalid id optional uint64 fileId = 13 [default = 0]; // default as an invalid id
optional uint32 childrenNum = 14 [default = 0];
} }
/** /**

View File

@ -252,12 +252,12 @@ public Object answer(InvocationOnMock invocation)
Mockito.doReturn( Mockito.doReturn(
new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission( new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission(
(short) 777), "owner", "group", new byte[0], new byte[0], (short) 777), "owner", "group", new byte[0], new byte[0],
1010)).when(mockNN).getFileInfo(anyString()); 1010, 0)).when(mockNN).getFileInfo(anyString());
Mockito.doReturn( Mockito.doReturn(
new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission( new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission(
(short) 777), "owner", "group", new byte[0], new byte[0], (short) 777), "owner", "group", new byte[0], new byte[0],
1010)) 1010, 0))
.when(mockNN) .when(mockNN)
.create(anyString(), (FsPermission) anyObject(), anyString(), .create(anyString(), (FsPermission) anyObject(), anyString(),
(EnumSetWritable<CreateFlag>) anyObject(), anyBoolean(), (EnumSetWritable<CreateFlag>) anyObject(), anyBoolean(),

View File

@ -24,7 +24,6 @@
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -37,7 +36,6 @@
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator; import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus; import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem; import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.hdfs.server.namenode.NameNode; import org.apache.hadoop.hdfs.server.namenode.NameNode;
@ -105,6 +103,16 @@ public void testGetFileInfo() throws IOException {
// Make sure getFileInfo returns null for files which do not exist // Make sure getFileInfo returns null for files which do not exist
HdfsFileStatus fileInfo = dfsClient.getFileInfo("/noSuchFile"); HdfsFileStatus fileInfo = dfsClient.getFileInfo("/noSuchFile");
assertEquals("Non-existant file should result in null", null, fileInfo); assertEquals("Non-existant file should result in null", null, fileInfo);
Path path1 = new Path("/name1");
Path path2 = new Path("/name1/name2");
assertTrue(fs.mkdirs(path1));
FSDataOutputStream out = fs.create(path2, false);
out.close();
fileInfo = dfsClient.getFileInfo(path1.toString());
assertEquals(1, fileInfo.getChildrenNum());
fileInfo = dfsClient.getFileInfo(path2.toString());
assertEquals(0, fileInfo.getChildrenNum());
// Test getFileInfo throws the right exception given a non-absolute path. // Test getFileInfo throws the right exception given a non-absolute path.
try { try {

View File

@ -294,12 +294,12 @@ public void testFactory() throws Exception {
Mockito.doReturn( Mockito.doReturn(
new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission( new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission(
(short) 777), "owner", "group", new byte[0], new byte[0], (short) 777), "owner", "group", new byte[0], new byte[0],
1010)).when(mcp).getFileInfo(anyString()); 1010, 0)).when(mcp).getFileInfo(anyString());
Mockito Mockito
.doReturn( .doReturn(
new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission( new HdfsFileStatus(0, false, 1, 1024, 0, 0, new FsPermission(
(short) 777), "owner", "group", new byte[0], new byte[0], (short) 777), "owner", "group", new byte[0], new byte[0],
1010)) 1010, 0))
.when(mcp) .when(mcp)
.create(anyString(), (FsPermission) anyObject(), anyString(), .create(anyString(), (FsPermission) anyObject(), anyString(),
(EnumSetWritable<CreateFlag>) anyObject(), anyBoolean(), (EnumSetWritable<CreateFlag>) anyObject(), anyBoolean(),

View File

@ -46,7 +46,7 @@ public void testHdfsFileStatus() {
final HdfsFileStatus status = new HdfsFileStatus(1001L, false, 3, 1L << 26, final HdfsFileStatus status = new HdfsFileStatus(1001L, false, 3, 1L << 26,
now, now + 10, new FsPermission((short) 0644), "user", "group", now, now + 10, new FsPermission((short) 0644), "user", "group",
DFSUtil.string2Bytes("bar"), DFSUtil.string2Bytes("foo"), DFSUtil.string2Bytes("bar"), DFSUtil.string2Bytes("foo"),
INodeId.GRANDFATHER_INODE_ID); INodeId.GRANDFATHER_INODE_ID, 0);
final FileStatus fstatus = toFileStatus(status, parent); final FileStatus fstatus = toFileStatus(status, parent);
System.out.println("status = " + status); System.out.println("status = " + status);
System.out.println("fstatus = " + fstatus); System.out.println("fstatus = " + fstatus);