Skip to content

HDDS-13919. S3 Conditional Writes (PutObject) [1/2]#9815

Merged
jojochuang merged 39 commits intoapache:masterfrom
peterxcli:HDDS-13919-conditional-writes
Apr 1, 2026
Merged

HDDS-13919. S3 Conditional Writes (PutObject) [1/2]#9815
jojochuang merged 39 commits intoapache:masterfrom
peterxcli:HDDS-13919-conditional-writes

Conversation

@peterxcli
Copy link
Copy Markdown
Member

@peterxcli peterxcli commented Feb 24, 2026

What changes were proposed in this pull request?

  • Add createKeyIfNotExists, rewriteKeyIfMatch to RpcClient API, prevent the logic mix wit the existing rewriteKey
  • Object Endpoint put endpoint handler multiplex createKeyIfNotExists, rewriteKeyIfMatch and createKey
  • OM side validation logic of etag matching in key creation and commit request
  • Error translation from OM exception S3 Error for conditional request

## Specification
### AWS S3 Conditional Write Specification
#### If-None-Match Header
```
If-None-Match: "*"
```
- Succeeds only if object does NOT exist
- Returns `412 Precondition Failed` if object exists
- Primary use case: Create-only semantics
#### If-Match Header
```
If-Match: "<etag>"
```
- Succeeds only if object EXISTS and ETag matches
- Returns `412 Precondition Failed` if object doesn't exist or ETag mismatches
- Primary use case: Atomic updates (compare-and-swap)

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-13919

How was this patch tested?

Clean CI:
https://github.com/peterxcli/ozone/actions/runs/23634401199/job/68841474397

  • unit tests for affected components
  • rpc client integration test for newly introduced two Bucket API
  • s3 sdk test
  • robot test

…ion handling

- Implemented tests for `createKey` and `rewriteKey` methods to validate behavior when using the `EXPECTED_GEN_CREATE_IF_NOT_EXISTS` constant.
- Added scenarios for key creation when the key is absent and when it already exists.
- Enhanced the `rewriteFailsWhenKeyExists` test to cover cases for both committed and uncommitted keys.
- Updated error handling to ensure correct responses for key existence checks.
…ion handling

- Implemented tests for `createKey` and `rewriteKey` methods to validate behavior when using the `EXPECTED_GEN_CREATE_IF_NOT_EXISTS` constant.
- Added scenarios for key creation when the key is absent and when it already exists.
- Enhanced the `rewriteFailsWhenKeyExists` test to cover cases for both committed and uncommitted keys.
- Updated error handling to ensure correct responses for key existence checks.
@peterxcli peterxcli changed the title Hdds 13919 conditional writes HDDS-13919. S3 Conditional Writes (PutObject) Feb 24, 2026
Copy link
Copy Markdown
Contributor

@jojochuang jojochuang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from a quick glance it looks mostly reasonable.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end support for S3 conditional PUT semantics (If-None-Match: * and If-Match: <etag>) by extending the client RPC API, S3 Gateway PUT handling, and Ozone Manager (create/commit) validation and error mapping.

Changes:

  • Extend Ozone client APIs with createKeyIfNotExists and rewriteKeyIfMatch and wire them through RpcClient, ClientProtocol, and OzoneBucket.
  • Add S3 Gateway conditional header parsing/multiplexing for PUT and translate OM conditional failures to S3 412 PreconditionFailed.
  • Add OM create/commit validation for expectedETag, new OM exception/status codes, and comprehensive unit/integration/robot/S3 SDK tests.

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java Adds unit tests for conditional PUT behavior and ETag parsing.
hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneBucketStub.java Extends test bucket stub with conditional create/rewrite behaviors.
hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java Wires new bucket APIs through the client protocol test stub.
hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java Defines constants for conditional request headers.
hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java Implements conditional PUT header handling and OM→S3 error translation.
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java Adds OM create-phase tests for expected ETag validation.
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCommitRequest.java Adds OM commit-phase tests for expected ETag validation.
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRequest.java Propagates expected ETag from request into key info preparation.
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java Adds create-phase validation for expectedETag against existing key metadata.
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequestWithFSO.java Clears expectedETag before persisting committed keys (FSO path).
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java Clears expectedETag on commit and validates ETag at commit time.
hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto Adds new status codes and expectedETag fields to protocol messages.
hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java Adds integration tests for the new bucket APIs and ETag-based rewrite.
hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v2/AbstractS3SDKV2Tests.java Adds AWS SDK v2 coverage for conditional PUT behaviors.
hadoop-ozone/integration-test-s3/src/test/java/org/apache/hadoop/ozone/s3/awssdk/v1/AbstractS3SDKV1Tests.java Adds AWS SDK v1 coverage for conditional PUT behaviors.
hadoop-ozone/dist/src/main/smoketest/s3/conditionalput.robot Adds robot smoketests validating conditional PUT via awscli.
hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java Propagates expected ETag from client args into OM RPC requests.
hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java Persists/serializes the new expectedETag field on key info.
hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyArgs.java Adds expectedETag to OM key args and protobuf conversion.
hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java Adds new OM exception result codes for ETag mismatch/unavailable.
hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java Implements new conditional APIs using expectedDataGeneration / expectedETag.
hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java Exposes new conditional write methods in the client protocol API.
hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java Adds bucket-level wrappers for the new conditional APIs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

@jojochuang jojochuang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a few code style comments otherwise looks good to me.

Copy link
Copy Markdown
Contributor

@ivandika3 ivandika3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @peterxcli for the patch, left initial comments.

@peterxcli peterxcli marked this pull request as draft March 31, 2026 17:02
@peterxcli peterxcli marked this pull request as ready for review April 1, 2026 01:07
Copy link
Copy Markdown
Contributor

@ivandika3 ivandika3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peterxcli thanks for the update, left additional comments.

@peterxcli peterxcli requested a review from ivandika3 April 1, 2026 08:14
return Response.ok().status(HttpStatus.SC_OK).build();
}

String ifNoneMatch = getHeaders().getHeaderString(
Copy link
Copy Markdown
Member Author

@peterxcli peterxcli Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m still thinking about how to refactor this(line 283-314), as the conditional request validation logic dominates the function.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peterxcli
Copy link
Copy Markdown
Member Author

@ivandika3 please take another look, Thanks!

Copy link
Copy Markdown
Contributor

@ivandika3 ivandika3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peterxcli Thanks for the update. LGTM +1.

@jojochuang jojochuang merged commit e9cceba into apache:master Apr 1, 2026
45 checks passed
@jojochuang
Copy link
Copy Markdown
Contributor

Merged. Thanks @peterxcli and @ivandika3

@peterxcli
Copy link
Copy Markdown
Member Author

Thanks @ivandika3, @jojochuang for reviewing!

@peterxcli peterxcli changed the title HDDS-13919. S3 Conditional Writes (PutObject) HDDS-13919. S3 Conditional Writes (PutObject) [1/2] Apr 1, 2026
@peterxcli peterxcli deleted the HDDS-13919-conditional-writes branch April 1, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants