Skip to content

Commit 8a2c9f4

Browse files
committed
HADOOP-15691 Add PathCapabilities to FS and FC to complement StreamCapabilities.
This contains all the work to date, reapplied to trunk so that Yetus will take up the PR again. Change-Id: Icfab71d177c88c75fd651d7eea56d3d1e8618f61
1 parent 0eba407 commit 8a2c9f4

File tree

33 files changed

+943
-27
lines changed

33 files changed

+943
-27
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.EnumSet;
3030
import java.util.HashMap;
3131
import java.util.List;
32+
import java.util.Locale;
3233
import java.util.Map;
3334
import java.util.NoSuchElementException;
3435
import java.util.Set;
@@ -45,6 +46,7 @@
4546
import org.apache.hadoop.fs.Options.CreateOpts;
4647
import org.apache.hadoop.fs.Options.Rename;
4748
import org.apache.hadoop.fs.impl.AbstractFSBuilderImpl;
49+
import org.apache.hadoop.fs.impl.PathCapabilitiesSupport;
4850
import org.apache.hadoop.fs.permission.AclEntry;
4951
import org.apache.hadoop.fs.permission.AclStatus;
5052
import org.apache.hadoop.fs.permission.FsAction;
@@ -71,7 +73,7 @@
7173
*/
7274
@InterfaceAudience.Public
7375
@InterfaceStability.Stable
74-
public abstract class AbstractFileSystem {
76+
public abstract class AbstractFileSystem implements PathCapabilities {
7577
static final Logger LOG = LoggerFactory.getLogger(AbstractFileSystem.class);
7678

7779
/** Recording statistics per a file system class. */
@@ -1362,4 +1364,30 @@ public CompletableFuture<FSDataInputStream> openFileWithOptions(Path path,
13621364
new CompletableFuture<>(), () -> open(path, bufferSize));
13631365
}
13641366

1367+
/**
1368+
* Return the base capabilities of the filesystems
1369+
* may override to declare different behavior.
1370+
* @param path path to query the capability of.
1371+
* @param capability string to query the stream support for.
1372+
* @return true if the capability is supported under that part of the FS.
1373+
* @throws IOException on failure
1374+
*/
1375+
public boolean hasPathCapability(final Path path,
1376+
final String capability)
1377+
throws IOException {
1378+
PathCapabilitiesSupport.validatehasPathCapabilityArgs(path, capability);
1379+
// qualify the path to make sure that it refers to the current FS.
1380+
makeQualified(path);
1381+
switch (capability.toLowerCase(Locale.ENGLISH)) {
1382+
case CommonPathCapabilities.FS_SYMLINKS:
1383+
// delegate to the existing supportsSymlinks() call.
1384+
return supportsSymlinks();
1385+
case CommonPathCapabilities.FS_DELEGATION_TOKENS:
1386+
// this is less efficient than it should be.
1387+
return getCanonicalServiceName() != null;
1388+
default:
1389+
// the feature is not implemented.
1390+
return false;
1391+
}
1392+
}
13651393
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Collections;
2828
import java.util.EnumSet;
2929
import java.util.List;
30+
import java.util.Locale;
3031
import java.util.Set;
3132
import java.util.concurrent.CompletableFuture;
3233

@@ -872,4 +873,24 @@ public FSDataOutputStreamBuilder createFile(Path path) {
872873
public FSDataOutputStreamBuilder appendFile(Path path) {
873874
return createDataOutputStreamBuilder(this, path).append();
874875
}
876+
877+
/**
878+
* Disable those operations which are disabled so as to guarantee
879+
* checksumming of all created files.
880+
* {@inheritDoc}
881+
*/
882+
@Override
883+
public boolean hasPathCapability(final Path path, final String capability)
884+
throws IOException {
885+
// query the superclass, which triggers argument validation.
886+
boolean superCapability = super.hasPathCapability(path, capability);
887+
switch (capability.toLowerCase(Locale.ENGLISH)) {
888+
case CommonPathCapabilities.FS_APPEND:
889+
case CommonPathCapabilities.FS_CONCAT:
890+
return false;
891+
default:
892+
return superCapability;
893+
}
894+
}
895+
875896
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.fs;
20+
21+
import java.util.List;
22+
23+
import org.apache.hadoop.fs.permission.FsPermission;
24+
25+
/**
26+
* Common path capabilities.
27+
*/
28+
public final class CommonPathCapabilities {
29+
30+
public CommonPathCapabilities() {
31+
}
32+
33+
/**
34+
* Does the Filesystem support
35+
* {@link FileSystem#setAcl(Path, List)},
36+
* {@link FileSystem#getAclStatus(Path)}
37+
* and related methods?
38+
* Value: {@value}.
39+
*/
40+
public static final String FS_ACLS = "fs.paths.acls";
41+
42+
/**
43+
* Does the Filesystem support {@link FileSystem#append(Path)}?
44+
* Value: {@value}.
45+
*/
46+
public static final String FS_APPEND = "fs.paths.append";
47+
48+
/**
49+
* Does the FS support {@link FileSystem#getFileChecksum(Path)}?
50+
* Value: {@value}.
51+
*/
52+
public static final String FS_CHECKSUMS = "fs.paths.checksums";
53+
54+
/**
55+
* Does the FS support {@link FileSystem#concat(Path, Path[])}?
56+
* Value: {@value}.
57+
*/
58+
public static final String FS_CONCAT = "fs.paths.concat";
59+
60+
/**
61+
* Does the filesystem support Delegation Tokens?
62+
* Value: {@value}.
63+
*/
64+
public static final String FS_DELEGATION_TOKENS =
65+
"fs.paths.delegation.tokens";
66+
67+
/**
68+
* Does the FS support {@link FileSystem#listCorruptFileBlocks(Path)} ()}?
69+
* Value: {@value}.
70+
*/
71+
public static final String FS_LIST_CORRUPT_FILE_BLOCKS =
72+
"fs.paths.list-corrupt-file-blocks";
73+
74+
/**
75+
* Does the FS support
76+
* {@link FileSystem#createPathHandle(FileStatus, Options.HandleOpt...)}
77+
* and related methods?
78+
* Value: {@value}.
79+
*/
80+
public static final String FS_PATHHANDLES = "fs.paths.pathhandles";
81+
82+
/**
83+
* Does the FS support {@link FileSystem#setPermission(Path, FsPermission)}
84+
* and related methods?
85+
* Value: {@value}.
86+
*/
87+
public static final String FS_PERMISSIONS = "fs.paths.permissions";
88+
89+
/**
90+
* Does this filesystem connector only support filesystem read operations?
91+
* For example, the {@code HttpFileSystem} is always read-only.
92+
* This is different from "is the specific instance and path read only?",
93+
* which must be determined by checking permissions (where supported), or
94+
* attempting write operations under a path.
95+
* Value: {@value}.
96+
*/
97+
public static final String FS_READ_ONLY_CONNECTOR =
98+
"fs.paths.read-only-connector";
99+
100+
/**
101+
* Does the FS support snapshots through
102+
* {@link FileSystem#createSnapshot(Path)} and related methods??
103+
* Value: {@value}.
104+
*/
105+
public static final String FS_SNAPSHOTS = "fs.paths.snapshots";
106+
107+
/**
108+
* Does the FS support {@link FileSystem#setStoragePolicy(Path, String)}
109+
* and related methods?
110+
* Value: {@value}.
111+
*/
112+
public static final String FS_STORAGEPOLICY =
113+
"fs.paths.storagepolicy";
114+
115+
/**
116+
* Does the FS support symlinks through
117+
* {@link FileSystem#createSymlink(Path, Path, boolean)} and related methods?
118+
* Value: {@value}.
119+
*/
120+
public static final String FS_SYMLINKS =
121+
"fs.paths.symlinks";
122+
123+
/**
124+
* Does the FS support {@link FileSystem#truncate(Path, long)} ?
125+
* Value: {@value}.
126+
*/
127+
public static final String FS_TRUNCATE =
128+
"fs.paths.truncate";
129+
130+
/**
131+
* Does the Filesystem support XAttributes through
132+
* {@link FileSystem#setXAttr(Path, String, byte[])} and related methods?
133+
* Value: {@value}.
134+
*/
135+
public static final String FS_XATTRS = "fs.paths.xattrs";
136+
137+
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,4 +281,11 @@ public CompletableFuture<FSDataInputStream> openFileWithOptions(Path path,
281281
int bufferSize) throws IOException {
282282
return fsImpl.openFileWithOptions(path, mandatoryKeys, options, bufferSize);
283283
}
284+
285+
@Override
286+
public boolean hasPathCapability(final Path path,
287+
final String capability)
288+
throws IOException {
289+
return fsImpl.hasPathCapability(path, capability);
290+
}
284291
}

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import org.apache.hadoop.fs.FileSystem.Statistics;
4747
import org.apache.hadoop.fs.Options.CreateOpts;
4848
import org.apache.hadoop.fs.impl.FutureDataInputStreamBuilderImpl;
49+
import org.apache.hadoop.fs.impl.FsLinkResolution;
50+
import org.apache.hadoop.fs.impl.PathCapabilitiesSupport;
4951
import org.apache.hadoop.fs.permission.AclEntry;
5052
import org.apache.hadoop.fs.permission.AclStatus;
5153
import org.apache.hadoop.fs.permission.FsAction;
@@ -171,7 +173,7 @@
171173

172174
@InterfaceAudience.Public
173175
@InterfaceStability.Stable
174-
public class FileContext {
176+
public class FileContext implements PathCapabilities {
175177

176178
public static final Logger LOG = LoggerFactory.getLogger(FileContext.class);
177179
/**
@@ -2934,4 +2936,21 @@ public CompletableFuture<FSDataInputStream> next(
29342936
}.resolve(FileContext.this, absF);
29352937
}
29362938
}
2939+
2940+
/**
2941+
* Return the path capabilities of the bonded {@code AbstractFileSystem}.
2942+
* @param path path to query the capability of.
2943+
* @param capability string to query the stream support for.
2944+
* @return true iff the capability is supported under that FS.
2945+
* @throws IOException path resolution or other IO failure
2946+
* @throws IllegalArgumentException invalid arguments
2947+
*/
2948+
public boolean hasPathCapability(Path path, String capability)
2949+
throws IOException {
2950+
PathCapabilitiesSupport.validatehasPathCapabilityArgs(path, capability);
2951+
return FsLinkResolution.resolve(this,
2952+
fixRelativePart(path),
2953+
(fs, p) -> fs.hasPathCapability(p, capability));
2954+
}
2955+
29372956
}

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.IdentityHashMap;
3636
import java.util.Iterator;
3737
import java.util.List;
38+
import java.util.Locale;
3839
import java.util.Map;
3940
import java.util.NoSuchElementException;
4041
import java.util.Optional;
@@ -58,6 +59,7 @@
5859
import org.apache.hadoop.fs.Options.Rename;
5960
import org.apache.hadoop.fs.impl.AbstractFSBuilderImpl;
6061
import org.apache.hadoop.fs.impl.FutureDataInputStreamBuilderImpl;
62+
import org.apache.hadoop.fs.impl.PathCapabilitiesSupport;
6163
import org.apache.hadoop.fs.permission.AclEntry;
6264
import org.apache.hadoop.fs.permission.AclStatus;
6365
import org.apache.hadoop.fs.permission.FsAction;
@@ -134,7 +136,7 @@
134136
@InterfaceAudience.Public
135137
@InterfaceStability.Stable
136138
public abstract class FileSystem extends Configured
137-
implements Closeable, DelegationTokenIssuer {
139+
implements Closeable, DelegationTokenIssuer, PathCapabilities {
138140
public static final String FS_DEFAULT_NAME_KEY =
139141
CommonConfigurationKeys.FS_DEFAULT_NAME_KEY;
140142
public static final String DEFAULT_FS =
@@ -709,6 +711,7 @@ protected FileSystem() {
709711
*
710712
*/
711713
protected void checkPath(Path path) {
714+
Preconditions.checkArgument(path != null, "null path");
712715
URI uri = path.toUri();
713716
String thatScheme = uri.getScheme();
714717
if (thatScheme == null) // fs is relative
@@ -3213,6 +3216,31 @@ public Collection<FileStatus> getTrashRoots(boolean allUsers) {
32133216
return ret;
32143217
}
32153218

3219+
/**
3220+
* The base FileSystem implementation generally has no knowledge
3221+
* of the capabilities of actual implementations.
3222+
* Unless it has a way to explicitly determine the capabilities,
3223+
* this method returns false.
3224+
* {@inheritDoc}
3225+
*/
3226+
public boolean hasPathCapability(final Path path, final String capability)
3227+
throws IOException {
3228+
PathCapabilitiesSupport.validatehasPathCapabilityArgs(path, capability);
3229+
// qualify the path to make sure that it refers to the current FS.
3230+
makeQualified(path);
3231+
switch (capability.toLowerCase(Locale.ENGLISH)) {
3232+
case CommonPathCapabilities.FS_SYMLINKS:
3233+
// delegate to the existing supportsSymlinks() call.
3234+
return supportsSymlinks() && areSymlinksEnabled();
3235+
case CommonPathCapabilities.FS_DELEGATION_TOKENS:
3236+
// this is less efficient than it should be.
3237+
return getCanonicalServiceName() != null;
3238+
default:
3239+
// the feature is not implemented.
3240+
return false;
3241+
}
3242+
}
3243+
32163244
// making it volatile to be able to do a double checked locking
32173245
private volatile static boolean FILE_SYSTEMS_LOADED = false;
32183246

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,4 +725,10 @@ protected CompletableFuture<FSDataInputStream> openFileWithOptions(
725725
return fs.openFileWithOptions(pathHandle, mandatoryKeys, options,
726726
bufferSize);
727727
}
728+
729+
public boolean hasPathCapability(final Path path, final String capability)
730+
throws IOException {
731+
return fs.hasPathCapability(path, capability);
732+
}
733+
728734
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,4 +446,9 @@ public CompletableFuture<FSDataInputStream> openFileWithOptions(
446446
return myFs.openFileWithOptions(path, mandatoryKeys, options, bufferSize);
447447
}
448448

449+
public boolean hasPathCapability(final Path path,
450+
final String capability)
451+
throws IOException {
452+
return myFs.hasPathCapability(path, capability);
453+
}
449454
}

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.hadoop.fs;
1919

2020
import org.apache.hadoop.conf.Configuration;
21+
import org.apache.hadoop.fs.impl.PathCapabilitiesSupport;
2122
import org.apache.hadoop.fs.permission.FsPermission;
2223
import org.apache.hadoop.fs.Options.HandleOpt;
2324
import org.apache.hadoop.io.IOUtils;
@@ -899,7 +900,23 @@ public void setPermission(Path p, FsPermission permission)
899900
throws IOException {
900901
throw new IOException("Har: setPermission not allowed");
901902
}
902-
903+
904+
/**
905+
* Declare that this filesystem connector is always read only.
906+
* {@inheritDoc}
907+
*/
908+
@Override
909+
public boolean hasPathCapability(final Path path, final String capability)
910+
throws IOException {
911+
PathCapabilitiesSupport.validatehasPathCapabilityArgs(path, capability);
912+
switch (capability.toLowerCase(Locale.ENGLISH)) {
913+
case CommonPathCapabilities.FS_READ_ONLY_CONNECTOR:
914+
return true;
915+
default:
916+
return false;
917+
}
918+
}
919+
903920
/**
904921
* Hadoop archives input stream. This input stream fakes EOF
905922
* since archive files are part of bigger part files.

0 commit comments

Comments
 (0)