HDFS-12455. WebHDFS - Adding "snapshot enabled" status to ListStatus query result. Contributed by Ajay Kumar.

This commit is contained in:
Xiaoyu Yao 2017-10-03 13:02:12 -07:00
parent b91305119b
commit 107c177782
12 changed files with 103 additions and 13 deletions

View File

@ -60,7 +60,8 @@ public class FileStatus implements Writable, Comparable<Object>,
HAS_ACL, HAS_ACL,
HAS_CRYPT, HAS_CRYPT,
HAS_EC, HAS_EC,
}; SNAPSHOT_ENABLED
}
private static final Set<AttrFlags> NONE = Collections.<AttrFlags>emptySet(); private static final Set<AttrFlags> NONE = Collections.<AttrFlags>emptySet();
private static Set<AttrFlags> flags(boolean acl, boolean crypt, boolean ec) { private static Set<AttrFlags> flags(boolean acl, boolean crypt, boolean ec) {
if (!(acl || crypt || ec)) { if (!(acl || crypt || ec)) {
@ -273,6 +274,15 @@ public class FileStatus implements Writable, Comparable<Object>,
return attr.contains(AttrFlags.HAS_EC); return attr.contains(AttrFlags.HAS_EC);
} }
/**
* Check if directory is Snapshot enabled or not.
*
* @return true if directory is snapshot enabled
*/
public boolean isSnapshotEnabled() {
return attr.contains(AttrFlags.SNAPSHOT_ENABLED);
}
/** /**
* Get the owner of the file. * Get the owner of the file.
* @return owner of the file. The string could be empty if there is no * @return owner of the file. The string could be empty if there is no
@ -330,6 +340,19 @@ public class FileStatus implements Writable, Comparable<Object>,
this.group = (group == null) ? "" : group; this.group = (group == null) ? "" : group;
} }
/**
* Sets Snapshot enabled flag.
*
* @param isSnapShotEnabled When true, SNAPSHOT_ENABLED flag is set
*/
public void setSnapShotEnabledFlag(boolean isSnapShotEnabled) {
if (isSnapShotEnabled) {
attr.add(AttrFlags.SNAPSHOT_ENABLED);
} else {
attr.remove(AttrFlags.SNAPSHOT_ENABLED);
}
}
/** /**
* @return The contents of the symbolic link. * @return The contents of the symbolic link.
*/ */
@ -486,4 +509,6 @@ public class FileStatus implements Writable, Comparable<Object>,
} }
} }
} }

View File

@ -94,11 +94,15 @@ public final class PBHelper {
owner = proto.getOwner(); owner = proto.getOwner();
group = proto.getGroup(); group = proto.getGroup();
int flags = proto.getFlags(); int flags = proto.getFlags();
return new FileStatus(length, isdir, blockReplication, blocksize, FileStatus fileStatus = new FileStatus(length, isdir, blockReplication,
mtime, atime, permission, owner, group, symlink, path, blocksize, mtime, atime, permission, owner, group, symlink, path,
(flags & FileStatusProto.Flags.HAS_ACL_VALUE) != 0, (flags & FileStatusProto.Flags.HAS_ACL_VALUE) != 0,
(flags & FileStatusProto.Flags.HAS_CRYPT_VALUE) != 0, (flags & FileStatusProto.Flags.HAS_CRYPT_VALUE) != 0,
(flags & FileStatusProto.Flags.HAS_EC_VALUE) != 0); (flags & FileStatusProto.Flags.HAS_EC_VALUE) != 0);
fileStatus.setSnapShotEnabledFlag((flags & FileStatusProto.Flags
.SNAPSHOT_ENABLED_VALUE) != 0);
return fileStatus;
} }
public static FileStatusProto convert(FileStatus stat) throws IOException { public static FileStatusProto convert(FileStatus stat) throws IOException {
@ -124,6 +128,8 @@ public final class PBHelper {
flags |= stat.hasAcl() ? FileStatusProto.Flags.HAS_ACL_VALUE : 0; flags |= stat.hasAcl() ? FileStatusProto.Flags.HAS_ACL_VALUE : 0;
flags |= stat.isEncrypted() ? FileStatusProto.Flags.HAS_CRYPT_VALUE : 0; flags |= stat.isEncrypted() ? FileStatusProto.Flags.HAS_CRYPT_VALUE : 0;
flags |= stat.isErasureCoded() ? FileStatusProto.Flags.HAS_EC_VALUE : 0; flags |= stat.isErasureCoded() ? FileStatusProto.Flags.HAS_EC_VALUE : 0;
flags |= stat.isSnapshotEnabled() ? FileStatusProto.Flags
.SNAPSHOT_ENABLED_VALUE : 0;
bld.setFlags(flags); bld.setFlags(flags);
return bld.build(); return bld.build();
} }

View File

@ -47,6 +47,7 @@ message FileStatusProto {
HAS_ACL = 0x01; // has ACLs HAS_ACL = 0x01; // has ACLs
HAS_CRYPT = 0x02; // encrypted HAS_CRYPT = 0x02; // encrypted
HAS_EC = 0x04; // erasure coded HAS_EC = 0x04; // erasure coded
SNAPSHOT_ENABLED = 0x08; // snapshot enabled
} }
required FileType fileType = 1; required FileType fileType = 1;
required string path = 2; required string path = 2;

