Skip to content

Commit 5aed13e

Browse files
authored
Fix bug about wrong part size number in CopyObjectHelper (#4049)
Fix bug about wrong part sze number in CopyObjectHelper
1 parent 16cd5c3 commit 5aed13e

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Fix an issue where the optimal number of parts calculated could be higher than 10,000"
6+
}

services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CopyObjectHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ private void doCopyInParts(CopyObjectRequest copyObjectRequest,
130130
Long contentLength,
131131
CompletableFuture<CopyObjectResponse> returnFuture,
132132
String uploadId) {
133-
long optimalPartSize = calculateOptimalPartSizeForCopy(partSizeInBytes);
133+
long optimalPartSize = calculateOptimalPartSizeForCopy(contentLength);
134134

135135
int partCount = determinePartCount(contentLength, optimalPartSize);
136136

services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/CopyObjectHelperTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,41 @@ void multiPartCopy_completeMultipartFailed_shouldFailAndAbort() {
221221
assertThat(actualRequest.uploadId()).isEqualTo(MULTIPART_ID);
222222
}
223223

224+
@Test
225+
void multiPartCopy_contentSizeExceeds10000Parts_shouldAdjustPartSize() {
226+
long contentLength = 1024L * 10_000 * 2; // twice too many parts with configures part size
227+
228+
stubSuccessfulHeadObjectCall(contentLength);
229+
stubSuccessfulCreateMulipartCall();
230+
stubSuccessfulUploadPartCopyCalls();
231+
stubSuccessfulCompleteMultipartCall();
232+
233+
CopyObjectRequest copyObjectRequest = copyObjectRequest();
234+
235+
CompletableFuture<CopyObjectResponse> future = copyHelper.copyObject(copyObjectRequest);
236+
237+
CopyObjectResponse actualResponse = future.join();
238+
assertThat(actualResponse.copyObjectResult()).isNotNull();
239+
240+
ArgumentCaptor<UploadPartCopyRequest> argumentCaptor = ArgumentCaptor.forClass(UploadPartCopyRequest.class);
241+
verify(s3AsyncClient, times(10_000)).uploadPartCopy(argumentCaptor.capture());
242+
List<UploadPartCopyRequest> actualUploadPartCopyRequests = argumentCaptor.getAllValues();
243+
assertThat(actualUploadPartCopyRequests).allSatisfy(d -> {
244+
assertThat(d.sourceBucket()).isEqualTo(SOURCE_BUCKET);
245+
assertThat(d.sourceKey()).isEqualTo(SOURCE_KEY);
246+
assertThat(d.destinationBucket()).isEqualTo(DESTINATION_BUCKET);
247+
assertThat(d.destinationKey()).isEqualTo(DESTINATION_KEY);
248+
});
249+
250+
long expectedPartSize = 2048L;
251+
for (int i = 0; i < actualUploadPartCopyRequests.size(); i++) {
252+
int rangeStart = (int) expectedPartSize * i;
253+
int rangeEnd = (int) (rangeStart + (expectedPartSize - 1));
254+
assertThat(actualUploadPartCopyRequests.get(i).copySourceRange()).isEqualTo(
255+
String.format("bytes=%d-%d", rangeStart, rangeEnd));
256+
}
257+
}
258+
224259
@Test
225260
void copy_cancelResponseFuture_shouldPropagate() {
226261
CopyObjectRequest copyObjectRequest = copyObjectRequest();

0 commit comments

Comments
 (0)