Skip to content

Commit 2a610f9

Browse files
committed
HADOOP-17024. ListStatus on ViewFS root should list the linkFallBack root
1 parent 743c2e9 commit 2a610f9

File tree

3 files changed

+128
-1
lines changed

3 files changed

+128
-1
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/viewfs/InodeTree.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ static class INodeDir<T> extends INode<T> {
123123
private final Map<String, INode<T>> children = new HashMap<>();
124124
private T internalDirFs = null; //filesystem of this internal directory
125125
private boolean isRoot = false;
126+
private INodeLink<T> fallbackLink = null;
126127

127128
INodeDir(final String pathToNode, final UserGroupInformation aUgi) {
128129
super(pathToNode, aUgi);
@@ -149,6 +150,17 @@ boolean isRoot() {
149150
return isRoot;
150151
}
151152

153+
INodeLink<T> getFallbackLink() {
154+
return fallbackLink;
155+
}
156+
157+
void addFallbackLink(INodeLink<T> fallbackLink) throws IOException {
158+
if (!isRoot) {
159+
throw new IOException("fallbackLink can only be set for root");
160+
}
161+
this.fallbackLink = fallbackLink;
162+
}
163+
152164
Map<String, INode<T>> getChildren() {
153165
return Collections.unmodifiableMap(children);
154166
}
@@ -580,6 +592,7 @@ protected InodeTree(final Configuration config, final String viewName)
580592
}
581593
}
582594
rootFallbackLink = fallbackLink;
595+
getRootDir().addFallbackLink(rootFallbackLink);
583596
}
584597

585598
if (!gotMountTableEntry) {

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/viewfs/ViewFileSystem.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,6 +1204,7 @@ public FileStatus getFileStatus(Path f) throws IOException {
12041204
public FileStatus[] listStatus(Path f) throws AccessControlException,
12051205
FileNotFoundException, IOException {
12061206
checkPathIsSlash(f);
1207+
FileStatus[] fallbackStatuses = listStatusForFallbackLink();
12071208
FileStatus[] result = new FileStatus[theInternalDir.getChildren().size()];
12081209
int i = 0;
12091210
for (Entry<String, INode<FileSystem>> iEntry :
@@ -1226,7 +1227,39 @@ public FileStatus[] listStatus(Path f) throws AccessControlException,
12261227
myUri, null));
12271228
}
12281229
}
1229-
return result;
1230+
if (fallbackStatuses.length > 0) {
1231+
return consolidateFileStatuses(fallbackStatuses, result);
1232+
} else {
1233+
return result;
1234+
}
1235+
}
1236+
1237+
private FileStatus[] consolidateFileStatuses(FileStatus[] fallbackStatuses,
1238+
FileStatus[] mountPointStatuses) {
1239+
ArrayList<FileStatus> result = new ArrayList<>();
1240+
Set<String> pathSet = new HashSet<>();
1241+
int i = 0;
1242+
for (FileStatus status : mountPointStatuses) {
1243+
result.add(status);
1244+
pathSet.add(status.getPath().getName());
1245+
}
1246+
for (FileStatus status : fallbackStatuses) {
1247+
if (!pathSet.contains(status.getPath().getName())) {
1248+
result.add(status);
1249+
}
1250+
}
1251+
return result.toArray(new FileStatus[0]);
1252+
}
1253+
1254+
private FileStatus[] listStatusForFallbackLink() throws IOException {
1255+
if (theInternalDir.isRoot() && theInternalDir.getFallbackLink() != null) {
1256+
URI fallBackUri = theInternalDir.getFallbackLink().targetDirLinkList[0];
1257+
ChRootedFileSystem linkedFs = (ChRootedFileSystem)
1258+
theInternalDir.getFallbackLink().getTargetFileSystem();
1259+
return linkedFs.getMyFs().listStatus(new Path(fallBackUri.toString()));
1260+
} else {
1261+
return new FileStatus[0];
1262+
}
12301263
}
12311264

12321265
@Override

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/fs/viewfs/TestViewFileSystemLinkFallback.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.net.URI;
2727
import java.net.URISyntaxException;
2828

29+
import java.util.HashSet;
2930
import javax.security.auth.login.LoginException;
3031

3132
import org.apache.hadoop.conf.Configuration;
@@ -261,4 +262,84 @@ public void testConfLinkFallbackWithMountPoint() throws Exception {
261262
e.getMessage().contains(expectedErrorMsg));
262263
}
263264
}
265+
266+
/**
267+
* This tests whether the fallback link gets listed for list operation
268+
* of root directory of mount table
269+
* @throws Exception
270+
*/
271+
@Test
272+
public void testListingWithFallbackLink() throws Exception {
273+
Path dir1 = new Path(targetTestRoot, "fallbackDir/dir1");
274+
fsTarget.mkdirs(dir1);
275+
String clusterName = Constants.CONFIG_VIEWFS_DEFAULT_MOUNT_TABLE;
276+
URI viewFsUri = new URI(FsConstants.VIEWFS_SCHEME, clusterName,
277+
"/", null, null);
278+
279+
HashSet<Path> beforeFallback = new HashSet<>();
280+
try(FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
281+
for (FileStatus stat : vfs.listStatus(new Path(viewFsUri.toString()))) {
282+
beforeFallback.add(stat.getPath());
283+
}
284+
}
285+
286+
ConfigUtil.addLinkFallback(conf, clusterName,
287+
new Path(targetTestRoot, "fallbackDir").toUri());
288+
289+
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
290+
HashSet<Path> afterFallback = new HashSet<>();
291+
for (FileStatus stat : vfs.listStatus(new Path(viewFsUri.toString()))) {
292+
afterFallback.add(stat.getPath());
293+
}
294+
afterFallback.removeAll(beforeFallback);
295+
assertTrue("Listing didn't include fallback link",
296+
afterFallback.size() == 1);
297+
Path[] fallbackArray = new Path[afterFallback.size()];
298+
assertEquals("Path did not match" ,
299+
dir1, afterFallback.toArray(fallbackArray)[0]);
300+
}
301+
}
302+
303+
/**
304+
* This tests whether fallback directory gets shaded during list operation
305+
* of root directory of mount table when the same directory name exists as
306+
* mount point as well as in the fallback linked directory
307+
* @throws Exception
308+
*/
309+
@Test
310+
public void testListingWithFallbackLinkWithSameMountDirectories()
311+
throws Exception {
312+
// Creating two directories under the fallback directory.
313+
// "user" directory already exists as configured mount point.
314+
Path dir1 = new Path(targetTestRoot, "fallbackDir/user");
315+
Path dir2 = new Path(targetTestRoot, "fallbackDir/user1");
316+
fsTarget.mkdirs(dir1);
317+
fsTarget.mkdirs(dir2);
318+
String clusterName = Constants.CONFIG_VIEWFS_DEFAULT_MOUNT_TABLE;
319+
URI viewFsUri = new URI(FsConstants.VIEWFS_SCHEME, clusterName,
320+
"/", null, null);
321+
322+
HashSet<Path> beforeFallback = new HashSet<>();
323+
try(FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
324+
for (FileStatus stat : vfs.listStatus(new Path(viewFsUri.toString()))) {
325+
beforeFallback.add(stat.getPath());
326+
}
327+
}
328+
ConfigUtil.addLinkFallback(conf, clusterName,
329+
new Path(targetTestRoot, "fallbackDir").toUri());
330+
331+
try (FileSystem vfs = FileSystem.get(viewFsUri, conf)) {
332+
HashSet<Path> afterFallback = new HashSet<>();
333+
for (FileStatus stat : vfs.listStatus(new Path(viewFsUri.toString()))) {
334+
afterFallback.add(stat.getPath());
335+
}
336+
afterFallback.removeAll(beforeFallback);
337+
assertTrue("The same directory name in fallback link should be shaded",
338+
afterFallback.size() == 1);
339+
Path[] fallbackArray = new Path[afterFallback.size()];
340+
// Only dir2 should be listed as fallback link
341+
assertEquals("Path did not match" ,
342+
dir2, afterFallback.toArray(fallbackArray)[0]);
343+
}
344+
}
264345
}

0 commit comments

Comments
 (0)