4444import org .apache .hadoop .fs .FSDataOutputStream ;
4545import org .apache .hadoop .fs .FileAlreadyExistsException ;
4646import org .apache .hadoop .fs .FileChecksum ;
47+ import org .apache .hadoop .fs .FileContext ;
4748import org .apache .hadoop .fs .FileStatus ;
4849import org .apache .hadoop .fs .FsConstants ;
4950import org .apache .hadoop .fs .FsServerDefaults ;
@@ -236,7 +237,8 @@ protected AbstractFileSystem getTargetFileSystem(final URI uri)
236237 @ Override
237238 protected AbstractFileSystem getTargetFileSystem (
238239 final INodeDir <AbstractFileSystem > dir ) throws URISyntaxException {
239- return new InternalDirOfViewFs (dir , creationTime , ugi , getUri ());
240+ return new InternalDirOfViewFs (dir , creationTime , ugi , getUri (), this ,
241+ config );
240242 }
241243
242244 @ Override
@@ -455,6 +457,11 @@ public LocatedFileStatus getViewFsFileStatus(LocatedFileStatus stat,
455457 /**
456458 * {@inheritDoc}
457459 *
460+ * Note: listStatus considers listing from fallbackLink if available. If the
461+ * same directory path is present in configured mount path as well as in
462+ * fallback fs, then only the fallback path will be listed in the returned
463+ * result except for link.
464+ *
458465 * If any of the the immediate children of the given path f is a symlink(mount
459466 * link), the returned FileStatus object of that children would be represented
460467 * as a symlink. It will not be resolved to the target path and will not get
@@ -880,15 +887,20 @@ static class InternalDirOfViewFs extends AbstractFileSystem {
880887 final long creationTime ; // of the the mount table
881888 final UserGroupInformation ugi ; // the user/group of user who created mtable
882889 final URI myUri ; // the URI of the outer ViewFs
883-
890+ private InodeTree <AbstractFileSystem > fsState ;
891+ private Configuration conf ;
892+
884893 public InternalDirOfViewFs (final InodeTree .INodeDir <AbstractFileSystem > dir ,
885- final long cTime , final UserGroupInformation ugi , final URI uri )
894+ final long cTime , final UserGroupInformation ugi , final URI uri ,
895+ InodeTree fsState , Configuration conf )
886896 throws URISyntaxException {
887897 super (FsConstants .VIEWFS_URI , FsConstants .VIEWFS_SCHEME , false , -1 );
888898 theInternalDir = dir ;
889899 creationTime = cTime ;
890900 this .ugi = ugi ;
891901 myUri = uri ;
902+ this .fsState = fsState ;
903+ this .conf = conf ;
892904 }
893905
894906 static private void checkPathIsSlash (final Path f ) throws IOException {
@@ -1015,7 +1027,8 @@ public int getUriDefaultPort() {
10151027 public FileStatus [] listStatus (final Path f ) throws IOException {
10161028 checkPathIsSlash (f );
10171029 FileStatus [] fallbackStatuses = listStatusForFallbackLink ();
1018- FileStatus [] result = new FileStatus [theInternalDir .getChildren ().size ()];
1030+ Set <FileStatus > linkStatuses = new HashSet <>();
1031+ Set <FileStatus > internalDirStatuses = new HashSet <>();
10191032 int i = 0 ;
10201033 for (Entry <String , INode <AbstractFileSystem >> iEntry :
10211034 theInternalDir .getChildren ().entrySet ()) {
@@ -1029,11 +1042,10 @@ public FileStatus[] listStatus(final Path f) throws IOException {
10291042 // To maintain backward compatibility, with default option(showing
10301043 // mount links as symlinks), we will represent target link as
10311044 // symlink and rest other properties are belongs to mount link only.
1032- result [ i ++] =
1045+ linkStatuses . add (
10331046 new FileStatus (0 , false , 0 , 0 , creationTime , creationTime ,
10341047 PERMISSION_555 , ugi .getShortUserName (),
1035- ugi .getPrimaryGroupName (), link .getTargetLink (),
1036- path );
1048+ ugi .getPrimaryGroupName (), link .getTargetLink (), path ));
10371049 continue ;
10381050 }
10391051
@@ -1049,63 +1061,75 @@ public FileStatus[] listStatus(final Path f) throws IOException {
10491061 FileStatus status =
10501062 ((ChRootedFs ) link .getTargetFileSystem ()).getMyFs ()
10511063 .getFileStatus (new Path (linkedPath ));
1052- result [i ++] = new FileStatus (status .getLen (), status .isDirectory (),
1053- status .getReplication (), status .getBlockSize (),
1054- status .getModificationTime (), status .getAccessTime (),
1055- status .getPermission (), status .getOwner (), status .getGroup (),
1056- null , path );
1064+ linkStatuses .add (
1065+ new FileStatus (status .getLen (), status .isDirectory (),
1066+ status .getReplication (), status .getBlockSize (),
1067+ status .getModificationTime (), status .getAccessTime (),
1068+ status .getPermission (), status .getOwner (),
1069+ status .getGroup (), null , path ));
10571070 } catch (FileNotFoundException ex ) {
10581071 LOG .warn ("Cannot get one of the children's(" + path
10591072 + ") target path(" + link .getTargetFileSystem ().getUri ()
10601073 + ") file status." , ex );
10611074 throw ex ;
10621075 }
10631076 } else {
1064- result [ i ++] =
1077+ internalDirStatuses . add (
10651078 new FileStatus (0 , true , 0 , 0 , creationTime , creationTime ,
10661079 PERMISSION_555 , ugi .getShortUserName (),
1067- ugi .getGroupNames ()[ 0 ] , path );
1080+ ugi .getPrimaryGroupName () , path ) );
10681081 }
10691082 }
1083+
1084+ FileStatus [] internalDirStatusesMergedWithFallBack = internalDirStatuses
1085+ .toArray (new FileStatus [internalDirStatuses .size ()]);
10701086 if (fallbackStatuses .length > 0 ) {
1071- return consolidateFileStatuses (fallbackStatuses , result );
1072- } else {
1073- return result ;
1087+ internalDirStatusesMergedWithFallBack =
1088+ merge (fallbackStatuses , internalDirStatusesMergedWithFallBack );
10741089 }
1090+
1091+ // Links will always have precedence than internalDir or fallback paths.
1092+ return merge (linkStatuses .toArray (new FileStatus [linkStatuses .size ()]),
1093+ internalDirStatusesMergedWithFallBack );
10751094 }
10761095
1077- private FileStatus [] consolidateFileStatuses (FileStatus [] fallbackStatuses ,
1078- FileStatus [] mountPointStatuses ) {
1096+ private FileStatus [] merge (FileStatus [] toStatuses ,
1097+ FileStatus [] fromStatuses ) {
10791098 ArrayList <FileStatus > result = new ArrayList <>();
10801099 Set <String > pathSet = new HashSet <>();
1081- for (FileStatus status : mountPointStatuses ) {
1100+ for (FileStatus status : toStatuses ) {
10821101 result .add (status );
10831102 pathSet .add (status .getPath ().getName ());
10841103 }
1085- for (FileStatus status : fallbackStatuses ) {
1104+ for (FileStatus status : fromStatuses ) {
10861105 if (!pathSet .contains (status .getPath ().getName ())) {
10871106 result .add (status );
10881107 }
10891108 }
1090- return result .toArray (new FileStatus [0 ]);
1109+ return result .toArray (new FileStatus [result . size () ]);
10911110 }
10921111
10931112 private FileStatus [] listStatusForFallbackLink () throws IOException {
1094- if (theInternalDir .isRoot () &&
1095- theInternalDir .getFallbackLink () != null ) {
1096- AbstractFileSystem linkedFs =
1097- theInternalDir .getFallbackLink ().getTargetFileSystem ();
1098- // Fallback link is only applicable for root
1099- FileStatus [] statuses = linkedFs .listStatus (new Path ("/" ));
1100- for (FileStatus status : statuses ) {
1101- // Fix the path back to viewfs scheme
1102- status .setPath (
1103- new Path (myUri .toString (), status .getPath ().getName ()));
1113+ if (fsState .getRootFallbackLink () != null ) {
1114+ AbstractFileSystem linkedFallbackFs =
1115+ fsState .getRootFallbackLink ().getTargetFileSystem ();
1116+ Path p = Path .getPathWithoutSchemeAndAuthority (
1117+ new Path (theInternalDir .fullPath ));
1118+ if (theInternalDir .isRoot () || FileContext
1119+ .getFileContext (linkedFallbackFs , conf ).util ().exists (p )) {
1120+ // Fallback link is only applicable for root
1121+ FileStatus [] statuses = linkedFallbackFs .listStatus (p );
1122+ for (FileStatus status : statuses ) {
1123+ // Fix the path back to viewfs scheme
1124+ Path pathFromConfiguredFallbackRoot =
1125+ new Path (p , status .getPath ().getName ());
1126+ status .setPath (
1127+ new Path (myUri .toString (), pathFromConfiguredFallbackRoot ));
1128+ }
1129+ return statuses ;
11041130 }
1105- return statuses ;
1106- } else {
1107- return new FileStatus [0 ];
11081131 }
1132+ return new FileStatus [0 ];
11091133 }
11101134
11111135 @ Override
0 commit comments