Skip to content

Commit 9726b46

Browse files
steveloughrandeepakdamri
authored andcommitted
HADOOP-15691 Add PathCapabilities to FileSystem and FileContext.
Contributed by Steve Loughran. This complements the StreamCapabilities Interface by allowing applications to probe for a specific path on a specific instance of a FileSystem client to offer a specific capability. This is intended to allow applications to determine * Whether a method is implemented before calling it and dealing with UnsupportedOperationException. * Whether a specific feature is believed to be available in the remote store. As well as a common set of capabilities defined in CommonPathCapabilities, file systems are free to add their own capabilities, prefixed with fs. + schema + . The plan is to identify and document more capabilities -and for file systems which add new features, for a declaration of the availability of the feature to always be available. Note * The remote store is not expected to be checked for the feature; It is more a check of client API and the client's configuration/knowledge of the state of the remote system. * Permissions are not checked. Change-Id: I80bfebe94f4a8bdad8f3ac055495735b824968f5
1 parent e158c78 commit 9726b46

File tree

17 files changed

+155
-24
lines changed

17 files changed

+155
-24
lines changed

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
import org.slf4j.Logger;
6161
import org.slf4j.LoggerFactory;
6262

63+
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;
64+
6365
/**
6466
* This class provides an interface for implementors of a Hadoop file system
6567
* (analogous to the VFS of Unix). Applications do not access this class;
@@ -72,7 +74,7 @@
7274
*/
7375
@InterfaceAudience.Public
7476
@InterfaceStability.Stable
75-
public abstract class AbstractFileSystem {
77+
public abstract class AbstractFileSystem implements PathCapabilities {
7678
static final Logger LOG = LoggerFactory.getLogger(AbstractFileSystem.class);
7779

7880
/** Recording statistics per a file system class. */
@@ -1371,4 +1373,16 @@ public CompletableFuture<FSDataInputStream> openFileWithOptions(Path path,
13711373
new CompletableFuture<>(), () -> open(path, bufferSize));
13721374
}
13731375

1376+
public boolean hasPathCapability(final Path path,
1377+
final String capability)
1378+
throws IOException {
1379+
switch (validatePathCapabilityArgs(makeQualified(path), capability)) {
1380+
case CommonPathCapabilities.FS_SYMLINKS:
1381+
// delegate to the existing supportsSymlinks() call.
1382+
return supportsSymlinks();
1383+
default:
1384+
// the feature is not implemented.
1385+
return false;
1386+
}
1387+
}
13741388
}

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: 22 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;
@@ -68,6 +70,8 @@
6870
import org.slf4j.Logger;
6971
import org.slf4j.LoggerFactory;
7072

