HDFS-10744. Internally optimize path component resolution. Contributed by Daryn Sharp.

(cherry picked from commit 1ef8d7a638)
(cherry picked from commit 3dac73080a)
This commit is contained in:
Kihwal Lee 2016-09-02 11:31:48 -05:00 committed by Zhe Zhang
parent 9afc6615b0
commit 199ccd4915
11 changed files with 110 additions and 174 deletions

View File

@ -39,8 +39,7 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
@ -65,8 +64,7 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
@ -90,8 +88,7 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
@ -115,8 +112,7 @@ class FSDirAclOp {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
@ -135,9 +131,8 @@ class FSDirAclOp {
throws IOException { throws IOException {
String src = srcArg; String src = srcArg;
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
@ -155,8 +150,7 @@ class FSDirAclOp {
FSDirectory fsd, String src) throws IOException { FSDirectory fsd, String src) throws IOException {
checkAclsConfigFlag(fsd); checkAclsConfigFlag(fsd);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
String srcs = FSDirectory.normalizePath(src); String srcs = FSDirectory.normalizePath(src);
fsd.readLock(); fsd.readLock();
try { try {

View File

@ -52,11 +52,10 @@ public class FSDirAttrOp {
throws IOException { throws IOException {
String src = srcArg; String src = srcArg;
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
iip = fsd.getINodesInPath4Write(src); iip = fsd.getINodesInPath4Write(src);
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
unprotectedSetPermission(fsd, src, permission); unprotectedSetPermission(fsd, src, permission);
@ -71,11 +70,10 @@ public class FSDirAttrOp {
FSDirectory fsd, String src, String username, String group) FSDirectory fsd, String src, String username, String group)
throws IOException { throws IOException {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
iip = fsd.getINodesInPath4Write(src); iip = fsd.getINodesInPath4Write(src);
fsd.checkOwner(pc, iip); fsd.checkOwner(pc, iip);
if (!pc.isSuperUser()) { if (!pc.isSuperUser()) {
@ -105,12 +103,11 @@ public class FSDirAttrOp {
} }
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
iip = fsd.getINodesInPath4Write(src); iip = fsd.getINodesInPath4Write(src);
// Write access is required to set access and modification times // Write access is required to set access and modification times
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
@ -138,10 +135,9 @@ public class FSDirAttrOp {
bm.verifyReplication(src, replication, null); bm.verifyReplication(src, replication, null);
final boolean isFile; final boolean isFile;
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
final INodesInPath iip = fsd.getINodesInPath4Write(src); final INodesInPath iip = fsd.getINodesInPath4Write(src);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.WRITE); fsd.checkPathAccess(pc, iip, FsAction.WRITE);
@ -170,11 +166,10 @@ public class FSDirAttrOp {
+ DFS_STORAGE_POLICY_ENABLED_KEY + " is set to false."); + DFS_STORAGE_POLICY_ENABLED_KEY + " is set to false.");
} }
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = FSDirectory.resolvePath(src, pathComponents, fsd); src = FSDirectory.resolvePath(src, fsd);
iip = fsd.getINodesInPath4Write(src); iip = fsd.getINodesInPath4Write(src);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
@ -203,10 +198,9 @@ public class FSDirAttrOp {
static long getPreferredBlockSize(FSDirectory fsd, String src) static long getPreferredBlockSize(FSDirectory fsd, String src)
throws IOException { throws IOException {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
fsd.readLock(); fsd.readLock();
try { try {
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
final INodesInPath iip = fsd.getINodesInPath(src, false); final INodesInPath iip = fsd.getINodesInPath(src, false);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);

View File

@ -77,9 +77,8 @@ class FSDirDeleteOp {
throws IOException { throws IOException {
FSDirectory fsd = fsn.getFSDirectory(); FSDirectory fsd = fsn.getFSDirectory();
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
final INodesInPath iip = fsd.getINodesInPath4Write(src, false); final INodesInPath iip = fsd.getINodesInPath4Write(src, false);
if (!recursive && fsd.isNonEmptyDirectory(iip)) { if (!recursive && fsd.isNonEmptyDirectory(iip)) {
throw new PathIsNotEmptyDirectoryException(src + " is non empty"); throw new PathIsNotEmptyDirectoryException(src + " is non empty");

View File

@ -50,10 +50,9 @@ class FSDirMkdirOp {
throw new InvalidPathException(src); throw new InvalidPathException(src);
} }
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
INodesInPath iip = fsd.getINodesInPath4Write(src); INodesInPath iip = fsd.getINodesInPath4Write(src);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);

View File

@ -64,11 +64,9 @@ class FSDirRenameOp {
} }
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] srcComponents = FSDirectory.getPathComponentsForReservedPath(src);
byte[][] dstComponents = FSDirectory.getPathComponentsForReservedPath(dst);
HdfsFileStatus resultingStat = null; HdfsFileStatus resultingStat = null;
src = fsd.resolvePath(pc, src, srcComponents); src = fsd.resolvePath(pc, src);
dst = fsd.resolvePath(pc, dst, dstComponents); dst = fsd.resolvePath(pc, dst);
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
final boolean status = renameTo(fsd, pc, src, dst, logRetryCache); final boolean status = renameTo(fsd, pc, src, dst, logRetryCache);
if (status) { if (status) {
@ -239,11 +237,9 @@ class FSDirRenameOp {
} }
final FSPermissionChecker pc = fsd.getPermissionChecker(); final FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] srcComponents = FSDirectory.getPathComponentsForReservedPath(src);
byte[][] dstComponents = FSDirectory.getPathComponentsForReservedPath(dst);
BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo(); BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
src = fsd.resolvePath(pc, src, srcComponents); src = fsd.resolvePath(pc, src);
dst = fsd.resolvePath(pc, dst, dstComponents); dst = fsd.resolvePath(pc, dst);
renameTo(fsd, pc, src, dst, collectedBlocks, logRetryCache, options); renameTo(fsd, pc, src, dst, collectedBlocks, logRetryCache, options);
INodesInPath dstIIP = fsd.getINodesInPath(dst, false); INodesInPath dstIIP = fsd.getINodesInPath(dst, false);
HdfsFileStatus resultingStat = fsd.getAuditFileInfo(dstIIP); HdfsFileStatus resultingStat = fsd.getAuditFileInfo(dstIIP);

View File

@ -48,18 +48,14 @@ class FSDirStatAndListingOp {
static DirectoryListing getListingInt(FSDirectory fsd, final String srcArg, static DirectoryListing getListingInt(FSDirectory fsd, final String srcArg,
byte[] startAfter, boolean needLocation) throws IOException { byte[] startAfter, boolean needLocation) throws IOException {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory
.getPathComponentsForReservedPath(srcArg);
final String startAfterString = DFSUtil.bytes2String(startAfter); final String startAfterString = DFSUtil.bytes2String(startAfter);
final String src = fsd.resolvePath(pc, srcArg, pathComponents); final String src = fsd.resolvePath(pc, srcArg);
final INodesInPath iip = fsd.getINodesInPath(src, true); final INodesInPath iip = fsd.getINodesInPath(src, true);
// Get file name when startAfter is an INodePath // Get file name when startAfter is an INodePath
if (FSDirectory.isReservedName(startAfterString)) { if (FSDirectory.isReservedName(startAfterString)) {
byte[][] startAfterComponents = FSDirectory
.getPathComponentsForReservedPath(startAfterString);
try { try {
String tmp = FSDirectory.resolvePath(src, startAfterComponents, fsd); String tmp = FSDirectory.resolvePath(startAfterString, fsd);
byte[][] regularPath = INode.getPathComponents(tmp); byte[][] regularPath = INode.getPathComponents(tmp);
startAfter = regularPath[regularPath.length - 1]; startAfter = regularPath[regularPath.length - 1];
} catch (IOException e) { } catch (IOException e) {
@ -99,8 +95,7 @@ class FSDirStatAndListingOp {
throw new InvalidPathException("Invalid file name: " + src); throw new InvalidPathException("Invalid file name: " + src);
} }
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, srcArg);
src = fsd.resolvePath(pc, src, pathComponents);
final INodesInPath iip = fsd.getINodesInPath(src, resolveLink); final INodesInPath iip = fsd.getINodesInPath(src, resolveLink);
boolean isSuperUser = true; boolean isSuperUser = true;
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
@ -116,8 +111,7 @@ class FSDirStatAndListingOp {
*/ */
static boolean isFileClosed(FSDirectory fsd, String src) throws IOException { static boolean isFileClosed(FSDirectory fsd, String src) throws IOException {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
final INodesInPath iip = fsd.getINodesInPath(src, true); final INodesInPath iip = fsd.getINodesInPath(src, true);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkTraverse(pc, iip); fsd.checkTraverse(pc, iip);
@ -127,9 +121,8 @@ class FSDirStatAndListingOp {
static ContentSummary getContentSummary( static ContentSummary getContentSummary(
FSDirectory fsd, String src) throws IOException { FSDirectory fsd, String src) throws IOException {
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
final INodesInPath iip = fsd.getINodesInPath(src, false); final INodesInPath iip = fsd.getINodesInPath(src, false);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPermission(pc, iip, false, null, null, null, fsd.checkPermission(pc, iip, false, null, null, null,

View File

@ -52,11 +52,10 @@ class FSDirSymlinkOp {
} }
FSPermissionChecker pc = fsn.getPermissionChecker(); FSPermissionChecker pc = fsn.getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(link);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
link = fsd.resolvePath(pc, link, pathComponents); link = fsd.resolvePath(pc, link);
iip = fsd.getINodesInPath4Write(link, false); iip = fsd.getINodesInPath4Write(link, false);
if (!createParent) { if (!createParent) {
fsd.verifyParentDir(iip, link); fsd.verifyParentDir(iip, link);

View File

@ -67,8 +67,7 @@ class FSDirXAttrOp {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
XAttrPermissionFilter.checkPermissionForApi( XAttrPermissionFilter.checkPermissionForApi(
pc, xAttr, FSDirectory.isReservedRawName(src)); pc, xAttr, FSDirectory.isReservedRawName(src));
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1); List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1);
xAttrs.add(xAttr); xAttrs.add(xAttr);
INodesInPath iip; INodesInPath iip;
@ -95,8 +94,7 @@ class FSDirXAttrOp {
if (!getAll) { if (!getAll) {
XAttrPermissionFilter.checkPermissionForApi(pc, xAttrs, isRawPath); XAttrPermissionFilter.checkPermissionForApi(pc, xAttrs, isRawPath);
} }
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
final INodesInPath iip = fsd.getINodesInPath(src, true); final INodesInPath iip = fsd.getINodesInPath(src, true);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
fsd.checkPathAccess(pc, iip, FsAction.READ); fsd.checkPathAccess(pc, iip, FsAction.READ);
@ -135,8 +133,7 @@ class FSDirXAttrOp {
FSDirXAttrOp.checkXAttrsConfigFlag(fsd); FSDirXAttrOp.checkXAttrsConfigFlag(fsd);
final FSPermissionChecker pc = fsd.getPermissionChecker(); final FSPermissionChecker pc = fsd.getPermissionChecker();
final boolean isRawPath = FSDirectory.isReservedRawName(src); final boolean isRawPath = FSDirectory.isReservedRawName(src);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = fsd.resolvePath(pc, src);
src = fsd.resolvePath(pc, src, pathComponents);
final INodesInPath iip = fsd.getINodesInPath(src, true); final INodesInPath iip = fsd.getINodesInPath(src, true);
if (fsd.isPermissionEnabled()) { if (fsd.isPermissionEnabled()) {
/* To access xattr names, you need EXECUTE in the owning directory. */ /* To access xattr names, you need EXECUTE in the owning directory. */
@ -163,15 +160,13 @@ class FSDirXAttrOp {
FSPermissionChecker pc = fsd.getPermissionChecker(); FSPermissionChecker pc = fsd.getPermissionChecker();
XAttrPermissionFilter.checkPermissionForApi( XAttrPermissionFilter.checkPermissionForApi(
pc, xAttr, FSDirectory.isReservedRawName(src)); pc, xAttr, FSDirectory.isReservedRawName(src));
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(
src);
List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1); List<XAttr> xAttrs = Lists.newArrayListWithCapacity(1);
xAttrs.add(xAttr); xAttrs.add(xAttr);
INodesInPath iip; INodesInPath iip;
fsd.writeLock(); fsd.writeLock();
try { try {
src = fsd.resolvePath(pc, src, pathComponents); src = fsd.resolvePath(pc, src);
iip = fsd.getINodesInPath4Write(src); iip = fsd.getINodesInPath4Write(src);
checkXAttrChangeAccess(fsd, iip, xAttr, pc); checkXAttrChangeAccess(fsd, iip, xAttr, pc);

View File

@ -127,6 +127,8 @@ public class FSDirectory implements Closeable {
public final static String DOT_INODES_STRING = ".inodes"; public final static String DOT_INODES_STRING = ".inodes";
public final static byte[] DOT_INODES = public final static byte[] DOT_INODES =
DFSUtil.string2Bytes(DOT_INODES_STRING); DFSUtil.string2Bytes(DOT_INODES_STRING);
private final static byte[] DOT_DOT =
DFSUtil.string2Bytes("..");
INodeDirectory rootDir; INodeDirectory rootDir;
private final FSNamesystem namesystem; private final FSNamesystem namesystem;
@ -556,7 +558,6 @@ public class FSDirectory implements Closeable {
* *
* @param pc The permission checker used when resolving path. * @param pc The permission checker used when resolving path.
* @param path The path to resolve. * @param path The path to resolve.
* @param pathComponents path components corresponding to the path
* @return if the path indicates an inode, return path after replacing up to * @return if the path indicates an inode, return path after replacing up to
* <inodeid> with the corresponding path of the inode, else the path * <inodeid> with the corresponding path of the inode, else the path
* in {@code src} as is. If the path refers to a path in the "raw" * in {@code src} as is. If the path refers to a path in the "raw"
@ -564,12 +565,12 @@ public class FSDirectory implements Closeable {
* @throws FileNotFoundException * @throws FileNotFoundException
* @throws AccessControlException * @throws AccessControlException
*/ */
String resolvePath(FSPermissionChecker pc, String path, byte[][] pathComponents) String resolvePath(FSPermissionChecker pc, String path)
throws FileNotFoundException, AccessControlException { throws FileNotFoundException, AccessControlException {
if (isReservedRawName(path) && isPermissionEnabled) { if (isReservedRawName(path) && isPermissionEnabled) {
pc.checkSuperuserPrivilege(); pc.checkSuperuserPrivilege();
} }
return resolvePath(path, pathComponents, this); return resolvePath(path, this);
} }
/** /**
@ -1389,13 +1390,6 @@ public class FSDirectory implements Closeable {
return components.toArray(new byte[components.size()][]); return components.toArray(new byte[components.size()][]);
} }
/**
* @return path components for reserved path, else null.
*/
static byte[][] getPathComponentsForReservedPath(String src) {
return !isReservedName(src) ? null : INode.getPathComponents(src);
}
/** Check if a given inode name is reserved */ /** Check if a given inode name is reserved */
public static boolean isReservedName(INode inode) { public static boolean isReservedName(INode inode) {
return CHECK_RESERVED_FILE_NAMES return CHECK_RESERVED_FILE_NAMES
@ -1412,6 +1406,12 @@ public class FSDirectory implements Closeable {
Path.SEPARATOR + RAW_STRING); Path.SEPARATOR + RAW_STRING);
} }
static boolean isReservedName(byte[][] components) {
return (components.length > 2) &&
Arrays.equals(INodeDirectory.ROOT_NAME, components[0]) &&
Arrays.equals(DOT_RESERVED, components[1]);
}
/** /**
* Resolve a /.reserved/... path to a non-reserved path. * Resolve a /.reserved/... path to a non-reserved path.
* <p/> * <p/>
@ -1431,7 +1431,6 @@ public class FSDirectory implements Closeable {
* unencrypted file). * unencrypted file).
* *
* @param src path that is being processed * @param src path that is being processed
* @param pathComponents path components corresponding to the path
* @param fsd FSDirectory * @param fsd FSDirectory
* @return if the path indicates an inode, return path after replacing up to * @return if the path indicates an inode, return path after replacing up to
* <inodeid> with the corresponding path of the inode, else the path * <inodeid> with the corresponding path of the inode, else the path
@ -1439,39 +1438,32 @@ public class FSDirectory implements Closeable {
* directory, return the non-raw pathname. * directory, return the non-raw pathname.
* @throws FileNotFoundException if inodeid is invalid * @throws FileNotFoundException if inodeid is invalid
*/ */
static String resolvePath(String src, byte[][] pathComponents, static String resolvePath(String src,
FSDirectory fsd) throws FileNotFoundException { FSDirectory fsd) throws FileNotFoundException {
final int nComponents = (pathComponents == null) ? byte[][] pathComponents = INode.getPathComponents(src);
0 : pathComponents.length; final int nComponents = pathComponents.length;
if (nComponents <= 2) { if (!isReservedName(pathComponents)) {
return src;
}
if (!Arrays.equals(DOT_RESERVED, pathComponents[1])) {
/* This is not a /.reserved/ path so do nothing. */ /* This is not a /.reserved/ path so do nothing. */
return src; } else if (Arrays.equals(DOT_INODES, pathComponents[2])) {
}
if (Arrays.equals(DOT_INODES, pathComponents[2])) {
/* It's a /.reserved/.inodes path. */ /* It's a /.reserved/.inodes path. */
if (nComponents > 3) { if (nComponents > 3) {
return resolveDotInodesPath(src, pathComponents, fsd); pathComponents = resolveDotInodesPath(pathComponents, fsd);
} else {
return src;
} }
} else if (Arrays.equals(RAW, pathComponents[2])) { } else if (Arrays.equals(RAW, pathComponents[2])) {
/* It's /.reserved/raw so strip off the /.reserved/raw prefix. */ /* It's /.reserved/raw so strip off the /.reserved/raw prefix. */
if (nComponents == 3) { if (nComponents == 3) {
return Path.SEPARATOR; pathComponents = new byte[][]{INodeDirectory.ROOT_NAME};
} else { } else {
return constructRemainingPath("", pathComponents, 3); pathComponents = constructRemainingPath(
new byte[][]{INodeDirectory.ROOT_NAME}, pathComponents, 3);
} }
} else {
/* It's some sort of /.reserved/<unknown> path. Ignore it. */
return src;
} }
// this double conversion will be unnecessary when resolving returns
// INodesInPath (needs components byte[][])
return DFSUtil.byteArray2PathString(pathComponents);
} }
private static String resolveDotInodesPath(String src, private static byte[][] resolveDotInodesPath(
byte[][] pathComponents, FSDirectory fsd) byte[][] pathComponents, FSDirectory fsd)
throws FileNotFoundException { throws FileNotFoundException {
final String inodeId = DFSUtil.bytes2String(pathComponents[3]); final String inodeId = DFSUtil.bytes2String(pathComponents[3]);
@ -1479,48 +1471,47 @@ public class FSDirectory implements Closeable {
try { try {
id = Long.parseLong(inodeId); id = Long.parseLong(inodeId);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new FileNotFoundException("Invalid inode path: " + src); throw new FileNotFoundException("Invalid inode path: " +
DFSUtil.byteArray2PathString(pathComponents));
} }
if (id == INodeId.ROOT_INODE_ID && pathComponents.length == 4) { if (id == INodeId.ROOT_INODE_ID && pathComponents.length == 4) {
return Path.SEPARATOR; return new byte[][]{INodeDirectory.ROOT_NAME};
} }
INode inode = fsd.getInode(id); INode inode = fsd.getInode(id);
if (inode == null) { if (inode == null) {
throw new FileNotFoundException( throw new FileNotFoundException(
"File for given inode path does not exist: " + src); "File for given inode path does not exist: " +
DFSUtil.byteArray2PathString(pathComponents));
} }
// Handle single ".." for NFS lookup support. // Handle single ".." for NFS lookup support.
if ((pathComponents.length > 4) if ((pathComponents.length > 4)
&& DFSUtil.bytes2String(pathComponents[4]).equals("..")) { && Arrays.equals(pathComponents[4], DOT_DOT)) {
INode parent = inode.getParent(); INode parent = inode.getParent();
if (parent == null || parent.getId() == INodeId.ROOT_INODE_ID) { if (parent == null || parent.getId() == INodeId.ROOT_INODE_ID) {
// inode is root, or its parent is root. // inode is root, or its parent is root.
return Path.SEPARATOR; return new byte[][]{INodeDirectory.ROOT_NAME};
} else {
return parent.getFullPathName();
} }
return parent.getPathComponents();
} }
return constructRemainingPath(
String path = ""; inode.getPathComponents(), pathComponents, 4);
if (id != INodeId.ROOT_INODE_ID) {
path = inode.getFullPathName();
}
return constructRemainingPath(path, pathComponents, 4);
} }
private static String constructRemainingPath(String pathPrefix, private static byte[][] constructRemainingPath(byte[][] components,
byte[][] pathComponents, int startAt) { byte[][] extraComponents, int startAt) {
int remainder = extraComponents.length - startAt;
StringBuilder path = new StringBuilder(pathPrefix); if (remainder > 0) {
for (int i = startAt; i < pathComponents.length; i++) { // grow the array and copy in the remaining components
path.append(Path.SEPARATOR).append( int pos = components.length;
DFSUtil.bytes2String(pathComponents[i])); components = Arrays.copyOf(components, pos + remainder);
System.arraycopy(extraComponents, startAt, components, pos, remainder);
} }
if (NameNode.LOG.isDebugEnabled()) { if (NameNode.LOG.isDebugEnabled()) {
NameNode.LOG.debug("Resolved path is " + path); NameNode.LOG.debug(
"Resolved path is " + DFSUtil.byteArray2PathString(components));
} }
return path.toString(); return components;
} }
INode getINode4DotSnapshot(String src) throws UnresolvedLinkException { INode getINode4DotSnapshot(String src) throws UnresolvedLinkException {

View File

@ -1778,8 +1778,6 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
logAuditEvent(true, "open", srcArg); logAuditEvent(true, "open", srcArg);
if (res.updateAccessTime()) { if (res.updateAccessTime()) {
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(
srcArg);
String src = srcArg; String src = srcArg;
writeLock(); writeLock();
final long now = now(); final long now = now();
@ -1803,7 +1801,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
* HDFS-7463. A better fix is to change the edit log of SetTime to * HDFS-7463. A better fix is to change the edit log of SetTime to
* use inode id instead of a path. * use inode id instead of a path.
*/ */
src = dir.resolvePath(pc, srcArg, pathComponents); src = dir.resolvePath(pc, srcArg);
final INodesInPath iip = dir.getINodesInPath(src, true); final INodesInPath iip = dir.getINodesInPath(src, true);
INode inode = iip.getLastINode(); INode inode = iip.getLastINode();
boolean updateAccessTime = inode != null && boolean updateAccessTime = inode != null &&
@ -1880,8 +1878,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
boolean needBlockToken) boolean needBlockToken)
throws IOException { throws IOException {
String src = srcArg; String src = srcArg;
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src); src = dir.resolvePath(pc, srcArg);
src = dir.resolvePath(pc, srcArg, pathComponents);
final INodesInPath iip = dir.getINodesInPath(src, true); final INodesInPath iip = dir.getINodesInPath(src, true);
final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src); final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src);
if (isPermissionEnabled) { if (isPermissionEnabled) {
@ -2075,13 +2072,12 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
boolean res; boolean res;
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
writeLock(); writeLock();
BlocksMapUpdateInfo toRemoveBlocks = new BlocksMapUpdateInfo(); BlocksMapUpdateInfo toRemoveBlocks = new BlocksMapUpdateInfo();
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot truncate for " + src); checkNameNodeSafeMode("Cannot truncate for " + src);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
res = truncateInternal(src, newLength, clientName, res = truncateInternal(src, newLength, clientName,
clientMachine, mtime, pc, toRemoveBlocks); clientMachine, mtime, pc, toRemoveBlocks);
stat = dir.getAuditFileInfo(dir.getINodesInPath4Write(src, false)); stat = dir.getAuditFileInfo(dir.getINodesInPath4Write(src, false));
@ -2438,7 +2434,6 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
" minimum value (" + DFSConfigKeys.DFS_NAMENODE_MIN_BLOCK_SIZE_KEY " minimum value (" + DFSConfigKeys.DFS_NAMENODE_MIN_BLOCK_SIZE_KEY
+ "): " + blockSize + " < " + minBlockSize); + "): " + blockSize + " < " + minBlockSize);
} }
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
boolean create = flag.contains(CreateFlag.CREATE); boolean create = flag.contains(CreateFlag.CREATE);
boolean overwrite = flag.contains(CreateFlag.OVERWRITE); boolean overwrite = flag.contains(CreateFlag.OVERWRITE);
boolean isLazyPersist = flag.contains(CreateFlag.LAZY_PERSIST); boolean isLazyPersist = flag.contains(CreateFlag.LAZY_PERSIST);
@ -2465,7 +2460,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
if (provider != null) { if (provider != null) {
readLock(); readLock();
try { try {
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
INodesInPath iip = dir.getINodesInPath4Write(src); INodesInPath iip = dir.getINodesInPath4Write(src);
// Nothing to do if the path is not within an EZ // Nothing to do if the path is not within an EZ
final EncryptionZone zone = dir.getEZForPath(iip); final EncryptionZone zone = dir.getEZForPath(iip);
@ -2503,7 +2498,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
checkNameNodeSafeMode("Cannot create file" + src); checkNameNodeSafeMode("Cannot create file" + src);
dir.writeLock(); dir.writeLock();
try { try {
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
final INodesInPath iip = dir.getINodesInPath4Write(src); final INodesInPath iip = dir.getINodesInPath4Write(src);
toRemoveBlocks = startFileInternal( toRemoveBlocks = startFileInternal(
pc, iip, permissions, holder, pc, iip, permissions, holder,
@ -2877,12 +2872,11 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
boolean skipSync = false; boolean skipSync = false;
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
writeLock(); writeLock();
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot recover the lease of " + src); checkNameNodeSafeMode("Cannot recover the lease of " + src);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
final INodesInPath iip = dir.getINodesInPath4Write(src); final INodesInPath iip = dir.getINodesInPath4Write(src);
final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src); final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src);
if (!inode.isUnderConstruction()) { if (!inode.isUnderConstruction()) {
@ -3030,12 +3024,11 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
LocatedBlock lb = null; LocatedBlock lb = null;
HdfsFileStatus stat = null; HdfsFileStatus stat = null;
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
writeLock(); writeLock();
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot append to file" + src); checkNameNodeSafeMode("Cannot append to file" + src);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
final INodesInPath iip = dir.getINodesInPath4Write(src); final INodesInPath iip = dir.getINodesInPath4Write(src);
lb = appendFileInternal(pc, iip, holder, clientMachine, newBlock, lb = appendFileInternal(pc, iip, holder, clientMachine, newBlock,
logRetryCache); logRetryCache);
@ -3120,12 +3113,11 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
" for {}", src, fileId, clientName); " for {}", src, fileId, clientName);
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
readLock(); readLock();
try { try {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
FileState fileState = analyzeFileState( FileState fileState = analyzeFileState(
src, fileId, clientName, previous, onRetryBlock); src, fileId, clientName, previous, onRetryBlock);
if (onRetryBlock[0] != null && onRetryBlock[0].getLocations().length > 0) { if (onRetryBlock[0] != null && onRetryBlock[0].getLocations().length > 0) {
@ -3380,14 +3372,13 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
final byte storagePolicyID; final byte storagePolicyID;
final List<DatanodeStorageInfo> chosen; final List<DatanodeStorageInfo> chosen;
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
readLock(); readLock();
try { try {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
//check safe mode //check safe mode
checkNameNodeSafeMode("Cannot add datanode; src=" + src + ", blk=" + blk); checkNameNodeSafeMode("Cannot add datanode; src=" + src + ", blk=" + blk);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
//check lease //check lease
final INode inode; final INode inode;
@ -3436,14 +3427,13 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
NameNode.stateChangeLog.debug( NameNode.stateChangeLog.debug(
"BLOCK* NameSystem.abandonBlock: {} of file {}", b, src); "BLOCK* NameSystem.abandonBlock: {} of file {}", b, src);
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
waitForLoadingFSImage(); waitForLoadingFSImage();
writeLock(); writeLock();
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot abandon block " + b + " for file" + src); checkNameNodeSafeMode("Cannot abandon block " + b + " for file" + src);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
final INode inode; final INode inode;
final INodesInPath iip; final INodesInPath iip;
@ -3534,14 +3524,13 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
checkBlock(last); checkBlock(last);
boolean success = false; boolean success = false;
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
waitForLoadingFSImage(); waitForLoadingFSImage();
writeLock(); writeLock();
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot complete file " + src); checkNameNodeSafeMode("Cannot complete file " + src);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
success = completeFileInternal(src, holder, success = completeFileInternal(src, holder,
ExtendedBlock.getLocalBlock(last), fileId); ExtendedBlock.getLocalBlock(last), fileId);
} finally { } finally {
@ -4032,7 +4021,6 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
throws IOException { throws IOException {
NameNode.stateChangeLog.info("BLOCK* fsync: " + src + " for " + clientName); NameNode.stateChangeLog.info("BLOCK* fsync: " + src + " for " + clientName);
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
waitForLoadingFSImage(); waitForLoadingFSImage();
@ -4040,7 +4028,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
try { try {
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot fsync file " + src); checkNameNodeSafeMode("Cannot fsync file " + src);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
final INode inode; final INode inode;
if (fileId == INodeId.GRANDFATHER_INODE_ID) { if (fileId == INodeId.GRANDFATHER_INODE_ID) {
// Older clients may not have given us an inode ID to work with. // Older clients may not have given us an inode ID to work with.
@ -8100,15 +8088,13 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
String src = srcArg; String src = srcArg;
HdfsFileStatus resultingStat = null; HdfsFileStatus resultingStat = null;
checkSuperuserPrivilege(); checkSuperuserPrivilege();
final byte[][] pathComponents =
FSDirectory.getPathComponentsForReservedPath(src);
FSPermissionChecker pc = getPermissionChecker(); FSPermissionChecker pc = getPermissionChecker();
writeLock(); writeLock();
try { try {
checkSuperuserPrivilege(); checkSuperuserPrivilege();
checkOperation(OperationCategory.WRITE); checkOperation(OperationCategory.WRITE);
checkNameNodeSafeMode("Cannot create encryption zone on " + src); checkNameNodeSafeMode("Cannot create encryption zone on " + src);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
final CipherSuite suite = CipherSuite.convert(cipher); final CipherSuite suite = CipherSuite.convert(cipher);
// For now this is hardcoded, as we only support one method. // For now this is hardcoded, as we only support one method.
@ -8140,15 +8126,13 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
throws AccessControlException, UnresolvedLinkException, IOException { throws AccessControlException, UnresolvedLinkException, IOException {
String src = srcArg; String src = srcArg;
HdfsFileStatus resultingStat = null; HdfsFileStatus resultingStat = null;
final byte[][] pathComponents =
FSDirectory.getPathComponentsForReservedPath(src);
boolean success = false; boolean success = false;
final FSPermissionChecker pc = getPermissionChecker(); final FSPermissionChecker pc = getPermissionChecker();
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
readLock(); readLock();
try { try {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
src = dir.resolvePath(pc, src, pathComponents); src = dir.resolvePath(pc, src);
final INodesInPath iip = dir.getINodesInPath(src, true); final INodesInPath iip = dir.getINodesInPath(src, true);
if (isPermissionEnabled) { if (isPermissionEnabled) {
dir.checkPathAccess(pc, iip, FsAction.READ); dir.checkPathAccess(pc, iip, FsAction.READ);
@ -8250,11 +8234,10 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
void checkAccess(String src, FsAction mode) throws IOException { void checkAccess(String src, FsAction mode) throws IOException {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
readLock(); readLock();
try { try {
checkOperation(OperationCategory.READ); checkOperation(OperationCategory.READ);
src = FSDirectory.resolvePath(src, pathComponents, dir); src = FSDirectory.resolvePath(src, dir);
final INodesInPath iip = dir.getINodesInPath(src, true); final INodesInPath iip = dir.getINodesInPath(src, true);
INode inode = iip.getLastINode(); INode inode = iip.getLastINode();
if (inode == null) { if (inode == null) {

View File

@ -842,9 +842,9 @@ public class TestINodeFile {
byte[][] actual = FSDirectory.getPathComponents(inode); byte[][] actual = FSDirectory.getPathComponents(inode);
DFSTestUtil.checkComponentsEquals(expected, actual); DFSTestUtil.checkComponentsEquals(expected, actual);
} }
/** /**
* Tests for {@link FSDirectory#resolvePath(String, byte[][], FSDirectory)} * Tests for {@link FSDirectory#resolvePath(String, FSDirectory)}
*/ */
@Test @Test
public void testInodePath() throws IOException { public void testInodePath() throws IOException {
@ -854,54 +854,47 @@ public class TestINodeFile {
// For an any inode look up return inode corresponding to "c" from /a/b/c // For an any inode look up return inode corresponding to "c" from /a/b/c
FSDirectory fsd = Mockito.mock(FSDirectory.class); FSDirectory fsd = Mockito.mock(FSDirectory.class);
Mockito.doReturn(inode).when(fsd).getInode(Mockito.anyLong()); Mockito.doReturn(inode).when(fsd).getInode(Mockito.anyLong());
// Null components
assertEquals("/test", FSDirectory.resolvePath("/test", null, fsd));
// Tests for FSDirectory#resolvePath() // Tests for FSDirectory#resolvePath()
// Non inode regular path // Non inode regular path
byte[][] components = INode.getPathComponents(path); String resolvedPath = FSDirectory.resolvePath(path, fsd);
String resolvedPath = FSDirectory.resolvePath(path, components, fsd);
assertEquals(path, resolvedPath); assertEquals(path, resolvedPath);
// Inode path with no trailing separator // Inode path with no trailing separator
components = INode.getPathComponents("/.reserved/.inodes/1"); String testPath = "/.reserved/.inodes/1";
resolvedPath = FSDirectory.resolvePath(path, components, fsd); resolvedPath = FSDirectory.resolvePath(testPath, fsd);
assertEquals(path, resolvedPath); assertEquals(path, resolvedPath);
// Inode path with trailing separator // Inode path with trailing separator
components = INode.getPathComponents("/.reserved/.inodes/1/"); testPath = "/.reserved/.inodes/1/";
resolvedPath = FSDirectory.resolvePath(testPath, fsd);
assertEquals(path, resolvedPath); assertEquals(path, resolvedPath);
// Inode relative path // Inode relative path
components = INode.getPathComponents("/.reserved/.inodes/1/d/e/f"); testPath = "/.reserved/.inodes/1/d/e/f";
resolvedPath = FSDirectory.resolvePath(path, components, fsd); resolvedPath = FSDirectory.resolvePath(testPath, fsd);
assertEquals("/a/b/c/d/e/f", resolvedPath); assertEquals("/a/b/c/d/e/f", resolvedPath);
// A path with just .inodes returns the path as is // A path with just .inodes returns the path as is
String testPath = "/.reserved/.inodes"; testPath = "/.reserved/.inodes";
components = INode.getPathComponents(testPath); resolvedPath = FSDirectory.resolvePath(testPath, fsd);
resolvedPath = FSDirectory.resolvePath(testPath, components, fsd);
assertEquals(testPath, resolvedPath); assertEquals(testPath, resolvedPath);
// Root inode path // Root inode path
testPath = "/.reserved/.inodes/" + INodeId.ROOT_INODE_ID; testPath = "/.reserved/.inodes/" + INodeId.ROOT_INODE_ID;
components = INode.getPathComponents(testPath); resolvedPath = FSDirectory.resolvePath(testPath, fsd);
resolvedPath = FSDirectory.resolvePath(testPath, components, fsd);
assertEquals("/", resolvedPath); assertEquals("/", resolvedPath);
// An invalid inode path should remain unresolved // An invalid inode path should remain unresolved
testPath = "/.invalid/.inodes/1"; testPath = "/.invalid/.inodes/1";
components = INode.getPathComponents(testPath); resolvedPath = FSDirectory.resolvePath(testPath, fsd);
resolvedPath = FSDirectory.resolvePath(testPath, components, fsd);
assertEquals(testPath, resolvedPath); assertEquals(testPath, resolvedPath);
// Test path with nonexistent(deleted or wrong id) inode // Test path with nonexistent(deleted or wrong id) inode
Mockito.doReturn(null).when(fsd).getInode(Mockito.anyLong()); Mockito.doReturn(null).when(fsd).getInode(Mockito.anyLong());
testPath = "/.reserved/.inodes/1234"; testPath = "/.reserved/.inodes/1234";
components = INode.getPathComponents(testPath);
try { try {
String realPath = FSDirectory.resolvePath(testPath, components, fsd); String realPath = FSDirectory.resolvePath(testPath, fsd);
fail("Path should not be resolved:" + realPath); fail("Path should not be resolved:" + realPath);
} catch (IOException e) { } catch (IOException e) {
assertTrue(e instanceof FileNotFoundException); assertTrue(e instanceof FileNotFoundException);