001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.hadoop.fs.viewfs;
019
020 import static org.apache.hadoop.fs.viewfs.Constants.PERMISSION_555;
021
022 import java.io.FileNotFoundException;
023 import java.io.IOException;
024 import java.net.URI;
025 import java.net.URISyntaxException;
026 import java.util.Arrays;
027 import java.util.EnumSet;
028 import java.util.HashSet;
029 import java.util.List;
030 import java.util.Set;
031 import java.util.Map.Entry;
032
033 import org.apache.hadoop.classification.InterfaceAudience;
034 import org.apache.hadoop.classification.InterfaceStability;
035 import org.apache.hadoop.conf.Configuration;
036 import org.apache.hadoop.fs.BlockLocation;
037 import org.apache.hadoop.fs.ContentSummary;
038 import org.apache.hadoop.fs.CreateFlag;
039 import org.apache.hadoop.fs.FSDataInputStream;
040 import org.apache.hadoop.fs.FSDataOutputStream;
041 import org.apache.hadoop.fs.FileAlreadyExistsException;
042 import org.apache.hadoop.fs.FileChecksum;
043 import org.apache.hadoop.fs.FileStatus;
044 import org.apache.hadoop.fs.FileSystem;
045 import org.apache.hadoop.fs.FsConstants;
046 import org.apache.hadoop.fs.FsServerDefaults;
047 import org.apache.hadoop.fs.Path;
048 import org.apache.hadoop.fs.UnsupportedFileSystemException;
049 import org.apache.hadoop.fs.permission.AclEntry;
050 import org.apache.hadoop.fs.permission.AclStatus;
051 import org.apache.hadoop.fs.permission.FsPermission;
052 import org.apache.hadoop.fs.viewfs.InodeTree.INode;
053 import org.apache.hadoop.fs.viewfs.InodeTree.INodeLink;
054 import org.apache.hadoop.security.AccessControlException;
055 import org.apache.hadoop.security.UserGroupInformation;
056 import org.apache.hadoop.util.Progressable;
057 import org.apache.hadoop.util.Time;
058
059 /**
060 * ViewFileSystem (extends the FileSystem interface) implements a client-side
061 * mount table. Its spec and implementation is identical to {@link ViewFs}.
062 */
063
064 @InterfaceAudience.Public
065 @InterfaceStability.Evolving /*Evolving for a release,to be changed to Stable */
066 public class ViewFileSystem extends FileSystem {
067
068 private static final Path ROOT_PATH = new Path(Path.SEPARATOR);
069
070 static AccessControlException readOnlyMountTable(final String operation,
071 final String p) {
072 return new AccessControlException(
073 "InternalDir of ViewFileSystem is readonly; operation=" + operation +
074 "Path=" + p);
075 }
076 static AccessControlException readOnlyMountTable(final String operation,
077 final Path p) {
078 return readOnlyMountTable(operation, p.toString());
079 }
080
081 static public class MountPoint {
082 private Path src; // the src of the mount
083 private URI[] targets; // target of the mount; Multiple targets imply mergeMount
084 MountPoint(Path srcPath, URI[] targetURIs) {
085 src = srcPath;
086 targets = targetURIs;
087 }
088 Path getSrc() {
089 return src;
090 }
091 URI[] getTargets() {
092 return targets;
093 }
094 }
095
096 final long creationTime; // of the the mount table
097 final UserGroupInformation ugi; // the user/group of user who created mtable
098 URI myUri;
099 private Path workingDir;
100 Configuration config;
101 InodeTree<FileSystem> fsState; // the fs state; ie the mount table
102 Path homeDir = null;
103
104 /**
105 * Make the path Absolute and get the path-part of a pathname.
106 * Checks that URI matches this file system
107 * and that the path-part is a valid name.
108 *
109 * @param p path
110 * @return path-part of the Path p
111 */
112 private String getUriPath(final Path p) {
113 checkPath(p);
114 String s = makeAbsolute(p).toUri().getPath();
115 return s;
116 }
117
118 private Path makeAbsolute(final Path f) {
119 return f.isAbsolute() ? f : new Path(workingDir, f);
120 }
121
122 /**
123 * This is the constructor with the signature needed by
124 * {@link FileSystem#createFileSystem(URI, Configuration)}
125 *
126 * After this constructor is called initialize() is called.
127 * @throws IOException
128 */
129 public ViewFileSystem() throws IOException {
130 ugi = UserGroupInformation.getCurrentUser();
131 creationTime = Time.now();
132 }
133
134 /**
135 * Return the protocol scheme for the FileSystem.
136 * <p/>
137 *
138 * @return <code>viewfs</code>
139 */
140 @Override
141 public String getScheme() {
142 return "viewfs";
143 }
144
145 /**
146 * Called after a new FileSystem instance is constructed.
147 * @param theUri a uri whose authority section names the host, port, etc. for
148 * this FileSystem
149 * @param conf the configuration
150 */
151 @Override
152 public void initialize(final URI theUri, final Configuration conf)
153 throws IOException {
154 super.initialize(theUri, conf);
155 setConf(conf);
156 config = conf;
157 // Now build client side view (i.e. client side mount table) from config.
158 final String authority = theUri.getAuthority();
159 try {
160 myUri = new URI(FsConstants.VIEWFS_SCHEME, authority, "/", null, null);
161 fsState = new InodeTree<FileSystem>(conf, authority) {
162
163 @Override
164 protected
165 FileSystem getTargetFileSystem(final URI uri)
166 throws URISyntaxException, IOException {
167 return new ChRootedFileSystem(uri, config);
168 }
169
170 @Override
171 protected
172 FileSystem getTargetFileSystem(final INodeDir<FileSystem> dir)
173 throws URISyntaxException {
174 return new InternalDirOfViewFs(dir, creationTime, ugi, myUri);
175 }
176
177 @Override
178 protected
179 FileSystem getTargetFileSystem(URI[] mergeFsURIList)
180 throws URISyntaxException, UnsupportedFileSystemException {
181 throw new UnsupportedFileSystemException("mergefs not implemented");
182 // return MergeFs.createMergeFs(mergeFsURIList, config);
183 }
184 };
185 workingDir = this.getHomeDirectory();
186 } catch (URISyntaxException e) {
187 throw new IOException("URISyntax exception: " + theUri);
188 }
189
190 }
191
192
193 /**
194 * Convenience Constructor for apps to call directly
195 * @param theUri which must be that of ViewFileSystem
196 * @param conf
197 * @throws IOException
198 */
199 ViewFileSystem(final URI theUri, final Configuration conf)
200 throws IOException {
201 this();
202 initialize(theUri, conf);
203 }
204
205 /**
206 * Convenience Constructor for apps to call directly
207 * @param conf
208 * @throws IOException
209 */
210 public ViewFileSystem(final Configuration conf) throws IOException {
211 this(FsConstants.VIEWFS_URI, conf);
212 }
213
214 public Path getTrashCanLocation(final Path f) throws FileNotFoundException {
215 final InodeTree.ResolveResult<FileSystem> res =
216 fsState.resolve(getUriPath(f), true);
217 return res.isInternalDir() ? null : res.targetFileSystem.getHomeDirectory();
218 }
219
220 @Override
221 public URI getUri() {
222 return myUri;
223 }
224
225 @Override
226 public Path resolvePath(final Path f)
227 throws IOException {
228 final InodeTree.ResolveResult<FileSystem> res;
229 res = fsState.resolve(getUriPath(f), true);
230 if (res.isInternalDir()) {
231 return f;
232 }
233 return res.targetFileSystem.resolvePath(res.remainingPath);
234 }
235
236 @Override
237 public Path getHomeDirectory() {
238 if (homeDir == null) {
239 String base = fsState.getHomeDirPrefixValue();
240 if (base == null) {
241 base = "/user";
242 }
243 homeDir = (base.equals("/") ?
244 this.makeQualified(new Path(base + ugi.getShortUserName())):
245 this.makeQualified(new Path(base + "/" + ugi.getShortUserName())));
246 }
247 return homeDir;
248 }
249
250 @Override
251 public Path getWorkingDirectory() {
252 return workingDir;
253 }
254
255 @Override
256 public void setWorkingDirectory(final Path new_dir) {
257 getUriPath(new_dir); // this validates the path
258 workingDir = makeAbsolute(new_dir);
259 }
260
261 @Override
262 public FSDataOutputStream append(final Path f, final int bufferSize,
263 final Progressable progress) throws IOException {
264 InodeTree.ResolveResult<FileSystem> res =
265 fsState.resolve(getUriPath(f), true);
266 return res.targetFileSystem.append(res.remainingPath, bufferSize, progress);
267 }
268
269 @Override
270 public FSDataOutputStream createNonRecursive(Path f, FsPermission permission,
271 EnumSet<CreateFlag> flags, int bufferSize, short replication, long blockSize,
272 Progressable progress) throws IOException {
273 InodeTree.ResolveResult<FileSystem> res;
274 try {
275 res = fsState.resolve(getUriPath(f), false);
276 } catch (FileNotFoundException e) {
277 throw readOnlyMountTable("create", f);
278 }
279 assert(res.remainingPath != null);
280 return res.targetFileSystem.createNonRecursive(res.remainingPath, permission,
281 flags, bufferSize, replication, blockSize, progress);
282 }
283
284 @Override
285 public FSDataOutputStream create(final Path f, final FsPermission permission,
286 final boolean overwrite, final int bufferSize, final short replication,
287 final long blockSize, final Progressable progress) throws IOException {
288 InodeTree.ResolveResult<FileSystem> res;
289 try {
290 res = fsState.resolve(getUriPath(f), false);
291 } catch (FileNotFoundException e) {
292 throw readOnlyMountTable("create", f);
293 }
294 assert(res.remainingPath != null);
295 return res.targetFileSystem.create(res.remainingPath, permission,
296 overwrite, bufferSize, replication, blockSize, progress);
297 }
298
299
300 @Override
301 public boolean delete(final Path f, final boolean recursive)
302 throws AccessControlException, FileNotFoundException,
303 IOException {
304 InodeTree.ResolveResult<FileSystem> res =
305 fsState.resolve(getUriPath(f), true);
306 // If internal dir or target is a mount link (ie remainingPath is Slash)
307 if (res.isInternalDir() || res.remainingPath == InodeTree.SlashPath) {
308 throw readOnlyMountTable("delete", f);
309 }
310 return res.targetFileSystem.delete(res.remainingPath, recursive);
311 }
312
313 @Override
314 @SuppressWarnings("deprecation")
315 public boolean delete(final Path f)
316 throws AccessControlException, FileNotFoundException,
317 IOException {
318 return delete(f, true);
319 }
320
321 @Override
322 public BlockLocation[] getFileBlockLocations(FileStatus fs,
323 long start, long len) throws IOException {
324 final InodeTree.ResolveResult<FileSystem> res =
325 fsState.resolve(getUriPath(fs.getPath()), true);
326 return res.targetFileSystem.getFileBlockLocations(
327 new ViewFsFileStatus(fs, res.remainingPath), start, len);
328 }
329
330 @Override
331 public FileChecksum getFileChecksum(final Path f)
332 throws AccessControlException, FileNotFoundException,
333 IOException {
334 InodeTree.ResolveResult<FileSystem> res =
335 fsState.resolve(getUriPath(f), true);
336 return res.targetFileSystem.getFileChecksum(res.remainingPath);
337 }
338
339 @Override
340 public FileStatus getFileStatus(final Path f) throws AccessControlException,
341 FileNotFoundException, IOException {
342 InodeTree.ResolveResult<FileSystem> res =
343 fsState.resolve(getUriPath(f), true);
344
345 // FileStatus#getPath is a fully qualified path relative to the root of
346 // target file system.
347 // We need to change it to viewfs URI - relative to root of mount table.
348
349 // The implementors of RawLocalFileSystem were trying to be very smart.
350 // They implement FileStatus#getOwener lazily -- the object
351 // returned is really a RawLocalFileSystem that expect the
352 // FileStatus#getPath to be unchanged so that it can get owner when needed.
353 // Hence we need to interpose a new ViewFileSystemFileStatus that
354 // works around.
355 FileStatus status = res.targetFileSystem.getFileStatus(res.remainingPath);
356 return new ViewFsFileStatus(status, this.makeQualified(f));
357 }
358
359
360 @Override
361 public FileStatus[] listStatus(final Path f) throws AccessControlException,
362 FileNotFoundException, IOException {
363 InodeTree.ResolveResult<FileSystem> res =
364 fsState.resolve(getUriPath(f), true);
365
366 FileStatus[] statusLst = res.targetFileSystem.listStatus(res.remainingPath);
367 if (!res.isInternalDir()) {
368 // We need to change the name in the FileStatus as described in
369 // {@link #getFileStatus }
370 ChRootedFileSystem targetFs;
371 targetFs = (ChRootedFileSystem) res.targetFileSystem;
372 int i = 0;
373 for (FileStatus status : statusLst) {
374 String suffix = targetFs.stripOutRoot(status.getPath());
375 statusLst[i++] = new ViewFsFileStatus(status, this.makeQualified(
376 suffix.length() == 0 ? f : new Path(res.resolvedPath, suffix)));
377 }
378 }
379 return statusLst;
380 }
381
382 @Override
383 public boolean mkdirs(final Path dir, final FsPermission permission)
384 throws IOException {
385 InodeTree.ResolveResult<FileSystem> res =
386 fsState.resolve(getUriPath(dir), false);
387 return res.targetFileSystem.mkdirs(res.remainingPath, permission);
388 }
389
390 @Override
391 public FSDataInputStream open(final Path f, final int bufferSize)
392 throws AccessControlException, FileNotFoundException,
393 IOException {
394 InodeTree.ResolveResult<FileSystem> res =
395 fsState.resolve(getUriPath(f), true);
396 return res.targetFileSystem.open(res.remainingPath, bufferSize);
397 }
398
399
400 @Override
401 public boolean rename(final Path src, final Path dst) throws IOException {
402 // passing resolveLastComponet as false to catch renaming a mount point to
403 // itself. We need to catch this as an internal operation and fail.
404 InodeTree.ResolveResult<FileSystem> resSrc =
405 fsState.resolve(getUriPath(src), false);
406
407 if (resSrc.isInternalDir()) {
408 throw readOnlyMountTable("rename", src);
409 }
410
411 InodeTree.ResolveResult<FileSystem> resDst =
412 fsState.resolve(getUriPath(dst), false);
413 if (resDst.isInternalDir()) {
414 throw readOnlyMountTable("rename", dst);
415 }
416 /**
417 // Alternate 1: renames within same file system - valid but we disallow
418 // Alternate 2: (as described in next para - valid but we have disallowed it
419 //
420 // Note we compare the URIs. the URIs include the link targets.
421 // hence we allow renames across mount links as long as the mount links
422 // point to the same target.
423 if (!resSrc.targetFileSystem.getUri().equals(
424 resDst.targetFileSystem.getUri())) {
425 throw new IOException("Renames across Mount points not supported");
426 }
427 */
428
429 //
430 // Alternate 3 : renames ONLY within the the same mount links.
431 //
432 if (resSrc.targetFileSystem !=resDst.targetFileSystem) {
433 throw new IOException("Renames across Mount points not supported");
434 }
435 return resSrc.targetFileSystem.rename(resSrc.remainingPath,
436 resDst.remainingPath);
437 }
438
439 @Override
440 public void setOwner(final Path f, final String username,
441 final String groupname) throws AccessControlException,
442 FileNotFoundException,
443 IOException {
444 InodeTree.ResolveResult<FileSystem> res =
445 fsState.resolve(getUriPath(f), true);
446 res.targetFileSystem.setOwner(res.remainingPath, username, groupname);
447 }
448
449 @Override
450 public void setPermission(final Path f, final FsPermission permission)
451 throws AccessControlException, FileNotFoundException,
452 IOException {
453 InodeTree.ResolveResult<FileSystem> res =
454 fsState.resolve(getUriPath(f), true);
455 res.targetFileSystem.setPermission(res.remainingPath, permission);
456 }
457
458 @Override
459 public boolean setReplication(final Path f, final short replication)
460 throws AccessControlException, FileNotFoundException,
461 IOException {
462 InodeTree.ResolveResult<FileSystem> res =
463 fsState.resolve(getUriPath(f), true);
464 return res.targetFileSystem.setReplication(res.remainingPath, replication);
465 }
466
467 @Override
468 public void setTimes(final Path f, final long mtime, final long atime)
469 throws AccessControlException, FileNotFoundException,
470 IOException {
471 InodeTree.ResolveResult<FileSystem> res =
472 fsState.resolve(getUriPath(f), true);
473 res.targetFileSystem.setTimes(res.remainingPath, mtime, atime);
474 }
475
476 @Override
477 public void modifyAclEntries(Path path, List<AclEntry> aclSpec)
478 throws IOException {
479 InodeTree.ResolveResult<FileSystem> res = fsState.resolve(getUriPath(path),
480 true);
481 res.targetFileSystem.modifyAclEntries(res.remainingPath, aclSpec);
482 }
483
484 @Override
485 public void removeAclEntries(Path path, List<AclEntry> aclSpec)
486 throws IOException {
487 InodeTree.ResolveResult<FileSystem> res = fsState.resolve(getUriPath(path),
488 true);
489 res.targetFileSystem.removeAclEntries(res.remainingPath, aclSpec);
490 }
491
492 @Override
493 public void removeDefaultAcl(Path path)
494 throws IOException {
495 InodeTree.ResolveResult<FileSystem> res =
496 fsState.resolve(getUriPath(path), true);
497 res.targetFileSystem.removeDefaultAcl(res.remainingPath);
498 }
499
500 @Override
501 public void removeAcl(Path path)
502 throws IOException {
503 InodeTree.ResolveResult<FileSystem> res =
504 fsState.resolve(getUriPath(path), true);
505 res.targetFileSystem.removeAcl(res.remainingPath);
506 }
507
508 @Override
509 public void setAcl(Path path, List<AclEntry> aclSpec) throws IOException {
510 InodeTree.ResolveResult<FileSystem> res =
511 fsState.resolve(getUriPath(path), true);
512 res.targetFileSystem.setAcl(res.remainingPath, aclSpec);
513 }
514
515 @Override
516 public AclStatus getAclStatus(Path path) throws IOException {
517 InodeTree.ResolveResult<FileSystem> res =
518 fsState.resolve(getUriPath(path), true);
519 return res.targetFileSystem.getAclStatus(res.remainingPath);
520 }
521
522 @Override
523 public void setVerifyChecksum(final boolean verifyChecksum) {
524 List<InodeTree.MountPoint<FileSystem>> mountPoints =
525 fsState.getMountPoints();
526 for (InodeTree.MountPoint<FileSystem> mount : mountPoints) {
527 mount.target.targetFileSystem.setVerifyChecksum(verifyChecksum);
528 }
529 }
530
531 @Override
532 public long getDefaultBlockSize() {
533 throw new NotInMountpointException("getDefaultBlockSize");
534 }
535
536 @Override
537 public short getDefaultReplication() {
538 throw new NotInMountpointException("getDefaultReplication");
539 }
540
541 @Override
542 public FsServerDefaults getServerDefaults() throws IOException {
543 throw new NotInMountpointException("getServerDefaults");
544 }
545
546 @Override
547 public long getDefaultBlockSize(Path f) {
548 try {
549 InodeTree.ResolveResult<FileSystem> res =
550 fsState.resolve(getUriPath(f), true);
551 return res.targetFileSystem.getDefaultBlockSize(res.remainingPath);
552 } catch (FileNotFoundException e) {
553 throw new NotInMountpointException(f, "getDefaultBlockSize");
554 }
555 }
556
557 @Override
558 public short getDefaultReplication(Path f) {
559 try {
560 InodeTree.ResolveResult<FileSystem> res =
561 fsState.resolve(getUriPath(f), true);
562 return res.targetFileSystem.getDefaultReplication(res.remainingPath);
563 } catch (FileNotFoundException e) {
564 throw new NotInMountpointException(f, "getDefaultReplication");
565 }
566 }
567
568 @Override
569 public FsServerDefaults getServerDefaults(Path f) throws IOException {
570 InodeTree.ResolveResult<FileSystem> res =
571 fsState.resolve(getUriPath(f), true);
572 return res.targetFileSystem.getServerDefaults(res.remainingPath);
573 }
574
575 @Override
576 public ContentSummary getContentSummary(Path f) throws IOException {
577 InodeTree.ResolveResult<FileSystem> res =
578 fsState.resolve(getUriPath(f), true);
579 return res.targetFileSystem.getContentSummary(res.remainingPath);
580 }
581
582 @Override
583 public void setWriteChecksum(final boolean writeChecksum) {
584 List<InodeTree.MountPoint<FileSystem>> mountPoints =
585 fsState.getMountPoints();
586 for (InodeTree.MountPoint<FileSystem> mount : mountPoints) {
587 mount.target.targetFileSystem.setWriteChecksum(writeChecksum);
588 }
589 }
590
591 @Override
592 public FileSystem[] getChildFileSystems() {
593 List<InodeTree.MountPoint<FileSystem>> mountPoints =
594 fsState.getMountPoints();
595 Set<FileSystem> children = new HashSet<FileSystem>();
596 for (InodeTree.MountPoint<FileSystem> mountPoint : mountPoints) {
597 FileSystem targetFs = mountPoint.target.targetFileSystem;
598 children.addAll(Arrays.asList(targetFs.getChildFileSystems()));
599 }
600 return children.toArray(new FileSystem[]{});
601 }
602
603 public MountPoint[] getMountPoints() {
604 List<InodeTree.MountPoint<FileSystem>> mountPoints =
605 fsState.getMountPoints();
606
607 MountPoint[] result = new MountPoint[mountPoints.size()];
608 for ( int i = 0; i < mountPoints.size(); ++i ) {
609 result[i] = new MountPoint(new Path(mountPoints.get(i).src),
610 mountPoints.get(i).target.targetDirLinkList);
611 }
612 return result;
613 }
614
615 /*
616 * An instance of this class represents an internal dir of the viewFs
617 * that is internal dir of the mount table.
618 * It is a read only mount tables and create, mkdir or delete operations
619 * are not allowed.
620 * If called on create or mkdir then this target is the parent of the
621 * directory in which one is trying to create or mkdir; hence
622 * in this case the path name passed in is the last component.
623 * Otherwise this target is the end point of the path and hence
624 * the path name passed in is null.
625 */
626 static class InternalDirOfViewFs extends FileSystem {
627 final InodeTree.INodeDir<FileSystem> theInternalDir;
628 final long creationTime; // of the the mount table
629 final UserGroupInformation ugi; // the user/group of user who created mtable
630 final URI myUri;
631
632 public InternalDirOfViewFs(final InodeTree.INodeDir<FileSystem> dir,
633 final long cTime, final UserGroupInformation ugi, URI uri)
634 throws URISyntaxException {
635 myUri = uri;
636 try {
637 initialize(myUri, new Configuration());
638 } catch (IOException e) {
639 throw new RuntimeException("Cannot occur");
640 }
641 theInternalDir = dir;
642 creationTime = cTime;
643 this.ugi = ugi;
644 }
645
646 static private void checkPathIsSlash(final Path f) throws IOException {
647 if (f != InodeTree.SlashPath) {
648 throw new IOException (
649 "Internal implementation error: expected file name to be /" );
650 }
651 }
652
653 @Override
654 public URI getUri() {
655 return myUri;
656 }
657
658 @Override
659 public Path getWorkingDirectory() {
660 throw new RuntimeException (
661 "Internal impl error: getWorkingDir should not have been called" );
662 }
663
664 @Override
665 public void setWorkingDirectory(final Path new_dir) {
666 throw new RuntimeException (
667 "Internal impl error: getWorkingDir should not have been called" );
668 }
669
670 @Override
671 public FSDataOutputStream append(final Path f, final int bufferSize,
672 final Progressable progress) throws IOException {
673 throw readOnlyMountTable("append", f);
674 }
675
676 @Override
677 public FSDataOutputStream create(final Path f,
678 final FsPermission permission, final boolean overwrite,
679 final int bufferSize, final short replication, final long blockSize,
680 final Progressable progress) throws AccessControlException {
681 throw readOnlyMountTable("create", f);
682 }
683
684 @Override
685 public boolean delete(final Path f, final boolean recursive)
686 throws AccessControlException, IOException {
687 checkPathIsSlash(f);
688 throw readOnlyMountTable("delete", f);
689 }
690
691 @Override
692 @SuppressWarnings("deprecation")
693 public boolean delete(final Path f)
694 throws AccessControlException, IOException {
695 return delete(f, true);
696 }
697
698 @Override
699 public BlockLocation[] getFileBlockLocations(final FileStatus fs,
700 final long start, final long len) throws
701 FileNotFoundException, IOException {
702 checkPathIsSlash(fs.getPath());
703 throw new FileNotFoundException("Path points to dir not a file");
704 }
705
706 @Override
707 public FileChecksum getFileChecksum(final Path f)
708 throws FileNotFoundException, IOException {
709 checkPathIsSlash(f);
710 throw new FileNotFoundException("Path points to dir not a file");
711 }
712
713 @Override
714 public FileStatus getFileStatus(Path f) throws IOException {
715 checkPathIsSlash(f);
716 return new FileStatus(0, true, 0, 0, creationTime, creationTime,
717 PERMISSION_555, ugi.getUserName(), ugi.getGroupNames()[0],
718
719 new Path(theInternalDir.fullPath).makeQualified(
720 myUri, ROOT_PATH));
721 }
722
723
724 @Override
725 public FileStatus[] listStatus(Path f) throws AccessControlException,
726 FileNotFoundException, IOException {
727 checkPathIsSlash(f);
728 FileStatus[] result = new FileStatus[theInternalDir.children.size()];
729 int i = 0;
730 for (Entry<String, INode<FileSystem>> iEntry :
731 theInternalDir.children.entrySet()) {
732 INode<FileSystem> inode = iEntry.getValue();
733 if (inode instanceof INodeLink ) {
734 INodeLink<FileSystem> link = (INodeLink<FileSystem>) inode;
735
736 result[i++] = new FileStatus(0, false, 0, 0,
737 creationTime, creationTime, PERMISSION_555,
738 ugi.getUserName(), ugi.getGroupNames()[0],
739 link.getTargetLink(),
740 new Path(inode.fullPath).makeQualified(
741 myUri, null));
742 } else {
743 result[i++] = new FileStatus(0, true, 0, 0,
744 creationTime, creationTime, PERMISSION_555,
745 ugi.getUserName(), ugi.getGroupNames()[0],
746 new Path(inode.fullPath).makeQualified(
747 myUri, null));
748 }
749 }
750 return result;
751 }
752
753 @Override
754 public boolean mkdirs(Path dir, FsPermission permission)
755 throws AccessControlException, FileAlreadyExistsException {
756 if (theInternalDir.isRoot && dir == null) {
757 throw new FileAlreadyExistsException("/ already exits");
758 }
759 // Note dir starts with /
760 if (theInternalDir.children.containsKey(dir.toString().substring(1))) {
761 return true; // this is the stupid semantics of FileSystem
762 }
763 throw readOnlyMountTable("mkdirs", dir);
764 }
765
766 @Override
767 public FSDataInputStream open(Path f, int bufferSize)
768 throws AccessControlException, FileNotFoundException, IOException {
769 checkPathIsSlash(f);
770 throw new FileNotFoundException("Path points to dir not a file");
771 }
772
773 @Override
774 public boolean rename(Path src, Path dst) throws AccessControlException,
775 IOException {
776 checkPathIsSlash(src);
777 checkPathIsSlash(dst);
778 throw readOnlyMountTable("rename", src);
779 }
780
781 @Override
782 public void setOwner(Path f, String username, String groupname)
783 throws AccessControlException, IOException {
784 checkPathIsSlash(f);
785 throw readOnlyMountTable("setOwner", f);
786 }
787
788 @Override
789 public void setPermission(Path f, FsPermission permission)
790 throws AccessControlException, IOException {
791 checkPathIsSlash(f);
792 throw readOnlyMountTable("setPermission", f);
793 }
794
795 @Override
796 public boolean setReplication(Path f, short replication)
797 throws AccessControlException, IOException {
798 checkPathIsSlash(f);
799 throw readOnlyMountTable("setReplication", f);
800 }
801
802 @Override
803 public void setTimes(Path f, long mtime, long atime)
804 throws AccessControlException, IOException {
805 checkPathIsSlash(f);
806 throw readOnlyMountTable("setTimes", f);
807 }
808
809 @Override
810 public void setVerifyChecksum(boolean verifyChecksum) {
811 // Noop for viewfs
812 }
813
814 @Override
815 public FsServerDefaults getServerDefaults(Path f) throws IOException {
816 throw new NotInMountpointException(f, "getServerDefaults");
817 }
818
819 @Override
820 public long getDefaultBlockSize(Path f) {
821 throw new NotInMountpointException(f, "getDefaultBlockSize");
822 }
823
824 @Override
825 public short getDefaultReplication(Path f) {
826 throw new NotInMountpointException(f, "getDefaultReplication");
827 }
828 }
829 }