73+
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;
74+
7175
/**
7276
* The FileContext class provides an interface for users of the Hadoop
7377
* file system. It exposes a number of file system operations, e.g. create,
@@ -171,7 +175,7 @@
171175

172176
@InterfaceAudience.Public
173177
@InterfaceStability.Stable
174-
public class FileContext {
178+
public class FileContext implements PathCapabilities {
175179

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

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

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

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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939

4040
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;
4141

42+
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;
43+
4244
/**
4345
* This is an implementation of the Hadoop Archive
4446
* Filesystem. This archive Filesystem has index files

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/contract/ContractTestUtils.java

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.hadoop.fs.FileSystem;
2626
import org.apache.hadoop.fs.LocatedFileStatus;
2727
import org.apache.hadoop.fs.Path;
28+
import org.apache.hadoop.fs.PathCapabilities;
2829
import org.apache.hadoop.fs.RemoteIterator;
2930
import org.apache.hadoop.fs.StreamCapabilities;
3031
import org.apache.hadoop.io.IOUtils;
@@ -1466,22 +1467,61 @@ public static void assertCapabilities(
14661467
assertTrue("Stream should be instanceof StreamCapabilities",
14671468
stream instanceof StreamCapabilities);
14681469

1469-
if (shouldHaveCapabilities!=null) {
1470+
StreamCapabilities source = (StreamCapabilities) stream;
1471+
if (shouldHaveCapabilities != null) {
14701472
for (String shouldHaveCapability : shouldHaveCapabilities) {
14711473
assertTrue("Should have capability: " + shouldHaveCapability,
1472-
((StreamCapabilities) stream).hasCapability(shouldHaveCapability));
1474+
source.hasCapability(shouldHaveCapability));
14731475
}
14741476
}
14751477

1476-
if (shouldNotHaveCapabilities!=null) {
1478+
if (shouldNotHaveCapabilities != null) {
14771479
for (String shouldNotHaveCapability : shouldNotHaveCapabilities) {
14781480
assertFalse("Should not have capability: " + shouldNotHaveCapability,
1479-
((StreamCapabilities) stream)
1480-
.hasCapability(shouldNotHaveCapability));
1481+
source.hasCapability(shouldNotHaveCapability));
14811482
}
14821483
}
14831484
}
14841485

1486+
/**
1487+
* Custom assert to test {@link PathCapabilities}.
1488+
*
1489+
* @param source source (FS, FC, etc)
1490+
* @param path path to check
1491+
* @param capabilities The array of unexpected capabilities
1492+
*/
1493+
public static void assertHasPathCapabilities(
1494+
final PathCapabilities source,
1495+
final Path path,
1496+
final String...capabilities) throws IOException {
1497+
1498+
for (String shouldHaveCapability: capabilities) {
1499+
assertTrue("Should have capability: " + shouldHaveCapability
1500+
+ " under " + path,
1501+
source.hasPathCapability(path, shouldHaveCapability));
1502+
}
1503+
}
1504+
1505+
/**
1506+
* Custom assert to test that the named {@link PathCapabilities}
1507+
* are not supported.
1508+
*
1509+
* @param source source (FS, FC, etc)
1510+
* @param path path to check
1511+
* @param capabilities The array of unexpected capabilities
1512+
*/
1513+
public static void assertLacksPathCapabilities(
1514+
final PathCapabilities source,
1515+
final Path path,
1516+
final String...capabilities) throws IOException {
1517+
1518+
for (String shouldHaveCapability: capabilities) {
1519+
assertFalse("Path must not support capability: " + shouldHaveCapability
1520+
+ " under " + path,
1521+
source.hasPathCapability(path, shouldHaveCapability));
1522+
}
1523+
}
1524+
14851525
/**
14861526
* Function which calls {@code InputStream.read()} and
14871527
* downgrades an IOE to a runtime exception.

hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.apache.hadoop.fs.BlockLocation;
3232
import org.apache.hadoop.fs.BlockStoragePolicySpi;
3333
import org.apache.hadoop.fs.CacheFlag;
34+
import org.apache.hadoop.fs.CommonPathCapabilities;
3435
import org.apache.hadoop.fs.ContentSummary;
3536
import org.apache.hadoop.fs.CreateFlag;
3637
import org.apache.hadoop.fs.FSDataInputStream;
@@ -122,6 +123,8 @@
122123
import java.util.Map;
123124
import java.util.Optional;
124125

126+
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;
127+
125128
/****************************************************************
126129
* Implementation of the abstract FileSystem for the DFS system.
127130
* This object is the way end-user code interacts with a Hadoop

hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/web/WebHdfsFileSystem.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import org.apache.hadoop.crypto.key.KeyProviderTokenIssuer;
6464
import org.apache.hadoop.fs.BlockLocation;
6565
import org.apache.hadoop.fs.CommonConfigurationKeys;
66+
import org.apache.hadoop.fs.CommonPathCapabilities;
6667
import org.apache.hadoop.fs.ContentSummary;
6768
import org.apache.hadoop.fs.CreateFlag;
6869
import org.apache.hadoop.fs.DelegationTokenRenewer;
@@ -76,6 +77,7 @@
7677
import org.apache.hadoop.fs.GlobalStorageStatistics;
7778
import org.apache.hadoop.fs.GlobalStorageStatistics.StorageStatisticsProvider;
7879
import org.apache.hadoop.fs.QuotaUsage;
80+
import org.apache.hadoop.fs.PathCapabilities;
7981
import org.apache.hadoop.fs.StorageStatistics;
8082
import org.apache.hadoop.fs.StorageType;
8183
import org.apache.hadoop.fs.permission.FsCreateModes;
@@ -135,6 +137,8 @@
135137
import com.google.common.base.Preconditions;
136138
import com.google.common.collect.Lists;
137139

140+
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;
141+
138142
/** A FileSystem for HDFS over the web. */
139143
public class WebHdfsFileSystem extends FileSystem
140144
implements DelegationTokenRenewer.Renewable,

hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/client/HttpFSFileSystem.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import java.security.PrivilegedExceptionAction;
8787
import java.text.MessageFormat;
8888
import java.util.HashMap;
89+
import java.util.Locale;
8990
import java.util.Map;
9091

9192
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;

0 commit comments

Comments
 (0)