View File

@ -56,7 +56,8 @@ public class HdfsFileStatus extends FileStatus {
public enum Flags { public enum Flags {
HAS_ACL, HAS_ACL,
HAS_CRYPT, HAS_CRYPT,
HAS_EC; HAS_EC,
SNAPSHOT_ENABLED
} }
private final EnumSet<Flags> flags; private final EnumSet<Flags> flags;
@ -244,6 +245,15 @@ public class HdfsFileStatus extends FileStatus {
return storagePolicy; return storagePolicy;
} }
/**
* Check if directory is Snapshot enabled or not.
*
* @return true if directory is snapshot enabled
*/
public boolean isSnapshotEnabled() {
return flags.contains(Flags.SNAPSHOT_ENABLED);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
// satisfy findbugs // satisfy findbugs

View File

@ -1602,6 +1602,9 @@ public class PBHelperClient {
case HAS_EC: case HAS_EC:
f.add(HdfsFileStatus.Flags.HAS_EC); f.add(HdfsFileStatus.Flags.HAS_EC);
break; break;
case SNAPSHOT_ENABLED:
f.add(HdfsFileStatus.Flags.SNAPSHOT_ENABLED);
break;
default: default:
// ignore unknown // ignore unknown
break; break;
@ -2155,6 +2158,8 @@ public class PBHelperClient {
int flags = fs.hasAcl() ? HdfsFileStatusProto.Flags.HAS_ACL_VALUE : 0; int flags = fs.hasAcl() ? HdfsFileStatusProto.Flags.HAS_ACL_VALUE : 0;
flags |= fs.isEncrypted() ? HdfsFileStatusProto.Flags.HAS_CRYPT_VALUE : 0; flags |= fs.isEncrypted() ? HdfsFileStatusProto.Flags.HAS_CRYPT_VALUE : 0;
flags |= fs.isErasureCoded() ? HdfsFileStatusProto.Flags.HAS_EC_VALUE : 0; flags |= fs.isErasureCoded() ? HdfsFileStatusProto.Flags.HAS_EC_VALUE : 0;
flags |= fs.isSnapshotEnabled() ? HdfsFileStatusProto.Flags
.SNAPSHOT_ENABLED_VALUE : 0;
builder.setFlags(flags); builder.setFlags(flags);
return builder.build(); return builder.build();
} }

View File

@ -410,6 +410,7 @@ message HdfsFileStatusProto {
HAS_ACL = 0x01; // has ACLs HAS_ACL = 0x01; // has ACLs
HAS_CRYPT = 0x02; // encrypted HAS_CRYPT = 0x02; // encrypted
HAS_EC = 0x04; // erasure coded HAS_EC = 0x04; // erasure coded
SNAPSHOT_ENABLED = 0x08; // SNAPSHOT ENABLED
} }
required FileType fileType = 1; required FileType fileType = 1;
required bytes path = 2; // local name of inode encoded java UTF8 required bytes path = 2; // local name of inode encoded java UTF8

View File

@ -198,6 +198,7 @@ public class HttpFSFileSystem extends FileSystem
public static final String ENC_BIT_JSON = "encBit"; public static final String ENC_BIT_JSON = "encBit";
public static final String EC_BIT_JSON = "ecBit"; public static final String EC_BIT_JSON = "ecBit";
public static final String SNAPSHOT_BIT_JSON = "seBit";
public static final String DIRECTORY_LISTING_JSON = "DirectoryListing"; public static final String DIRECTORY_LISTING_JSON = "DirectoryListing";
public static final String PARTIAL_LISTING_JSON = "partialListing"; public static final String PARTIAL_LISTING_JSON = "partialListing";
@ -1066,20 +1067,28 @@ public class HttpFSFileSystem extends FileSystem
final Boolean aclBit = (Boolean) json.get(ACL_BIT_JSON); final Boolean aclBit = (Boolean) json.get(ACL_BIT_JSON);
final Boolean encBit = (Boolean) json.get(ENC_BIT_JSON); final Boolean encBit = (Boolean) json.get(ENC_BIT_JSON);
final Boolean erasureBit = (Boolean) json.get(EC_BIT_JSON); final Boolean erasureBit = (Boolean) json.get(EC_BIT_JSON);
final Boolean snapshotEnabledBit = (Boolean) json.get(SNAPSHOT_BIT_JSON);
final boolean aBit = (aclBit != null) ? aclBit : false; final boolean aBit = (aclBit != null) ? aclBit : false;
final boolean eBit = (encBit != null) ? encBit : false; final boolean eBit = (encBit != null) ? encBit : false;
final boolean ecBit = (erasureBit != null) ? erasureBit : false; final boolean ecBit = (erasureBit != null) ? erasureBit : false;
if (aBit || eBit || ecBit) { final boolean seBit =
(snapshotEnabledBit != null) ? snapshotEnabledBit : false;
if (aBit || eBit || ecBit || seBit) {
// include this for compatibility with 2.x // include this for compatibility with 2.x
FsPermissionExtension deprecatedPerm = FsPermissionExtension deprecatedPerm =
new FsPermissionExtension(permission, aBit, eBit, ecBit); new FsPermissionExtension(permission, aBit, eBit, ecBit);
return new FileStatus(len, FILE_TYPE.DIRECTORY == type, FileStatus fileStatus = new FileStatus(len, FILE_TYPE.DIRECTORY == type,
replication, blockSize, mTime, aTime, deprecatedPerm, owner, group, replication, blockSize, mTime, aTime, deprecatedPerm, owner, group,
null, path, aBit, eBit, ecBit); null, path, aBit, eBit, ecBit);
if (seBit) {
fileStatus.setSnapShotEnabledFlag(seBit);
} }
return fileStatus;
} else {
return new FileStatus(len, FILE_TYPE.DIRECTORY == type, return new FileStatus(len, FILE_TYPE.DIRECTORY == type,
replication, blockSize, mTime, aTime, permission, owner, group, path); replication, blockSize, mTime, aTime, permission, owner, group, path);
} }
}
/** /**
* Convert the given JSON object into an AclStatus * Convert the given JSON object into an AclStatus

View File

@ -948,6 +948,7 @@ public class ClientNamenodeProtocolServerSideTranslatorPB implements
} }
@Override @Override
public GetFileLinkInfoResponseProto getFileLinkInfo(RpcController controller, public GetFileLinkInfoResponseProto getFileLinkInfo(RpcController controller,
GetFileLinkInfoRequestProto req) throws ServiceException { GetFileLinkInfoRequestProto req) throws ServiceException {
try { try {

View File

@ -413,6 +413,8 @@ class FSDirStatAndListingOp {
.unprotectedGetErasureCodingPolicy(fsd.getFSNamesystem(), iip); .unprotectedGetErasureCodingPolicy(fsd.getFSNamesystem(), iip);
final boolean isErasureCoded = (ecPolicy != null); final boolean isErasureCoded = (ecPolicy != null);
boolean isSnapShottable = false;
if (node.isFile()) { if (node.isFile()) {
final INodeFile fileNode = node.asFile(); final INodeFile fileNode = node.asFile();
size = fileNode.computeFileSize(snapshot); size = fileNode.computeFileSize(snapshot);
@ -433,6 +435,8 @@ class FSDirStatAndListingOp {
loc = new LocatedBlocks(); loc = new LocatedBlocks();
} }
} }
} else if (node.isDirectory()) {
isSnapShottable = node.asDirectory().isSnapshottable();
} }
int childrenNum = node.isDirectory() ? int childrenNum = node.isDirectory() ?
@ -451,6 +455,9 @@ class FSDirStatAndListingOp {
if (isErasureCoded) { if (isErasureCoded) {
flags.add(HdfsFileStatus.Flags.HAS_EC); flags.add(HdfsFileStatus.Flags.HAS_EC);
} }
if(isSnapShottable){
flags.add(HdfsFileStatus.Flags.SNAPSHOT_ENABLED);
}
return createFileStatus( return createFileStatus(
size, size,
node.isDirectory(), node.isDirectory(),

View File

@ -135,6 +135,10 @@ public class JsonUtil {
if (status.isErasureCoded()) { if (status.isErasureCoded()) {
m.put("ecBit", true); m.put("ecBit", true);
} }
if (status.isSnapshotEnabled()) {
m.put("snapshotEnabled", status.isSnapshotEnabled());
}
m.put("accessTime", status.getAccessTime()); m.put("accessTime", status.getAccessTime());
m.put("modificationTime", status.getModificationTime()); m.put("modificationTime", status.getModificationTime());
m.put("blockSize", status.getBlockSize()); m.put("blockSize", status.getBlockSize());

View File

@ -440,6 +440,7 @@ See also: [`newlength`](#New_Length), [FileSystem](../../api/org/apache/hadoop/f
"pathSuffix" : "", "pathSuffix" : "",
"permission" : "777", "permission" : "777",
"replication" : 0, "replication" : 0,
"snapshotEnabled" : true
"type" : "DIRECTORY" //enum {FILE, DIRECTORY, SYMLINK} "type" : "DIRECTORY" //enum {FILE, DIRECTORY, SYMLINK}
} }
} }
@ -485,6 +486,7 @@ See also: [FileSystem](../../api/org/apache/hadoop/fs/FileSystem.html).getFileSt
"pathSuffix" : "bar", "pathSuffix" : "bar",
"permission" : "711", "permission" : "711",
"replication" : 0, "replication" : 0,
"snapshotEnabled" : true
"type" : "DIRECTORY" "type" : "DIRECTORY"
}, },
... ...

View File

@ -1269,6 +1269,25 @@ public class TestDistributedFileSystem {
} }
} }
@Test
public void testListStatusOfSnapshotDirs() throws IOException {
MiniDFSCluster cluster = new MiniDFSCluster.Builder(new HdfsConfiguration())
.build();
try {
DistributedFileSystem dfs = cluster.getFileSystem();
dfs.create(new Path("/parent/test1/dfsclose/file-0"));
Path snapShotDir = new Path("/parent/test1/");
dfs.allowSnapshot(snapShotDir);
FileStatus status = dfs.getFileStatus(new Path("/parent/test1"));
assertTrue(status.isSnapshotEnabled());
status = dfs.getFileStatus(new Path("/parent/"));
assertFalse(status.isSnapshotEnabled());
} finally {
cluster.shutdown();
}
}
@Test(timeout=10000) @Test(timeout=10000)
public void testDFSClientPeerReadTimeout() throws IOException { public void testDFSClientPeerReadTimeout() throws IOException {
final int timeout = 1000; final int timeout = 1000;