-
Notifications
You must be signed in to change notification settings - Fork 588
HDDS-9526. Two S3G instances writing the same key may cause data loss in case of an exception. #5524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… in case of an exception.
# Conflicts: # hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/BlockDataStreamOutputEntryPool.java # hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/BlockOutputStreamEntryPool.java # hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java # hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
|
|
||
| copyHeader = headers.getHeaderString(COPY_SOURCE_HEADER); | ||
| if (copyHeader != null) { | ||
| String range = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we add this COPY_SOURCE_HEADER_RANGE check in the put() L253 too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ozone does not currently support copy ranges for non-MPU keys so Ozone will copy the entire key regardless of the value of COPY_SOURCE_HEADER_RANGE.
Maybe we can add this when we need to support copy ranges.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked the CopyObject document, it looks like range copy is not supported.
https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html
| * A mismatch will prevent the commit from succeeding. | ||
| * This is essential for operations like S3 put to ensure atomicity. | ||
| */ | ||
| private boolean requiresAtomicWrite; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest change the requiresAtomicWrite to atomicKeyCreation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| } | ||
| if (requiresAtomicWrite) { | ||
| long expectedSize = blockOutputStreamEntryPool.getDataSize(); | ||
| Preconditions.checkArgument(expectedSize == offset, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest to use Preconditions.checkState here, so it will throw out IllegalStateException instead of
IllegalArgumentException. IllegalStateException is more appropriate than IllegalArgumentException here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And please catch this exception in ObjectEndpoint#put finally when OutputStream#close is called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| objectEndpoint.setHeaders(headers); | ||
| objectEndpoint.setClient(client); | ||
| objectEndpoint.setOzoneConfiguration(new OzoneConfiguration()); | ||
| objectEndpoint.setHeaders(headers); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is duplicate with L150.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| objectEndpoint.setHeaders(headers); | ||
| String keyName = UUID.randomUUID().toString(); | ||
|
|
||
| String chunkedContent = "0a;chunk-signature=signature\r\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xichen01 , could you explain a little bit about this chunkedContent? Don't understand why this string length is 15.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The length of "1234567890" + "abcde" is 15, 05;chunk-signature=signature is some metadata.
I referenced it here:
ozone/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
Lines 168 to 169 in 45aa6c1
| Assert.assertEquals(200, response.getStatus()); | |
| Assert.assertEquals("1234567890abcde", keyContent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay.
|
@xichen01 , thanks for provide the fix so quickly. Is it possible to do more manual tests, such as multi upload, and range multi upload case? |
OK, I will do more test for this Patch |
|
There are few test failures in your fork, can you please take a look https://github.com/xichen01/ozone/actions/runs/6717923197/job/18257546921 |
|
@SaketaChalamchala @tanvipenumudy can you please take a look? |
| try { | ||
| output.close(); | ||
| } catch (IllegalStateException ex) { | ||
| LOG.error(String.format( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can occur due to client behavior and we should not be logging at level error a client with a bad connection could fill up the S3G logs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The metric at line 320 should be moved below into the finally block.
hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/KeyOutputStream.java
Show resolved
Hide resolved
hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
Outdated
Show resolved
Hide resolved
hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
Outdated
Show resolved
Hide resolved
|
Can you look into the test failure in your branch https://github.com/xichen01/ozone/actions/runs/6773687585/job/18410561865 |
The failed test are: Prepare Ozone Manager | FAIL |
Test timeout 5 minutes exceeded.
--
Prepare :: Prepares OMs | FAIL |
1 test, 0 passed, 1 failedThis may have been an unstable test, I didn't change the OM code, when I reran the test, the test succeeded. |
|
Thanks @xichen01 working on this, Elegant code and detailed testing, LGTM. |
|
@ChenSammi @kerneltime @SaketaChalamchala please take a look at the latest patch |
ChenSammi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last patch looks good to me, +1
@kerneltime , @SaketaChalamchala , could you like to take another look?
|
Thanks @xichen01 for this contribution, @kerneltime @adoroszlai @SaketaChalamchala for the code review. |
… in case of an exception. (apache#5524)
…se data loss in case of an exception. (apache#5524) (cherry picked from commit e14fb8e) Change-Id: Iaa64909d76ec3bd129797ff54f46f19430e8dba8
What changes were proposed in this pull request?
To fix the problem of abnormal dirty data overwriting normal data when S3G writes data. Make Ozone S3 puts atomic writes, all successes total or failures
The main implementation is to check whether the data of the key is complete or not when committing, if the data written by the key is different from the expected size, the key is considered incomplete, and the commit operation is not executed.
requiresAtomicWriteis onlyenablein S3G, it will be set inEndpointBase#initialization, just like thes3AuthblockOutputStreamEntryPool.getDataSize()is thedataSizethat was passed in when the S3G created the key (including the MPU key).Content-Length: normal put keyx-amz-decoded-content-length: Stream mode uploaded key.x-amz-copy-source-range: The length specified in the MPU copyRange(Ozone does not currently support Copy Ranges for non-MPU keys.).RangePS:
refer to AWS put doc https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-9526
How was this patch tested?
unit test, manually test.
manually test.