This is an automated email from the ASF dual-hosted git repository.
erose pushed a commit to branch ozone-1.2
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/ozone-1.2 by this push:
new 8bd36cd HDDS-5893. Potential data loss on multipart upload commit
(#2763)
8bd36cd is described below
commit 8bd36cd7d06e9a9d34824a4465fe4e31263776d4
Author: UENISHI Kota <[email protected]>
AuthorDate: Wed Oct 27 06:50:08 2021 +0900
HDDS-5893. Potential data loss on multipart upload commit (#2763)
---
.../S3MultipartUploadCompleteResponse.java | 4 +-
...stS3MultipartUploadCompleteResponseWithFSO.java | 73 ++++++++++++++++++----
2 files changed, 63 insertions(+), 14 deletions(-)
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/multipart/S3MultipartUploadCompleteResponse.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/multipart/S3MultipartUploadCompleteResponse.java
index b832813..ec47b30 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/multipart/S3MultipartUploadCompleteResponse.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/s3/multipart/S3MultipartUploadCompleteResponse.java
@@ -97,7 +97,9 @@ public class S3MultipartUploadCompleteResponse extends
OMClientResponse {
if (repeatedOmKeyInfo == null) {
repeatedOmKeyInfo = new RepeatedOmKeyInfo(partsUnusedList);
} else {
- repeatedOmKeyInfo.addOmKeyInfo(omKeyInfo);
+ for (OmKeyInfo unUsedPart : partsUnusedList) {
+ repeatedOmKeyInfo.addOmKeyInfo(unUsedPart);
+ }
}
omMetadataManager.getDeletedTable().putWithBatch(batchOperation,
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/s3/multipart/TestS3MultipartUploadCompleteResponseWithFSO.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/s3/multipart/TestS3MultipartUploadCompleteResponseWithFSO.java
index 5114c73..5fdd575 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/s3/multipart/TestS3MultipartUploadCompleteResponseWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/s3/multipart/TestS3MultipartUploadCompleteResponseWithFSO.java
@@ -132,10 +132,57 @@ public class TestS3MultipartUploadCompleteResponseWithFSO
TestOMRequestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
omMetadataManager);
createParentPath(volumeName, bucketName);
+ runAddDBToBatchWithParts(volumeName, bucketName, keyName, 0);
- String multipartUploadID = UUID.randomUUID().toString();
+ // As 1 unused parts exists, so 1 unused entry should be there in delete
+ // table.
+ Assert.assertEquals(2, omMetadataManager.countRowsInTable(
+ omMetadataManager.getDeletedTable()));
+ }
+
+ @Test
+ public void testAddDBToBatchWithPartsWithKeyInDeleteTable() throws Exception
{
+
+ String volumeName = UUID.randomUUID().toString();
+ String bucketName = UUID.randomUUID().toString();
+ String keyName = getKeyName();
+
+ TestOMRequestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
+ omMetadataManager);
+ createParentPath(volumeName, bucketName);
+
+ // Put an entry to delete table with the same key prior to multipart commit
+ OmKeyInfo prevKey = TestOMRequestUtils.createOmKeyInfo(volumeName,
+ bucketName, keyName,
+ HddsProtos.ReplicationType.RATIS,
+ HddsProtos.ReplicationFactor.ONE,
+ parentID + 8,
+ parentID, 8, Time.now());
+ RepeatedOmKeyInfo prevKeys = new RepeatedOmKeyInfo(prevKey);
+ String ozoneKey = omMetadataManager
+ .getOzoneKey(prevKey.getVolumeName(),
+ prevKey.getBucketName(), prevKey.getFileName());
+ omMetadataManager.getDeletedTable().put(ozoneKey, prevKeys);
+
+ long oId = runAddDBToBatchWithParts(volumeName, bucketName, keyName, 1);
+
+ // Make sure new object isn't in delete table
+ RepeatedOmKeyInfo ds = omMetadataManager.getDeletedTable().get(ozoneKey);
+ for (OmKeyInfo omKeyInfo : ds.getOmKeyInfoList()) {
+ Assert.assertNotEquals(oId, omKeyInfo.getObjectID());
+ }
+
+ // As 1 unused parts and 1 previously put-and-deleted object exist,
+ // so 2 entries should be there in delete table.
+ Assert.assertEquals(2, omMetadataManager.countRowsInTable(
+ omMetadataManager.getDeletedTable()));
+ }
- int deleteEntryCount = 0;
+ private long runAddDBToBatchWithParts(String volumeName,
+ String bucketName, String keyName, int deleteEntryCount)
+ throws Exception {
+
+ String multipartUploadID = UUID.randomUUID().toString();
String fileName = OzoneFSUtils.getFileName(keyName);
String dbMultipartKey = omMetadataManager.getMultipartKey(volumeName,
@@ -153,17 +200,19 @@ public class TestS3MultipartUploadCompleteResponseWithFSO
OmMultipartKeyInfo omMultipartKeyInfo =
s3InitiateMultipartUploadResponseFSO.getOmMultipartKeyInfo();
+ // After commits, it adds an entry to the deleted table. Incrementing the
+ // variable before the method call, because this method also has entry
+ // count check inside.
+ deleteEntryCount++;
OmKeyInfo omKeyInfoFSO = commitS3MultipartUpload(volumeName, bucketName,
keyName, multipartUploadID, fileName, dbMultipartKey,
- omMultipartKeyInfo);
- // After commits, it adds an entry to the deleted table.
- deleteEntryCount++;
+ omMultipartKeyInfo, deleteEntryCount);
OmKeyInfo omKeyInfo =
TestOMRequestUtils.createOmKeyInfo(volumeName, bucketName, keyName,
HddsProtos.ReplicationType.RATIS,
HddsProtos.ReplicationFactor.ONE,
- parentID + 10,
+ parentID + 9,
parentID, 100, Time.now());
List<OmKeyInfo> unUsedParts = new ArrayList<>();
unUsedParts.add(omKeyInfo);
@@ -184,17 +233,15 @@ public class TestS3MultipartUploadCompleteResponseWithFSO
Assert.assertNull(omMetadataManager.getOpenKeyTable(getBucketLayout())
.get(dbMultipartOpenKey));
- // As 1 unused parts exists, so 1 unused entry should be there in delete
- // table.
- deleteEntryCount++;
- Assert.assertEquals(deleteEntryCount, omMetadataManager.countRowsInTable(
- omMetadataManager.getDeletedTable()));
+ return omKeyInfoFSO.getObjectID();
}
+ @SuppressWarnings("parameterNumber")
private OmKeyInfo commitS3MultipartUpload(String volumeName,
String bucketName, String keyName, String multipartUploadID,
String fileName, String multipartKey,
- OmMultipartKeyInfo omMultipartKeyInfo) throws IOException {
+ OmMultipartKeyInfo omMultipartKeyInfo,
+ int deleteEntryCount) throws IOException {
PartKeyInfo part1 = createPartKeyInfoFSO(volumeName, bucketName, parentID,
fileName, 1);
@@ -223,7 +270,7 @@ public class TestS3MultipartUploadCompleteResponseWithFSO
omMetadataManager.getStore().commitBatchOperation(batchOperation);
// As 1 parts are created, so 1 entry should be there in delete table.
- Assert.assertEquals(1, omMetadataManager.countRowsInTable(
+ Assert.assertEquals(deleteEntryCount, omMetadataManager.countRowsInTable(
omMetadataManager.getDeletedTable()));
String part1DeletedKeyName =
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]