Skip to content

Commit 3637cf1

Browse files
author
Sean Mackrory
committed
Iterating on Gabor's feedback
1 parent 38cd137 commit 3637cf1

File tree

3 files changed

+68
-60
lines changed

3 files changed

+68
-60
lines changed

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public class S3AFileSystem extends FileSystem implements StreamCapabilities,
238238
private volatile boolean isClosed = false;
239239
private MetadataStore metadataStore;
240240
private boolean allowAuthoritativeMetadataStore;
241-
private Collection<String> allowAuthoritativePaths = new ArrayList<>();
241+
private Collection<String> allowAuthoritativePaths;
242242

243243
/** Delegation token integration; non-empty when DT support is enabled. */
244244
private Optional<S3ADelegationTokens> delegationTokens = Optional.empty();
@@ -400,15 +400,7 @@ public void initialize(URI name, Configuration originalConf)
400400
setMetadataStore(S3Guard.getMetadataStore(this));
401401
allowAuthoritativeMetadataStore = conf.getBoolean(METADATASTORE_AUTHORITATIVE,
402402
DEFAULT_METADATASTORE_AUTHORITATIVE);
403-
404-
String[] authoritativePaths =
405-
conf.getTrimmedStrings(AUTHORITATIVE_PATH, DEFAULT_AUTHORITATIVE_PATH);
406-
if (authoritativePaths.length > 0) {
407-
for (int i = 0; i < authoritativePaths.length; i++) {
408-
Path qualified = qualify(new Path(authoritativePaths[i]));
409-
allowAuthoritativePaths.add(maybeAddTrailingSlash(qualified.toString()));
410-
}
411-
}
403+
allowAuthoritativePaths = S3Guard.getAuthoritativePaths(this);
412404

413405
if (hasMetadataStore()) {
414406
LOG.debug("Using metadata store {}, authoritative store={}, authoritative path={}",
@@ -421,23 +413,6 @@ public void initialize(URI name, Configuration originalConf)
421413

422414
}
423415

424-
@VisibleForTesting
425-
boolean allowAuthoritative(Path p) {
426-
String haystack = maybeAddTrailingSlash(p.toString());
427-
if (allowAuthoritativeMetadataStore) {
428-
return true;
429-
}
430-
if (!allowAuthoritativePaths.isEmpty()) {
431-
for (String needle : allowAuthoritativePaths) {
432-
433-
if (haystack.startsWith(needle)) {
434-
return true;
435-
}
436-
}
437-
}
438-
return false;
439-
}
440-
441416
/**
442417
* Initialize the thread pool.
443418
* This must be re-invoked after replacing the S3Client during test
@@ -868,7 +843,8 @@ public String pathToKey(Path path) {
868843
* @param key s3 key or ""
869844
* @return the with a trailing "/", or, if it is the root key, "",
870845
*/
871-
private String maybeAddTrailingSlash(String key) {
846+
@InterfaceAudience.Private
847+
public String maybeAddTrailingSlash(String key) {
872848
if (!key.isEmpty() && !key.endsWith("/")) {
873849
return key + '/';
874850
} else {
@@ -2426,7 +2402,9 @@ public FileStatus[] innerListStatus(Path f) throws FileNotFoundException,
24262402

24272403
DirListingMetadata dirMeta =
24282404
S3Guard.listChildrenWithTtl(metadataStore, path, ttlTimeProvider);
2429-
if (allowAuthoritative(f) && dirMeta != null && dirMeta.isAuthoritative()) {
2405+
boolean allowAuthoritative = S3Guard.allowAuthoritative(f, this,
2406+
allowAuthoritativeMetadataStore, allowAuthoritativePaths);
2407+
if (allowAuthoritative && dirMeta != null && dirMeta.isAuthoritative()) {
24302408
return S3Guard.dirMetaToStatuses(dirMeta);
24312409
}
24322410

@@ -2443,8 +2421,9 @@ public FileStatus[] innerListStatus(Path f) throws FileNotFoundException,
24432421
result.add(files.next());
24442422
}
24452423
// merge the results. This will update the store as needed
2424+
24462425
return S3Guard.dirListingUnion(metadataStore, path, result, dirMeta,
2447-
allowAuthoritative(f), ttlTimeProvider);
2426+
allowAuthoritative, ttlTimeProvider);
24482427
} else {
24492428
LOG.debug("Adding: rd (not a dir): {}", path);
24502429
FileStatus[] stats = new FileStatus[1];
@@ -2657,8 +2636,10 @@ S3AFileStatus innerGetFileStatus(final Path f,
26572636
// dest is also a directory, there's no difference.
26582637
// TODO After HADOOP-16085 the modification detection can be done with
26592638
// etags or object version instead of modTime
2639+
boolean allowAuthoritative = S3Guard.allowAuthoritative(f, this,
2640+
allowAuthoritativeMetadataStore, allowAuthoritativePaths);
26602641
if (!pm.getFileStatus().isDirectory() &&
2661-
!allowAuthoritative(f)) {
2642+
!allowAuthoritative) {
26622643
LOG.debug("Metadata for {} found in the non-auth metastore.", path);
26632644
final long msModTime = pm.getFileStatus().getModificationTime();
26642645

@@ -3823,13 +3804,16 @@ private RemoteIterator<S3ALocatedFileStatus> innerListFiles(Path f, boolean
38233804
key, delimiter);
38243805
final RemoteIterator<S3AFileStatus> cachedFilesIterator;
38253806
final Set<Path> tombstones;
3807+
boolean allowAuthoritative = S3Guard.allowAuthoritative(f, this,
3808+
allowAuthoritativeMetadataStore, allowAuthoritativePaths);
38263809
if (recursive) {
38273810
final PathMetadata pm = metadataStore.get(path, true);
38283811
// shouldn't need to check pm.isDeleted() because that will have
38293812
// been caught by getFileStatus above.
3813+
38303814
MetadataStoreListFilesIterator metadataStoreListFilesIterator =
38313815
new MetadataStoreListFilesIterator(metadataStore, pm,
3832-
allowAuthoritative(f));
3816+
allowAuthoritative);
38333817
tombstones = metadataStoreListFilesIterator.listTombstones();
38343818
cachedFilesIterator = metadataStoreListFilesIterator;
38353819
} else {
@@ -3842,7 +3826,7 @@ private RemoteIterator<S3ALocatedFileStatus> innerListFiles(Path f, boolean
38423826
}
38433827
cachedFilesIterator = listing.createProvidedFileStatusIterator(
38443828
S3Guard.dirMetaToStatuses(meta), ACCEPT_ALL, acceptor);
3845-
if (allowAuthoritative(f) && meta != null && meta.isAuthoritative()) {
3829+
if (allowAuthoritative && meta != null && meta.isAuthoritative()) {
38463830
// metadata listing is authoritative, so return it directly
38473831
return listing.createLocatedFileStatusIterator(cachedFilesIterator);
38483832
}
@@ -3915,7 +3899,9 @@ public RemoteIterator<LocatedFileStatus> listLocatedStatus(final Path f,
39153899
final RemoteIterator<S3AFileStatus> cachedFileStatusIterator =
39163900
listing.createProvidedFileStatusIterator(
39173901
S3Guard.dirMetaToStatuses(meta), filter, acceptor);
3918-
return (allowAuthoritative(f) && meta != null
3902+
boolean allowAuthoritative = S3Guard.allowAuthoritative(f, this,
3903+
allowAuthoritativeMetadataStore, allowAuthoritativePaths);
3904+
return (allowAuthoritative && meta != null
39193905
&& meta.isAuthoritative())
39203906
? listing.createLocatedFileStatusIterator(
39213907
cachedFileStatusIterator)

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/S3Guard.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import com.google.common.annotations.VisibleForTesting;
3636
import com.google.common.base.Preconditions;
37+
import org.apache.hadoop.fs.s3a.S3AFileSystem;
3738
import org.slf4j.Logger;
3839
import org.slf4j.LoggerFactory;
3940

@@ -49,9 +50,8 @@
4950
import org.apache.hadoop.fs.s3a.S3AInstrumentation;
5051
import org.apache.hadoop.util.ReflectionUtils;
5152

52-
import static org.apache.hadoop.fs.s3a.Constants.DEFAULT_METADATASTORE_METADATA_TTL;
53-
import static org.apache.hadoop.fs.s3a.Constants.METADATASTORE_METADATA_TTL;
54-
import static org.apache.hadoop.fs.s3a.Constants.S3_METADATA_STORE_IMPL;
53+
import static org.apache.hadoop.fs.s3a.Constants.*;
54+
import static org.apache.hadoop.fs.s3a.Constants.DEFAULT_AUTHORITATIVE_PATH;
5555
import static org.apache.hadoop.fs.s3a.Statistic.S3GUARD_METADATASTORE_PUT_PATH_LATENCY;
5656
import static org.apache.hadoop.fs.s3a.Statistic.S3GUARD_METADATASTORE_PUT_PATH_REQUEST;
5757
import static org.apache.hadoop.fs.s3a.S3AUtils.createUploadFileStatus;
@@ -772,4 +772,33 @@ public static DirListingMetadata listChildrenWithTtl(MetadataStore ms,
772772
return dlm;
773773
}
774774

775+
public static Collection<String> getAuthoritativePaths(S3AFileSystem fs) {
776+
String[] rawAuthoritativePaths =
777+
fs.getConf().getTrimmedStrings(AUTHORITATIVE_PATH, DEFAULT_AUTHORITATIVE_PATH);
778+
Collection<String> authoritativePaths = new ArrayList<>();
779+
if (rawAuthoritativePaths.length > 0) {
780+
for (int i = 0; i < rawAuthoritativePaths.length; i++) {
781+
Path qualified = fs.qualify(new Path(rawAuthoritativePaths[i]));
782+
authoritativePaths.add(fs.maybeAddTrailingSlash(qualified.toString()));
783+
}
784+
}
785+
return authoritativePaths;
786+
}
787+
788+
public static boolean allowAuthoritative(Path p, S3AFileSystem fs,
789+
boolean authMetadataStore, Collection<String> authPaths) {
790+
String haystack = fs.maybeAddTrailingSlash(p.toString());
791+
if (authMetadataStore) {
792+
return true;
793+
}
794+
if (!authPaths.isEmpty()) {
795+
for (String needle : authPaths) {
796+
797+
if (haystack.startsWith(needle)) {
798+
return true;
799+
}
800+
}
801+
}
802+
return false;
803+
}
775804
}

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestAuthoritativePath.java

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020

2121
import java.io.IOException;
2222
import java.net.URI;
23+
import java.util.Collection;
2324

2425
import org.apache.hadoop.fs.s3a.s3guard.NullMetadataStore;
26+
import org.apache.hadoop.fs.s3a.s3guard.S3Guard;
2527
import org.apache.hadoop.io.IOUtils;
2628
import org.apache.hadoop.conf.Configuration;
2729
import org.apache.hadoop.fs.Path;
@@ -45,7 +47,7 @@ public class ITestAuthoritativePath extends AbstractS3ATestBase {
4547
public Path testRoot;
4648

4749
private S3AFileSystem fullyAuthFS;
48-
private S3AFileSystem unguardedFS;
50+
private S3AFileSystem rawFS;
4951

5052
private MetadataStore ms;
5153

@@ -75,9 +77,9 @@ public void setup() throws Exception {
7577
assertTrue("Authoritative mode off in fullyAuthFS",
7678
fullyAuthFS.hasAuthoritativeMetadataStore());
7779

78-
unguardedFS = createUnguardedFS();
80+
rawFS = createRawFS();
7981
assertFalse("UnguardedFS still has S3Guard",
80-
unguardedFS.hasMetadataStore());
82+
rawFS.hasMetadataStore());
8183
}
8284

8385
private void cleanUpFS(S3AFileSystem fs) {
@@ -92,7 +94,7 @@ public void teardown() throws Exception {
9294
fullyAuthFS.delete(testRoot, true);
9395

9496
cleanUpFS(fullyAuthFS);
95-
cleanUpFS(unguardedFS);
97+
cleanUpFS(rawFS);
9698
super.teardown();
9799
}
98100

@@ -141,20 +143,7 @@ private S3AFileSystem createMultiPathAuthFS(String first, String middle, String
141143
return newFS;
142144
}
143145

144-
private S3AFileSystem createNonAuthFS() throws Exception {
145-
S3AFileSystem testFS = getFileSystem();
146-
Configuration config = new Configuration(testFS.getConf());
147-
URI uri = testFS.getUri();
148-
149-
removeBaseAndBucketOverrides(uri.getHost(), config,
150-
METADATASTORE_AUTHORITATIVE, AUTHORITATIVE_PATH);
151-
final S3AFileSystem newFS = createFS(uri, config);
152-
// set back the same metadata store instance
153-
newFS.setMetadataStore(ms);
154-
return newFS;
155-
}
156-
157-
private S3AFileSystem createUnguardedFS() throws Exception {
146+
private S3AFileSystem createRawFS() throws Exception {
158147
S3AFileSystem testFS = getFileSystem();
159148
Configuration config = new Configuration(testFS.getConf());
160149
URI uri = testFS.getUri();
@@ -190,7 +179,7 @@ private void runTestOutsidePath(S3AFileSystem partiallyAuthFS, Path nonAuthPath)
190179
// trigger an authoritative write-back
191180
fullyAuthFS.listStatus(inBandPath.getParent());
192181

193-
touch(unguardedFS, outOfBandPath);
182+
touch(rawFS, outOfBandPath);
194183

195184
// listing lacks outOfBandPath => short-circuited by auth mode
196185
checkListingDoesNotContainPath(fullyAuthFS, outOfBandPath);
@@ -213,7 +202,7 @@ private void runTestInsidePath(S3AFileSystem partiallyAuthFS, Path authPath) thr
213202
// trigger an authoritative write-back
214203
fullyAuthFS.listStatus(inBandPath.getParent());
215204

216-
touch(unguardedFS, outOfBandPath);
205+
touch(rawFS, outOfBandPath);
217206

218207
// listing lacks outOfBandPath => short-circuited by auth mode
219208
checkListingDoesNotContainPath(fullyAuthFS, outOfBandPath);
@@ -291,16 +280,20 @@ public void testMultiAuthPath() throws Exception {
291280
@Test
292281
public void testPrefixVsDirectory() throws Exception {
293282
S3AFileSystem fs = createSinglePathAuthFS("/auth");
283+
Collection<String> authPaths = S3Guard.getAuthoritativePaths(fs);
294284

295285
try{
296286
Path totalMismatch = new Path(testRoot, "/non-auth");
297-
assertFalse(fs.allowAuthoritative(totalMismatch));
287+
assertFalse(S3Guard.allowAuthoritative(totalMismatch, fs,
288+
false, authPaths));
298289

299290
Path prefixMatch = new Path(testRoot, "/authoritative");
300-
assertFalse(fs.allowAuthoritative(prefixMatch));
291+
assertFalse(S3Guard.allowAuthoritative(prefixMatch, fs,
292+
false, authPaths));
301293

302294
Path directoryMatch = new Path(testRoot, "/auth/oritative");
303-
assertTrue(fs.allowAuthoritative(directoryMatch));
295+
assertTrue(S3Guard.allowAuthoritative(directoryMatch, fs,
296+
false, authPaths));
304297
} finally {
305298
cleanUpFS(fs);
306299
}

0 commit comments

Comments
 (0)