2121import static org .apache .hadoop .fs .viewfs .Constants .CONFIG_VIEWFS_ENABLE_INNER_CACHE ;
2222import static org .apache .hadoop .fs .viewfs .Constants .CONFIG_VIEWFS_ENABLE_INNER_CACHE_DEFAULT ;
2323
24+ import com .google .common .base .Function ;
2425import java .io .FileNotFoundException ;
2526import java .io .IOException ;
2627import java .net .URI ;
2728import java .net .URISyntaxException ;
29+ import java .security .PrivilegedExceptionAction ;
2830import java .util .Arrays ;
2931import java .util .Collections ;
3032import java .util .EnumSet ;
@@ -237,24 +239,40 @@ public void initialize(final URI theUri, final Configuration conf)
237239 config = conf ;
238240 enableInnerCache = config .getBoolean (CONFIG_VIEWFS_ENABLE_INNER_CACHE ,
239241 CONFIG_VIEWFS_ENABLE_INNER_CACHE_DEFAULT );
240- final InnerCache innerCache = new InnerCache ();
242+ cache = new InnerCache ();
241243 // Now build client side view (i.e. client side mount table) from config.
242244 final String authority = theUri .getAuthority ();
243245 try {
244246 myUri = new URI (FsConstants .VIEWFS_SCHEME , authority , "/" , null , null );
245247 fsState = new InodeTree <FileSystem >(conf , authority ) {
246248
247249 @ Override
248- protected
249- FileSystem getTargetFileSystem (final URI uri )
250- throws URISyntaxException , IOException {
251- FileSystem fs ;
252- if (enableInnerCache ) {
253- fs = innerCache .get (uri , config );
254- } else {
255- fs = FileSystem .get (uri , config );
250+ protected Function <URI , FileSystem > initAndGetTargetFs () {
251+ return new Function <URI , FileSystem >() {
252+ @ Override
253+ public FileSystem apply (final URI uri ) {
254+ FileSystem fs ;
255+ try {
256+ fs = ugi .doAs (new PrivilegedExceptionAction <FileSystem >() {
257+ @ Override
258+ public FileSystem run () throws IOException {
259+ if (enableInnerCache ) {
260+ synchronized (cache ) {
261+ return cache .get (uri , config );
262+ }
263+ } else {
264+ return FileSystem .get (uri , config );
265+ }
266+ }
267+ });
268+ return new ChRootedFileSystem (fs , uri );
269+ } catch (IOException | InterruptedException ex ) {
270+ LOG .error ("Could not initialize the underlying FileSystem "
271+ + "object. Exception: " + ex .toString ());
272+ }
273+ return null ;
256274 }
257- return new ChRootedFileSystem ( fs , uri ) ;
275+ } ;
258276 }
259277
260278 @ Override
@@ -273,12 +291,6 @@ FileSystem getTargetFileSystem(URI[] mergeFsURIList)
273291 }
274292 };
275293
276- if (enableInnerCache ) {
277- // All fs instances are created and cached on startup. The cache is
278- // readonly after the initialize() so the concurrent access of the cache
279- // is safe.
280- cache = innerCache .unmodifiableCache ();
281- }
282294 workingDir = this .getHomeDirectory ();
283295 renameStrategy = RenameStrategy .valueOf (
284296 conf .get (Constants .CONFIG_VIEWFS_RENAME_STRATEGY ,
@@ -311,7 +323,7 @@ public ViewFileSystem(final Configuration conf) throws IOException {
311323 this (FsConstants .VIEWFS_URI , conf );
312324 }
313325
314- public Path getTrashCanLocation (final Path f ) throws FileNotFoundException {
326+ public Path getTrashCanLocation (final Path f ) throws IOException {
315327 final InodeTree .ResolveResult <FileSystem > res =
316328 fsState .resolve (getUriPath (f ), true );
317329 return res .isInternalDir () ? null : res .targetFileSystem .getHomeDirectory ();
@@ -767,9 +779,34 @@ public void removeXAttr(Path path, String name) throws IOException {
767779 public void setVerifyChecksum (final boolean verifyChecksum ) {
768780 List <InodeTree .MountPoint <FileSystem >> mountPoints =
769781 fsState .getMountPoints ();
782+ Map <String , FileSystem > fsMap = initializeMountedFileSystems (mountPoints );
783+ for (InodeTree .MountPoint <FileSystem > mount : mountPoints ) {
784+ fsMap .get (mount .src ).setVerifyChecksum (verifyChecksum );
785+ }
786+ }
787+
788+ /**
789+ * Initialize the target filesystem for all mount points.
790+ * @param mountPoints The mount points
791+ * @return Mapping of mount point and the initialized target filesystems
792+ * @throws RuntimeException when the target file system cannot be initialized
793+ */
794+ private Map <String , FileSystem > initializeMountedFileSystems (
795+ List <InodeTree .MountPoint <FileSystem >> mountPoints ) {
796+ FileSystem fs = null ;
797+ Map <String , FileSystem > fsMap = new HashMap <>(mountPoints .size ());
770798 for (InodeTree .MountPoint <FileSystem > mount : mountPoints ) {
771- mount .target .targetFileSystem .setVerifyChecksum (verifyChecksum );
799+ try {
800+ fs = mount .target .getTargetFileSystem ();
801+ fsMap .put (mount .src , fs );
802+ } catch (IOException ex ) {
803+ String errMsg = "Not able to initialize FileSystem for mount path " +
804+ mount .src + " with exception " + ex ;
805+ LOG .error (errMsg );
806+ throw new RuntimeException (errMsg , ex );
807+ }
772808 }
809+ return fsMap ;
773810 }
774811
775812 @ Override
@@ -795,6 +832,9 @@ public long getDefaultBlockSize(Path f) {
795832 return res .targetFileSystem .getDefaultBlockSize (res .remainingPath );
796833 } catch (FileNotFoundException e ) {
797834 throw new NotInMountpointException (f , "getDefaultBlockSize" );
835+ } catch (IOException e ) {
836+ throw new RuntimeException ("Not able to initialize fs in "
837+ + " getDefaultBlockSize for path " + f + " with exception" , e );
798838 }
799839 }
800840
@@ -806,6 +846,9 @@ public short getDefaultReplication(Path f) {
806846 return res .targetFileSystem .getDefaultReplication (res .remainingPath );
807847 } catch (FileNotFoundException e ) {
808848 throw new NotInMountpointException (f , "getDefaultReplication" );
849+ } catch (IOException e ) {
850+ throw new RuntimeException ("Not able to initialize fs in "
851+ + " getDefaultReplication for path " + f + " with exception" , e );
809852 }
810853 }
811854
@@ -834,18 +877,20 @@ public QuotaUsage getQuotaUsage(Path f) throws IOException {
834877 public void setWriteChecksum (final boolean writeChecksum ) {
835878 List <InodeTree .MountPoint <FileSystem >> mountPoints =
836879 fsState .getMountPoints ();
880+ Map <String , FileSystem > fsMap = initializeMountedFileSystems (mountPoints );
837881 for (InodeTree .MountPoint <FileSystem > mount : mountPoints ) {
838- mount .target . targetFileSystem .setWriteChecksum (writeChecksum );
882+ fsMap . get ( mount .src ) .setWriteChecksum (writeChecksum );
839883 }
840884 }
841885
842886 @ Override
843887 public FileSystem [] getChildFileSystems () {
844888 List <InodeTree .MountPoint <FileSystem >> mountPoints =
845889 fsState .getMountPoints ();
890+ Map <String , FileSystem > fsMap = initializeMountedFileSystems (mountPoints );
846891 Set <FileSystem > children = new HashSet <FileSystem >();
847892 for (InodeTree .MountPoint <FileSystem > mountPoint : mountPoints ) {
848- FileSystem targetFs = mountPoint .target . targetFileSystem ;
893+ FileSystem targetFs = fsMap . get ( mountPoint .src ) ;
849894 children .addAll (Arrays .asList (targetFs .getChildFileSystems ()));
850895 }
851896 return children .toArray (new FileSystem []{});
0 commit comments