HDFS-15427. Merged ListStatus with Fallback target filesystem and InternalDirViewFS. Contributed by Uma Maheswara Rao G.
This commit is contained in:
parent
201d734af3
commit
7c02d1889b
|
@ -374,7 +374,7 @@ abstract class InodeTree<T> {
|
||||||
throws UnsupportedFileSystemException, URISyntaxException, IOException;
|
throws UnsupportedFileSystemException, URISyntaxException, IOException;
|
||||||
|
|
||||||
protected abstract T getTargetFileSystem(INodeDir<T> dir)
|
protected abstract T getTargetFileSystem(INodeDir<T> dir)
|
||||||
throws URISyntaxException;
|
throws URISyntaxException, IOException;
|
||||||
|
|
||||||
protected abstract T getTargetFileSystem(String settings, URI[] mergeFsURIs)
|
protected abstract T getTargetFileSystem(String settings, URI[] mergeFsURIs)
|
||||||
throws UnsupportedFileSystemException, URISyntaxException, IOException;
|
throws UnsupportedFileSystemException, URISyntaxException, IOException;
|
||||||
|
@ -393,7 +393,7 @@ abstract class InodeTree<T> {
|
||||||
return rootFallbackLink != null;
|
return rootFallbackLink != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private INodeLink<T> getRootFallbackLink() {
|
protected INodeLink<T> getRootFallbackLink() {
|
||||||
Preconditions.checkState(root.isInternalDir());
|
Preconditions.checkState(root.isInternalDir());
|
||||||
return rootFallbackLink;
|
return rootFallbackLink;
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,8 @@ public class ViewFileSystem extends FileSystem {
|
||||||
@Override
|
@Override
|
||||||
protected FileSystem getTargetFileSystem(final INodeDir<FileSystem> dir)
|
protected FileSystem getTargetFileSystem(final INodeDir<FileSystem> dir)
|
||||||
throws URISyntaxException {
|
throws URISyntaxException {
|
||||||
return new InternalDirOfViewFs(dir, creationTime, ugi, myUri, config);
|
return new InternalDirOfViewFs(dir, creationTime, ugi, myUri, config,
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -518,10 +519,10 @@ public class ViewFileSystem extends FileSystem {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* Note: listStatus on root("/") considers listing from fallbackLink if
|
* Note: listStatus considers listing from fallbackLink if available. If the
|
||||||
* available. If the same directory name is present in configured mount path
|
* same directory path is present in configured mount path as well as in
|
||||||
* as well as in fallback link, then only the configured mount path will be
|
* fallback fs, then only the fallback path will be listed in the returned
|
||||||
* listed in the returned result.
|
* result except for link.
|
||||||
*
|
*
|
||||||
* If any of the the immediate children of the given path f is a symlink(mount
|
* If any of the the immediate children of the given path f is a symlink(mount
|
||||||
* link), the returned FileStatus object of that children would be represented
|
* link), the returned FileStatus object of that children would be represented
|
||||||
|
@ -1125,11 +1126,13 @@ public class ViewFileSystem extends FileSystem {
|
||||||
final UserGroupInformation ugi; // the user/group of user who created mtable
|
final UserGroupInformation ugi; // the user/group of user who created mtable
|
||||||
final URI myUri;
|
final URI myUri;
|
||||||
private final boolean showMountLinksAsSymlinks;
|
private final boolean showMountLinksAsSymlinks;
|
||||||
|
private InodeTree<FileSystem> fsState;
|
||||||
|
|
||||||
public InternalDirOfViewFs(final InodeTree.INodeDir<FileSystem> dir,
|
public InternalDirOfViewFs(final InodeTree.INodeDir<FileSystem> dir,
|
||||||
final long cTime, final UserGroupInformation ugi, URI uri,
|
final long cTime, final UserGroupInformation ugi, URI uri,
|
||||||
Configuration config) throws URISyntaxException {
|
Configuration config, InodeTree fsState) throws URISyntaxException {
|
||||||
myUri = uri;
|
myUri = uri;
|
||||||
|
this.fsState = fsState;
|
||||||
try {
|
try {
|
||||||
initialize(myUri, config);
|
initialize(myUri, config);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -1225,7 +1228,8 @@ public class ViewFileSystem extends FileSystem {
|
||||||
FileNotFoundException, IOException {
|
FileNotFoundException, IOException {
|
||||||
checkPathIsSlash(f);
|
checkPathIsSlash(f);
|
||||||
FileStatus[] fallbackStatuses = listStatusForFallbackLink();
|
FileStatus[] fallbackStatuses = listStatusForFallbackLink();
|
||||||
FileStatus[] result = new FileStatus[theInternalDir.getChildren().size()];
|
Set<FileStatus> linkStatuses = new HashSet<>();
|
||||||
|
Set<FileStatus> internalDirStatuses = new HashSet<>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Entry<String, INode<FileSystem>> iEntry :
|
for (Entry<String, INode<FileSystem>> iEntry :
|
||||||
theInternalDir.getChildren().entrySet()) {
|
theInternalDir.getChildren().entrySet()) {
|
||||||
|
@ -1238,11 +1242,10 @@ public class ViewFileSystem extends FileSystem {
|
||||||
// To maintain backward compatibility, with default option(showing
|
// To maintain backward compatibility, with default option(showing
|
||||||
// mount links as symlinks), we will represent target link as
|
// mount links as symlinks), we will represent target link as
|
||||||
// symlink and rest other properties are belongs to mount link only.
|
// symlink and rest other properties are belongs to mount link only.
|
||||||
result[i++] =
|
linkStatuses.add(
|
||||||
new FileStatus(0, false, 0, 0, creationTime, creationTime,
|
new FileStatus(0, false, 0, 0, creationTime, creationTime,
|
||||||
PERMISSION_555, ugi.getShortUserName(),
|
PERMISSION_555, ugi.getShortUserName(),
|
||||||
ugi.getPrimaryGroupName(), link.getTargetLink(),
|
ugi.getPrimaryGroupName(), link.getTargetLink(), path));
|
||||||
path);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1258,11 +1261,12 @@ public class ViewFileSystem extends FileSystem {
|
||||||
FileStatus status =
|
FileStatus status =
|
||||||
((ChRootedFileSystem)link.getTargetFileSystem())
|
((ChRootedFileSystem)link.getTargetFileSystem())
|
||||||
.getMyFs().getFileStatus(new Path(linkedPath));
|
.getMyFs().getFileStatus(new Path(linkedPath));
|
||||||
result[i++] = new FileStatus(status.getLen(), status.isDirectory(),
|
linkStatuses.add(
|
||||||
|
new FileStatus(status.getLen(), status.isDirectory(),
|
||||||
status.getReplication(), status.getBlockSize(),
|
status.getReplication(), status.getBlockSize(),
|
||||||
status.getModificationTime(), status.getAccessTime(),
|
status.getModificationTime(), status.getAccessTime(),
|
||||||
status.getPermission(), status.getOwner(), status.getGroup(),
|
status.getPermission(), status.getOwner(),
|
||||||
null, path);
|
status.getGroup(), null, path));
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
LOG.warn("Cannot get one of the children's(" + path
|
LOG.warn("Cannot get one of the children's(" + path
|
||||||
+ ") target path(" + link.getTargetFileSystem().getUri()
|
+ ") target path(" + link.getTargetFileSystem().getUri()
|
||||||
|
@ -1270,52 +1274,59 @@ public class ViewFileSystem extends FileSystem {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result[i++] =
|
internalDirStatuses.add(
|
||||||
new FileStatus(0, true, 0, 0, creationTime, creationTime,
|
new FileStatus(0, true, 0, 0, creationTime, creationTime,
|
||||||
PERMISSION_555, ugi.getShortUserName(),
|
PERMISSION_555, ugi.getShortUserName(),
|
||||||
ugi.getPrimaryGroupName(), path);
|
ugi.getPrimaryGroupName(), path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FileStatus[] internalDirStatusesMergedWithFallBack = internalDirStatuses
|
||||||
|
.toArray(new FileStatus[internalDirStatuses.size()]);
|
||||||
if (fallbackStatuses.length > 0) {
|
if (fallbackStatuses.length > 0) {
|
||||||
return consolidateFileStatuses(fallbackStatuses, result);
|
internalDirStatusesMergedWithFallBack =
|
||||||
} else {
|
merge(fallbackStatuses, internalDirStatusesMergedWithFallBack);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
// Links will always have precedence than internalDir or fallback paths.
|
||||||
|
return merge(linkStatuses.toArray(new FileStatus[linkStatuses.size()]),
|
||||||
|
internalDirStatusesMergedWithFallBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileStatus[] consolidateFileStatuses(FileStatus[] fallbackStatuses,
|
private FileStatus[] merge(FileStatus[] toStatuses,
|
||||||
FileStatus[] mountPointStatuses) {
|
FileStatus[] fromStatuses) {
|
||||||
ArrayList<FileStatus> result = new ArrayList<>();
|
ArrayList<FileStatus> result = new ArrayList<>();
|
||||||
Set<String> pathSet = new HashSet<>();
|
Set<String> pathSet = new HashSet<>();
|
||||||
for (FileStatus status : mountPointStatuses) {
|
for (FileStatus status : toStatuses) {
|
||||||
result.add(status);
|
result.add(status);
|
||||||
pathSet.add(status.getPath().getName());
|
pathSet.add(status.getPath().getName());
|
||||||
}
|
}
|
||||||
for (FileStatus status : fallbackStatuses) {
|
for (FileStatus status : fromStatuses) {
|
||||||
if (!pathSet.contains(status.getPath().getName())) {
|
if (!pathSet.contains(status.getPath().getName())) {
|
||||||
result.add(status);
|
result.add(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toArray(new FileStatus[0]);
|
return result.toArray(new FileStatus[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileStatus[] listStatusForFallbackLink() throws IOException {
|
private FileStatus[] listStatusForFallbackLink() throws IOException {
|
||||||
if (theInternalDir.isRoot() &&
|
if (this.fsState.getRootFallbackLink() != null) {
|
||||||
theInternalDir.getFallbackLink() != null) {
|
FileSystem linkedFallbackFs =
|
||||||
FileSystem linkedFs =
|
this.fsState.getRootFallbackLink().getTargetFileSystem();
|
||||||
theInternalDir.getFallbackLink().getTargetFileSystem();
|
Path p = Path.getPathWithoutSchemeAndAuthority(
|
||||||
// Fallback link is only applicable for root
|
new Path(theInternalDir.fullPath));
|
||||||
FileStatus[] statuses = linkedFs.listStatus(new Path("/"));
|
if (theInternalDir.isRoot() || linkedFallbackFs.exists(p)) {
|
||||||
|
FileStatus[] statuses = linkedFallbackFs.listStatus(p);
|
||||||
for (FileStatus status : statuses) {
|
for (FileStatus status : statuses) {
|
||||||
// Fix the path back to viewfs scheme
|
// Fix the path back to viewfs scheme
|
||||||
|
Path pathFromConfiguredFallbackRoot =
|
||||||
|
new Path(p, status.getPath().getName());
|
||||||
status.setPath(
|
status.setPath(
|
||||||
new Path(myUri.toString(), status.getPath().getName()));
|
new Path(myUri.toString(), pathFromConfiguredFallbackRoot));
|
||||||
}
|
}
|
||||||
return statuses;
|
return statuses;
|
||||||
} else {
|
|
||||||
return new FileStatus[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new FileStatus[0];
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mkdirs(Path dir, FsPermission permission)
|
public boolean mkdirs(Path dir, FsPermission permission)
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.apache.hadoop.fs.FSDataInputStream;
|
||||||
import org.apache.hadoop.fs.FSDataOutputStream;
|
import org.apache.hadoop.fs.FSDataOutputStream;
|
||||||
import org.apache.hadoop.fs.FileAlreadyExistsException;
|
import org.apache.hadoop.fs.FileAlreadyExistsException;
|
||||||
import org.apache.hadoop.fs.FileChecksum;
|
import org.apache.hadoop.fs.FileChecksum;
|
||||||
|
import org.apache.hadoop.fs.FileContext;
|
||||||
import org.apache.hadoop.fs.FileStatus;
|
import org.apache.hadoop.fs.FileStatus;
|
||||||
import org.apache.hadoop.fs.FsConstants;
|
import org.apache.hadoop.fs.FsConstants;
|
||||||
import org.apache.hadoop.fs.FsServerDefaults;
|
import org.apache.hadoop.fs.FsServerDefaults;
|
||||||
|
@ -236,7 +237,8 @@ public class ViewFs extends AbstractFileSystem {
|
||||||
@Override
|
@Override
|
||||||
protected AbstractFileSystem getTargetFileSystem(
|
protected AbstractFileSystem getTargetFileSystem(
|
||||||
final INodeDir<AbstractFileSystem> dir) throws URISyntaxException {
|
final INodeDir<AbstractFileSystem> dir) throws URISyntaxException {
|
||||||
return new InternalDirOfViewFs(dir, creationTime, ugi, getUri());
|
return new InternalDirOfViewFs(dir, creationTime, ugi, getUri(), this,
|
||||||
|
config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -455,6 +457,11 @@ public class ViewFs extends AbstractFileSystem {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
|
* Note: listStatus considers listing from fallbackLink if available. If the
|
||||||
|
* same directory path is present in configured mount path as well as in
|
||||||
|
* fallback fs, then only the fallback path will be listed in the returned
|
||||||
|
* result except for link.
|
||||||
|
*
|
||||||
* If any of the the immediate children of the given path f is a symlink(mount
|
* If any of the the immediate children of the given path f is a symlink(mount
|
||||||
* link), the returned FileStatus object of that children would be represented
|
* link), the returned FileStatus object of that children would be represented
|
||||||
* as a symlink. It will not be resolved to the target path and will not get
|
* as a symlink. It will not be resolved to the target path and will not get
|
||||||
|
@ -880,15 +887,20 @@ public class ViewFs extends AbstractFileSystem {
|
||||||
final long creationTime; // of the the mount table
|
final long creationTime; // of the the mount table
|
||||||
final UserGroupInformation ugi; // the user/group of user who created mtable
|
final UserGroupInformation ugi; // the user/group of user who created mtable
|
||||||
final URI myUri; // the URI of the outer ViewFs
|
final URI myUri; // the URI of the outer ViewFs
|
||||||
|
private InodeTree<AbstractFileSystem> fsState;
|
||||||
|
private Configuration conf;
|
||||||
|
|
||||||
public InternalDirOfViewFs(final InodeTree.INodeDir<AbstractFileSystem> dir,
|
public InternalDirOfViewFs(final InodeTree.INodeDir<AbstractFileSystem> dir,
|
||||||
final long cTime, final UserGroupInformation ugi, final URI uri)
|
final long cTime, final UserGroupInformation ugi, final URI uri,
|
||||||
|
InodeTree fsState, Configuration conf)
|
||||||
throws URISyntaxException {
|
throws URISyntaxException {
|
||||||
super(FsConstants.VIEWFS_URI, FsConstants.VIEWFS_SCHEME, false, -1);
|
super(FsConstants.VIEWFS_URI, FsConstants.VIEWFS_SCHEME, false, -1);
|
||||||
theInternalDir = dir;
|
theInternalDir = dir;
|
||||||
creationTime = cTime;
|
creationTime = cTime;
|
||||||
this.ugi = ugi;
|
this.ugi = ugi;
|
||||||
myUri = uri;
|
myUri = uri;
|
||||||
|
this.fsState = fsState;
|
||||||
|
this.conf = conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static private void checkPathIsSlash(final Path f) throws IOException {
|
static private void checkPathIsSlash(final Path f) throws IOException {
|
||||||
|
@ -1015,7 +1027,8 @@ public class ViewFs extends AbstractFileSystem {
|
||||||
public FileStatus[] listStatus(final Path f) throws IOException {
|
public FileStatus[] listStatus(final Path f) throws IOException {
|
||||||
checkPathIsSlash(f);
|
checkPathIsSlash(f);
|
||||||
FileStatus[] fallbackStatuses = listStatusForFallbackLink();
|
FileStatus[] fallbackStatuses = listStatusForFallbackLink();
|
||||||
FileStatus[] result = new FileStatus[theInternalDir.getChildren().size()];
|
Set<FileStatus> linkStatuses = new HashSet<>();
|
||||||
|
Set<FileStatus> internalDirStatuses = new HashSet<>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Entry<String, INode<AbstractFileSystem>> iEntry :
|
for (Entry<String, INode<AbstractFileSystem>> iEntry :
|
||||||
theInternalDir.getChildren().entrySet()) {
|
theInternalDir.getChildren().entrySet()) {
|
||||||
|
@ -1029,11 +1042,10 @@ public class ViewFs extends AbstractFileSystem {
|
||||||
// To maintain backward compatibility, with default option(showing
|
// To maintain backward compatibility, with default option(showing
|
||||||
// mount links as symlinks), we will represent target link as
|
// mount links as symlinks), we will represent target link as
|
||||||
// symlink and rest other properties are belongs to mount link only.
|
// symlink and rest other properties are belongs to mount link only.
|
||||||
result[i++] =
|
linkStatuses.add(
|
||||||
new FileStatus(0, false, 0, 0, creationTime, creationTime,
|
new FileStatus(0, false, 0, 0, creationTime, creationTime,
|
||||||
PERMISSION_555, ugi.getShortUserName(),
|
PERMISSION_555, ugi.getShortUserName(),
|
||||||
ugi.getPrimaryGroupName(), link.getTargetLink(),
|
ugi.getPrimaryGroupName(), link.getTargetLink(), path));
|
||||||
path);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1049,11 +1061,12 @@ public class ViewFs extends AbstractFileSystem {
|
||||||
FileStatus status =
|
FileStatus status =
|
||||||
((ChRootedFs) link.getTargetFileSystem()).getMyFs()
|
((ChRootedFs) link.getTargetFileSystem()).getMyFs()
|
||||||
.getFileStatus(new Path(linkedPath));
|
.getFileStatus(new Path(linkedPath));
|
||||||
result[i++] = new FileStatus(status.getLen(), status.isDirectory(),
|
linkStatuses.add(
|
||||||
|
new FileStatus(status.getLen(), status.isDirectory(),
|
||||||
status.getReplication(), status.getBlockSize(),
|
status.getReplication(), status.getBlockSize(),
|
||||||
status.getModificationTime(), status.getAccessTime(),
|
status.getModificationTime(), status.getAccessTime(),
|
||||||
status.getPermission(), status.getOwner(), status.getGroup(),
|
status.getPermission(), status.getOwner(),
|
||||||
null, path);
|
status.getGroup(), null, path));
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
LOG.warn("Cannot get one of the children's(" + path
|
LOG.warn("Cannot get one of the children's(" + path
|
||||||
+ ") target path(" + link.getTargetFileSystem().getUri()
|
+ ") target path(" + link.getTargetFileSystem().getUri()
|
||||||
|
@ -1061,52 +1074,63 @@ public class ViewFs extends AbstractFileSystem {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result[i++] =
|
internalDirStatuses.add(
|
||||||
new FileStatus(0, true, 0, 0, creationTime, creationTime,
|
new FileStatus(0, true, 0, 0, creationTime, creationTime,
|
||||||
PERMISSION_555, ugi.getShortUserName(),
|
PERMISSION_555, ugi.getShortUserName(),
|
||||||
ugi.getGroupNames()[0], path);
|
ugi.getPrimaryGroupName(), path));
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fallbackStatuses.length > 0) {
|
|
||||||
return consolidateFileStatuses(fallbackStatuses, result);
|
|
||||||
} else {
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileStatus[] consolidateFileStatuses(FileStatus[] fallbackStatuses,
|
FileStatus[] internalDirStatusesMergedWithFallBack = internalDirStatuses
|
||||||
FileStatus[] mountPointStatuses) {
|
.toArray(new FileStatus[internalDirStatuses.size()]);
|
||||||
|
if (fallbackStatuses.length > 0) {
|
||||||
|
internalDirStatusesMergedWithFallBack =
|
||||||
|
merge(fallbackStatuses, internalDirStatusesMergedWithFallBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Links will always have precedence than internalDir or fallback paths.
|
||||||
|
return merge(linkStatuses.toArray(new FileStatus[linkStatuses.size()]),
|
||||||
|
internalDirStatusesMergedWithFallBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileStatus[] merge(FileStatus[] toStatuses,
|
||||||
|
FileStatus[] fromStatuses) {
|
||||||
ArrayList<FileStatus> result = new ArrayList<>();
|
ArrayList<FileStatus> result = new ArrayList<>();
|
||||||
Set<String> pathSet = new HashSet<>();
|
Set<String> pathSet = new HashSet<>();
|
||||||
for (FileStatus status : mountPointStatuses) {
|
for (FileStatus status : toStatuses) {
|
||||||
result.add(status);
|
result.add(status);
|
||||||
pathSet.add(status.getPath().getName());
|
pathSet.add(status.getPath().getName());
|
||||||
}
|
}
|
||||||
for (FileStatus status : fallbackStatuses) {
|
for (FileStatus status : fromStatuses) {
|
||||||
if (!pathSet.contains(status.getPath().getName())) {
|
if (!pathSet.contains(status.getPath().getName())) {
|
||||||
result.add(status);
|
result.add(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toArray(new FileStatus[0]);
|
return result.toArray(new FileStatus[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileStatus[] listStatusForFallbackLink() throws IOException {
|
private FileStatus[] listStatusForFallbackLink() throws IOException {
|
||||||
if (theInternalDir.isRoot() &&
|
if (fsState.getRootFallbackLink() != null) {
|
||||||
theInternalDir.getFallbackLink() != null) {
|
AbstractFileSystem linkedFallbackFs =
|
||||||
AbstractFileSystem linkedFs =
|
fsState.getRootFallbackLink().getTargetFileSystem();
|
||||||
theInternalDir.getFallbackLink().getTargetFileSystem();
|
Path p = Path.getPathWithoutSchemeAndAuthority(
|
||||||
|
new Path(theInternalDir.fullPath));
|
||||||
|
if (theInternalDir.isRoot() || FileContext
|
||||||
|
.getFileContext(linkedFallbackFs, conf).util().exists(p)) {
|
||||||
// Fallback link is only applicable for root
|
// Fallback link is only applicable for root
|
||||||
FileStatus[] statuses = linkedFs.listStatus(new Path("/"));
|
FileStatus[] statuses = linkedFallbackFs.listStatus(p);
|
||||||
for (FileStatus status : statuses) {
|
for (FileStatus status : statuses) {
|
||||||
// Fix the path back to viewfs scheme
|
// Fix the path back to viewfs scheme
|
||||||
|
Path pathFromConfiguredFallbackRoot =
|
||||||
|
new Path(p, status.getPath().getName());
|
||||||
status.setPath(
|
status.setPath(
|
||||||
new Path(myUri.toString(), status.getPath().getName()));
|
new Path(myUri.toString(), pathFromConfiguredFallbackRoot));
|
||||||
}
|
}
|
||||||
return statuses;
|
return statuses;
|
||||||
} else {
|
|
||||||
return new FileStatus[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new FileStatus[0];
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mkdir(final Path dir, final FsPermission permission,
|
public void mkdir(final Path dir, final FsPermission permission,
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.apache.hadoop.fs.viewfs;
|
package org.apache.hadoop.fs.viewfs;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ import org.apache.hadoop.fs.FileSystem;
|
||||||
import org.apache.hadoop.fs.FileSystemTestHelper;
|
import org.apache.hadoop.fs.FileSystemTestHelper;
|
||||||
import org.apache.hadoop.fs.FsConstants;
|
import org.apache.hadoop.fs.FsConstants;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.fs.permission.FsPermission;
|
||||||
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
||||||
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
||||||
import org.apache.hadoop.hdfs.MiniDFSNNTopology;
|
import org.apache.hadoop.hdfs.MiniDFSNNTopology;
|
||||||
|
@ -343,8 +345,8 @@ public class TestViewFileSystemLinkFallback extends ViewFileSystemBaseTest {
|
||||||
afterFallback.add(stat.getPath());
|
afterFallback.add(stat.getPath());
|
||||||
}
|
}
|
||||||
afterFallback.removeAll(beforeFallback);
|
afterFallback.removeAll(beforeFallback);
|
||||||
assertTrue("The same directory name in fallback link should be shaded",
|
assertEquals("The same directory name in fallback link should be shaded",
|
||||||
afterFallback.size() == 1);
|
1, afterFallback.size());
|
||||||
Path[] fallbackArray = new Path[afterFallback.size()];
|
Path[] fallbackArray = new Path[afterFallback.size()];
|
||||||
// Only user1 should be listed as fallback link
|
// Only user1 should be listed as fallback link
|
||||||
Path expected = new Path(viewFsUri.toString(), "user1");
|
Path expected = new Path(viewFsUri.toString(), "user1");
|
||||||
|
@ -359,4 +361,249 @@ public class TestViewFileSystemLinkFallback extends ViewFileSystemBaseTest {
|
||||||
assertTrue(vfs.getFileStatus(childDir).isDirectory());
|
assertTrue(vfs.getFileStatus(childDir).isDirectory());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests ListStatus on non-link parent with fallback configured.
|
||||||
|
* =============================Example.======================================
|
||||||
|
* ===== Fallback path tree =============== Mount Path Tree ==================
|
||||||
|
* ===========================================================================
|
||||||
|
* * / ***** / *****************
|
||||||
|
* * / ***** / *****************
|
||||||
|
* * user1 ***** user1 *****************
|
||||||
|
* * / ***** / *****************
|
||||||
|
* * hive ***** hive *****************
|
||||||
|
* * / \ ***** / *****************
|
||||||
|
* * warehouse warehouse1 ***** warehouse *****************
|
||||||
|
* * (-rwxr--r--) ***** (-r-xr--r--) *****************
|
||||||
|
* * / ***** / *****************
|
||||||
|
* * partition-0 ***** partition-0 *****************
|
||||||
|
* ===========================================================================
|
||||||
|
* ===========================================================================
|
||||||
|
* *** ls /user1/hive *********
|
||||||
|
* *** viewfs://default/user1/hive/warehouse (-rwxr--r--) *********
|
||||||
|
* *** viewfs://default/user1/hive/warehouse1 *********
|
||||||
|
* ===========================================================================
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testListingWithFallbackLinkWithSameMountDirectoryTree()
|
||||||
|
throws Exception {
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
conf.setBoolean(Constants.CONFIG_VIEWFS_MOUNT_LINKS_AS_SYMLINKS, false);
|
||||||
|
ConfigUtil.addLink(conf, "/user1/hive/warehouse/partition-0",
|
||||||
|
new Path(targetTestRoot.toString()).toUri());
|
||||||
|
// Creating multiple directories path under the fallback directory.
|
||||||
|
// "/user1/hive/warehouse/partition-0" directory already exists as
|
||||||
|
// configured mount point.
|
||||||
|
Path dir1 = new Path(targetTestRoot,
|
||||||
|
"fallbackDir/user1/hive/warehouse/partition-0");
|
||||||
|
Path dir2 = new Path(targetTestRoot, "fallbackDir/user1/hive/warehouse1");
|
||||||
|
fsTarget.mkdirs(dir1);
|
||||||
|
fsTarget.mkdirs(dir2);
|
||||||
|
fsTarget.setPermission(new Path(targetTestRoot, "fallbackDir/user1/hive/"),
|
||||||
|
FsPermission.valueOf("-rwxr--r--"));
|
||||||
|
URI viewFsUri = new URI(FsConstants.VIEWFS_SCHEME,
|
||||||
|
Constants.CONFIG_VIEWFS_DEFAULT_MOUNT_TABLE, "/", null, null);
|
||||||
|
|
||||||
|
HashSet<Path> beforeFallback = new HashSet<>();
|
||||||
|
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
|
||||||
|
for (FileStatus stat : vfs
|
||||||
|
.listStatus(new Path(viewFsUri.toString(), "/user1/hive/"))) {
|
||||||
|
beforeFallback.add(stat.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigUtil
|
||||||
|
.addLinkFallback(conf, new Path(targetTestRoot, "fallbackDir").toUri());
|
||||||
|
|
||||||
|
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
|
||||||
|
HashSet<Path> afterFallback = new HashSet<>();
|
||||||
|
for (FileStatus stat : vfs
|
||||||
|
.listStatus(new Path(viewFsUri.toString(), "/user1/hive/"))) {
|
||||||
|
afterFallback.add(stat.getPath());
|
||||||
|
if (dir1.getName().equals(stat.getPath().getName())) {
|
||||||
|
// make sure fallback dir listed out with correct permissions, but not
|
||||||
|
// with link permissions.
|
||||||
|
assertEquals(FsPermission.valueOf("-rwxr--r--"),
|
||||||
|
stat.getPermission());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//viewfs://default/user1/hive/warehouse
|
||||||
|
afterFallback.removeAll(beforeFallback);
|
||||||
|
assertEquals("The same directory name in fallback link should be shaded",
|
||||||
|
1, afterFallback.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests ListStatus on link parent with fallback configured.
|
||||||
|
* =============================Example.======================================
|
||||||
|
* ===== Fallback path tree =============== Mount Path Tree ==================
|
||||||
|
* ===========================================================================
|
||||||
|
* * / ***** / **********
|
||||||
|
* * / ***** / **********
|
||||||
|
* * user1 ***** user1 **********
|
||||||
|
* * / ***** / **********
|
||||||
|
* * hive ***** hive **********
|
||||||
|
* * / \ ***** / **********
|
||||||
|
* * warehouse warehouse1 ***** warehouse **********
|
||||||
|
* * (-rwxr--r--) ***** (-r-xr--r--) **********
|
||||||
|
* * / ***** / **********
|
||||||
|
* * partition-0 ***** partition-0 ---> targetTestRoot **********
|
||||||
|
* * ***** (-r-xr--r--) (-rwxr--rw-) **********
|
||||||
|
* ===========================================================================
|
||||||
|
* ===========================================================================
|
||||||
|
* *** ls /user1/hive/warehouse **
|
||||||
|
* *** viewfs://default/user1/hive/warehouse/partition-0 (-rwxr--rw-) **
|
||||||
|
* ===========================================================================
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLSOnLinkParentWithFallbackLinkWithSameMountDirectoryTree()
|
||||||
|
throws Exception {
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
conf.setBoolean(Constants.CONFIG_VIEWFS_MOUNT_LINKS_AS_SYMLINKS, false);
|
||||||
|
ConfigUtil.addLink(conf, "/user1/hive/warehouse/partition-0",
|
||||||
|
new Path(targetTestRoot.toString()).toUri());
|
||||||
|
// Creating multiple directories path under the fallback directory.
|
||||||
|
// "/user1/hive/warehouse/partition-0" directory already exists as
|
||||||
|
// configured mount point.
|
||||||
|
Path dir1 = new Path(targetTestRoot,
|
||||||
|
"fallbackDir/user1/hive/warehouse/partition-0");
|
||||||
|
Path dir2 = new Path(targetTestRoot, "fallbackDir/user1/hive/warehouse1");
|
||||||
|
fsTarget.mkdirs(dir1);
|
||||||
|
fsTarget.mkdirs(dir2);
|
||||||
|
fsTarget.setPermission(new Path(targetTestRoot,
|
||||||
|
"fallbackDir/user1/hive/warehouse/partition-0"),
|
||||||
|
FsPermission.valueOf("-rwxr--r--"));
|
||||||
|
fsTarget.setPermission(targetTestRoot, FsPermission.valueOf("-rwxr--rw-"));
|
||||||
|
URI viewFsUri = new URI(FsConstants.VIEWFS_SCHEME,
|
||||||
|
Constants.CONFIG_VIEWFS_DEFAULT_MOUNT_TABLE, "/", null, null);
|
||||||
|
|
||||||
|
HashSet<Path> beforeFallback = new HashSet<>();
|
||||||
|
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
|
||||||
|
for (FileStatus stat : vfs.listStatus(
|
||||||
|
new Path(viewFsUri.toString(), "/user1/hive/warehouse/"))) {
|
||||||
|
beforeFallback.add(stat.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigUtil
|
||||||
|
.addLinkFallback(conf, new Path(targetTestRoot, "fallbackDir").toUri());
|
||||||
|
|
||||||
|
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
|
||||||
|
HashSet<Path> afterFallback = new HashSet<>();
|
||||||
|
for (FileStatus stat : vfs.listStatus(
|
||||||
|
new Path(viewFsUri.toString(), "/user1/hive/warehouse/"))) {
|
||||||
|
afterFallback.add(stat.getPath());
|
||||||
|
if (dir1.getName().equals(stat.getPath().getName())) {
|
||||||
|
// make sure fallback dir listed out with correct permissions, but not
|
||||||
|
// with link permissions.
|
||||||
|
assertEquals(FsPermission.valueOf("-rwxr--rw-"),
|
||||||
|
stat.getPermission());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afterFallback.removeAll(beforeFallback);
|
||||||
|
assertEquals("Just to make sure paths are same.", 0,
|
||||||
|
afterFallback.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests ListStatus on root with fallback configured.
|
||||||
|
* =============================Example.=======================================
|
||||||
|
* ===== Fallback path tree =============== Mount Path Tree ==================
|
||||||
|
* ===========================================================================
|
||||||
|
* * / / ***** / ***
|
||||||
|
* * / / ***** / ***
|
||||||
|
* * user1 user2 ***** user1 ---> targetTestRoot ***
|
||||||
|
* *(-r-xr--r--) (-r-xr--r--) ***** (-rwxr--rw-) ***
|
||||||
|
* ===========================================================================
|
||||||
|
* ===========================================================================
|
||||||
|
* *** ls /user1/hive/warehouse **
|
||||||
|
* *** viewfs://default/user1(-rwxr--rw-) **
|
||||||
|
* *** viewfs://default/user2(-r-xr--r--) **
|
||||||
|
* ===========================================================================
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLSOnRootWithFallbackLinkWithSameMountDirectories()
|
||||||
|
throws Exception {
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
conf.setBoolean(Constants.CONFIG_VIEWFS_MOUNT_LINKS_AS_SYMLINKS, false);
|
||||||
|
ConfigUtil
|
||||||
|
.addLink(conf, "/user1", new Path(targetTestRoot.toString()).toUri());
|
||||||
|
// Creating multiple directories path under the fallback directory.
|
||||||
|
// "/user1" directory already exists as configured mount point.
|
||||||
|
Path dir1 = new Path(targetTestRoot, "fallbackDir/user1");
|
||||||
|
Path dir2 = new Path(targetTestRoot, "fallbackDir/user2");
|
||||||
|
fsTarget.mkdirs(dir1);
|
||||||
|
fsTarget.mkdirs(dir2, FsPermission.valueOf("-rwxr--r--"));
|
||||||
|
fsTarget.setPermission(targetTestRoot, FsPermission.valueOf("-rwxr--rw-"));
|
||||||
|
URI viewFsUri = new URI(FsConstants.VIEWFS_SCHEME,
|
||||||
|
Constants.CONFIG_VIEWFS_DEFAULT_MOUNT_TABLE, "/", null, null);
|
||||||
|
|
||||||
|
HashSet<Path> beforeFallback = new HashSet<>();
|
||||||
|
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
|
||||||
|
for (FileStatus stat : vfs
|
||||||
|
.listStatus(new Path(viewFsUri.toString(), "/"))) {
|
||||||
|
beforeFallback.add(stat.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigUtil
|
||||||
|
.addLinkFallback(conf, new Path(targetTestRoot, "fallbackDir").toUri());
|
||||||
|
|
||||||
|
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
|
||||||
|
HashSet<Path> afterFallback = new HashSet<>();
|
||||||
|
for (FileStatus stat : vfs
|
||||||
|
.listStatus(new Path(viewFsUri.toString(), "/"))) {
|
||||||
|
afterFallback.add(stat.getPath());
|
||||||
|
if (dir1.getName().equals(stat.getPath().getName())) {
|
||||||
|
// make sure fallback dir listed out with correct permissions, but not
|
||||||
|
// with link permissions.
|
||||||
|
assertEquals(FsPermission.valueOf("-rwxr--rw-"),
|
||||||
|
stat.getPermission());
|
||||||
|
} else {
|
||||||
|
assertEquals("Path is: " + stat.getPath(),
|
||||||
|
FsPermission.valueOf("-rwxr--r--"), stat.getPermission());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afterFallback.removeAll(beforeFallback);
|
||||||
|
assertEquals(1, afterFallback.size());
|
||||||
|
assertEquals("/user2 dir from fallback should be listed.", "user2",
|
||||||
|
afterFallback.iterator().next().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLSOnLinkParentWhereMountLinkMatchesWithAFileUnderFallback()
|
||||||
|
throws Exception {
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
conf.setBoolean(Constants.CONFIG_VIEWFS_MOUNT_LINKS_AS_SYMLINKS, true);
|
||||||
|
ConfigUtil.addLink(conf, "/user1/hive/warehouse/part-0",
|
||||||
|
new Path(targetTestRoot.toString()).toUri());
|
||||||
|
// Create a file path in fallback matching to the path of mount link.
|
||||||
|
Path file1 =
|
||||||
|
new Path(targetTestRoot, "fallbackDir/user1/hive/warehouse/part-0");
|
||||||
|
fsTarget.createNewFile(file1);
|
||||||
|
Path dir2 = new Path(targetTestRoot, "fallbackDir/user1/hive/warehouse1");
|
||||||
|
fsTarget.mkdirs(dir2);
|
||||||
|
URI viewFsUri = new URI(FsConstants.VIEWFS_SCHEME,
|
||||||
|
Constants.CONFIG_VIEWFS_DEFAULT_MOUNT_TABLE, "/", null, null);
|
||||||
|
|
||||||
|
ConfigUtil
|
||||||
|
.addLinkFallback(conf, new Path(targetTestRoot, "fallbackDir").toUri());
|
||||||
|
|
||||||
|
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
|
||||||
|
for (FileStatus stat : vfs.listStatus(
|
||||||
|
new Path(viewFsUri.toString(), "/user1/hive/warehouse/"))) {
|
||||||
|
if (file1.getName().equals(stat.getPath().getName())) {
|
||||||
|
// Link represents as symlink.
|
||||||
|
assertFalse(stat.isFile());
|
||||||
|
assertFalse(stat.isDirectory());
|
||||||
|
assertTrue(stat.isSymlink());
|
||||||
|
Path fileUnderDir = new Path(stat.getPath(), "check");
|
||||||
|
assertTrue(vfs.mkdirs(fileUnderDir)); // Creating dir under target
|
||||||
|
assertTrue(fsTarget
|
||||||
|
.exists(new Path(targetTestRoot, fileUnderDir.getName())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue