Skip to content

Commit d04aa2e

Browse files
committed
HADOOP-19256. review of conditional write
+ hadoop common and s3a create file options wired up to s3a create file builder, and nowhere else. Change-Id: Ieaafa9ecdfd68306deb41ecf40c416374a310859
1 parent b19da55 commit d04aa2e

File tree

13 files changed

+312
-73
lines changed

13 files changed

+312
-73
lines changed

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,4 +710,55 @@ private OpenFileOptions() {
710710
public static final String FS_OPTION_OPENFILE_EC_POLICY =
711711
FS_OPTION_OPENFILE + "ec.policy";
712712
}
713+
714+
/**
715+
* The standard {@code createFile()} options.
716+
* <p>
717+
* If an option is not supported during file creation and it is considered
718+
* part of a commit protocol, then, when supplied in a must() option,
719+
* it MUST be rejected.
720+
*/
721+
@InterfaceAudience.Public
722+
@InterfaceStability.Evolving
723+
public interface CreateFileOptionKeys {
724+
725+
/**
726+
* {code createFile()} option to write a file iff there is nothing at the destination.
727+
* This may happen during create() or in the close.
728+
* <p>
729+
* Explicitly set {@link #FS_OPTION_CREATE_IN_CLOSE} if you want to force the end of file
730+
* creation.
731+
*
732+
* Value {@value}.
733+
* <p>
734+
* This can be set in the builder.
735+
* <p>
736+
* It should be exported as a path capability for all stores where
737+
* the feature is available *and* enabled.
738+
*/
739+
String FS_OPTION_CREATE_CONDITIONAL_OVERWRITE = "fs.option.create.conditional.overwrite";
740+
741+
/**
742+
* Overwrite a file only if there is an Etag match. This option takes a string.
743+
* Value {@value}.
744+
*/
745+
String FS_OPTION_CREATE_CONDITIONAL_OVERWRITE_ETAG =
746+
"fs.option.create.conditional.overwrite.etag";
747+
748+
/**
749+
* String to define the content filetype.
750+
* Value {@value}.
751+
*/
752+
String FS_OPTION_CREATE_CONTENT_TYPE = "fs.option.create.content.type";
753+
754+
/**
755+
* A flag which requires the filesystem to create files/objects in close(),
756+
* rather than create/createFile.
757+
* <p>
758+
* Object stores with this behavior should also export it as a path capability.
759+
*
760+
* Value {@value}.
761+
*/
762+
String FS_OPTION_CREATE_IN_CLOSE = "fs.option.create.in.close";
763+
}
713764
}

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

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,13 +1502,6 @@ private Constants() {
15021502
*/
15031503
public static final String FS_S3A_CREATE_PERFORMANCE = "fs.s3a.create.performance";
15041504

1505-
/**
1506-
* Flag for commit if none match.
1507-
* This can be set in the {code createFile()} builder.
1508-
* Value {@value}.
1509-
*/
1510-
public static final String FS_S3A_CONDITIONAL_FILE_CREATE = "fs.s3a.conditional.file.create";
1511-
15121505
/**
15131506
* Default value for create performance in an S3A FS.
15141507
* Value {@value}.
@@ -1528,6 +1521,23 @@ private Constants() {
15281521
*/
15291522
public static final String FS_S3A_PERFORMANCE_FLAGS =
15301523
"fs.s3a.performance.flags";
1524+
1525+
1526+
/**
1527+
* Is the create overwrite feature enabled or not?
1528+
* A configuration option and a path status probe.
1529+
* Value {@value}.
1530+
*/
1531+
public static final String FS_S3A_CREATE_OVERWRITE_SUPPORTED = "fs.s3a.create.overwrite.supported";
1532+
1533+
/**
1534+
* Create a multipart file, always: {@value}.
1535+
* <p>
1536+
* This is inefficient and will not work on a store which doesn't support that feature,
1537+
* so is primarily for testing.
1538+
*/
1539+
public static final String FS_S3A_CREATE_MULTIPART = "fs.s3a.create.multipart";
1540+
15311541
/**
15321542
* Prefix for adding a header to the object when created.
15331543
* The actual value must have a "." suffix and then the actual header.

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

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@
223223
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_DEFAULT;
224224
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_KEY;
225225
import static org.apache.hadoop.fs.CommonPathCapabilities.DIRECTORY_LISTING_INCONSISTENT;
226+
import static org.apache.hadoop.fs.Options.CreateFileOptionKeys.FS_OPTION_CREATE_CONDITIONAL_OVERWRITE;
227+
import static org.apache.hadoop.fs.Options.CreateFileOptionKeys.FS_OPTION_CREATE_CONDITIONAL_OVERWRITE_ETAG;
228+
import static org.apache.hadoop.fs.Options.CreateFileOptionKeys.FS_OPTION_CREATE_CONTENT_TYPE;
229+
import static org.apache.hadoop.fs.Options.CreateFileOptionKeys.FS_OPTION_CREATE_IN_CLOSE;
226230
import static org.apache.hadoop.fs.impl.FlagSet.buildFlagSet;
227231
import static org.apache.hadoop.fs.impl.PathCapabilitiesSupport.validatePathCapabilityArgs;
228232
import static org.apache.hadoop.fs.s3a.Constants.*;
@@ -2171,9 +2175,9 @@ private FSDataOutputStream innerCreateFile(
21712175
String destKey = putTracker.getDestKey();
21722176

21732177
// put options are derived from the option builder.
2174-
boolean conditionalCreate = options.isConditionalCreate();
2178+
boolean conditionalCreate = options.isConditionalOverwrite();
21752179
final PutObjectOptions putOptions =
2176-
new PutObjectOptions(null, options.getHeaders(), false, null);
2180+
new PutObjectOptions(null, options.getHeaders(), conditionalCreate, null);
21772181

21782182

21792183
validateOutputStreamConfiguration(path, getConf());
@@ -3248,7 +3252,8 @@ private DeleteObjectsResponse deleteObjects(DeleteObjectsRequest deleteRequest)
32483252
public PutObjectRequest.Builder newPutObjectRequestBuilder(String key,
32493253
long length,
32503254
boolean isDirectoryMarker) {
3251-
return requestFactory.newPutObjectRequestBuilder(key, null, length, isDirectoryMarker);
3255+
return requestFactory.newPutObjectRequestBuilder(key, null, length, isDirectoryMarker,
3256+
PutObjectOptions.defaultOptions());
32523257
}
32533258

32543259
/**
@@ -5416,11 +5421,19 @@ public boolean hasPathCapability(final Path path, final String capability)
54165421
case STORE_CAPABILITY_DIRECTORY_MARKER_MULTIPART_UPLOAD_ENABLED:
54175422
return isMultipartUploadEnabled();
54185423

5419-
// create file options
5424+
// create file options which are always true
5425+
5426+
case FS_OPTION_CREATE_IN_CLOSE:
5427+
case FS_OPTION_CREATE_CONTENT_TYPE:
54205428
case FS_S3A_CREATE_PERFORMANCE:
54215429
case FS_S3A_CREATE_HEADER:
54225430
return true;
54235431

5432+
case FS_OPTION_CREATE_CONDITIONAL_OVERWRITE:
5433+
case FS_OPTION_CREATE_CONDITIONAL_OVERWRITE_ETAG:
5434+
// TODO HADOOP-19256. conditional on enablement
5435+
return true;
5436+
54245437
// is the FS configured for create file performance
54255438
case FS_S3A_CREATE_PERFORMANCE_ENABLED:
54265439
return performanceFlags.enabled(PerformanceFlagEnum.Create);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ public PutObjectRequest createPutObjectRequest(String destKey,
245245
activateAuditSpan();
246246

247247
return getRequestFactory()
248-
.newPutObjectRequestBuilder(destKey, options, length, false)
248+
.newPutObjectRequestBuilder(destKey, options, length, false, options)
249249
.build();
250250
}
251251

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,14 @@ CopyObjectRequest.Builder newCopyObjectRequestBuilder(String srcKey,
118118
* @param options options for the request
119119
* @param length length of object to be uploaded
120120
* @param isDirectoryMarker true if object to be uploaded is a directory marker
121+
* @param putOptions
121122
* @return the request builder
122123
*/
123124
PutObjectRequest.Builder newPutObjectRequestBuilder(String key,
124125
PutObjectOptions options,
125126
long length,
126-
boolean isDirectoryMarker);
127+
boolean isDirectoryMarker,
128+
PutObjectOptions putOptions);
127129

128130
/**
129131
* Create a {@link PutObjectRequest} request for creating

0 commit comments

Comments
 (0)