Skip to content

S3 Async Client - Multipart download #5164

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

Merged
merged 50 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
7100df4
Merge from master (#4901)
L-Applin Feb 8, 2024
8c18e39
Splitting transformer (#4826)
L-Applin Feb 12, 2024
b247de9
Enable setting multipart to true/false by defining it as a custom cli…
anirudh9391 Feb 12, 2024
511205c
Add config class for SplittingTransformer (#4939)
davidh44 Feb 17, 2024
730750e
Merge mainline into multipart feature branch (#4965)
L-Applin Feb 26, 2024
a98af91
Surface area review (#4971)
L-Applin Feb 29, 2024
dd3eb20
MultipartS3AsyncClient download benchmarks (#4948)
davidh44 Mar 1, 2024
336fd35
Implementation of MultipartDownloaderSubscriber (#4931)
L-Applin Mar 7, 2024
7d82774
Update s3-benchmarks to support java-based multipart download. (#5003)
L-Applin Mar 11, 2024
9f4563b
Use Content-Range in multipart download for totalBytes (#5101)
L-Applin Apr 12, 2024
330ab9f
change NoopTransformer type-param to Object, preventing an NPE which …
L-Applin Apr 17, 2024
e041ca2
Fix for threads hanging with forwardTransformedResultTo (#5117)
L-Applin Apr 22, 2024
4187e62
Merge branch 'master' into feature/master/s3mpu
L-Applin Apr 25, 2024
d5dff64
Merge branch 'master' into feature/master/s3mpu
L-Applin Apr 29, 2024
97f0a5f
[draft] java-based integ test (#5129)
L-Applin May 1, 2024
768526e
Fix merge issue and bump peak thread count in stability tests (#5174)
zoewangg May 2, 2024
405cc74
Fix stability tests (#5178)
zoewangg May 3, 2024
1660397
Fix for multipart integ test failure (#5176)
L-Applin May 21, 2024
85a8f89
FileAsyncResponseTransformer - write to position (#5241)
L-Applin May 23, 2024
ee6ebff
add completed to ResumableFileDownload ser/des (#5254)
L-Applin May 30, 2024
0ecd657
Pause and resume for multipart download (#5258)
L-Applin Jun 6, 2024
d35cb3b
add completed to ResumableFileDownload ser/des
L-Applin May 29, 2024
5914453
review comments
L-Applin Jun 7, 2024
09b31b6
Merge branch 'master' into feature/master/s3mpu
L-Applin Jun 7, 2024
6c62bdd
Merge branch 'master' into feature/master/s3mpu
L-Applin Jun 10, 2024
417fe5b
fix ambiguous call to split in test
L-Applin Jun 10, 2024
0042b1d
fix WRITE_TO_POSITION file exist test
L-Applin Jun 10, 2024
abb4611
fix logging test
L-Applin Jun 10, 2024
3cde4d2
Merge branch 'master' into feature/master/s3mpu
L-Applin Jun 10, 2024
5755b43
fix java 21 javadoc error
L-Applin Jun 10, 2024
fc9b2e4
fix java 21 javadoc error
L-Applin Jun 11, 2024
e4ab19b
fix some Sonar issues
L-Applin Jun 11, 2024
404b763
Javadoc update for mulitpart get
L-Applin Jun 11, 2024
6a1f135
changelog entry
L-Applin Jun 12, 2024
d3a004a
changelog
L-Applin Jun 12, 2024
5819ab2
Added debug log around entire request and prevent random log leaking …
L-Applin Jun 13, 2024
735fa96
pr comments
L-Applin Jun 13, 2024
9e58e88
Merge branch 'master' into feature/master/s3mpu
L-Applin Jul 8, 2024
b10c73e
PR 5164 remaining comments (#5403)
L-Applin Jul 18, 2024
e7292e2
Merge branch 'master' into feature/master/s3mpu
L-Applin Jul 18, 2024
a52e476
Merge branch 'master' into feature/master/s3mpu
L-Applin Jul 18, 2024
5047516
Add trace logs for debugging multipart download (#5434)
L-Applin Jul 30, 2024
d2c1b92
Prevent multipart download from hanging (#5466)
L-Applin Aug 8, 2024
eb56b55
Merge branch 'master' into feature/master/s3mpu
L-Applin Aug 8, 2024
49f2af9
Merge branch 'master' into feature/master/s3mpu
L-Applin Aug 12, 2024
b202a3a
Merge branch 'master' into feature/master/s3mpu
L-Applin Aug 12, 2024
599b56c
Merge branch 'master' into feature/master/s3mpu
L-Applin Aug 13, 2024
99bea7f
Merge branch 'master' into feature/master/s3mpu
L-Applin Aug 13, 2024
3434f68
Merge branch 'master' into feature/master/s3mpu
L-Applin Aug 13, 2024
0573731
remove trace logs
L-Applin Aug 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "feature",
"category": "S3 Transfer Manager",
"contributor": "",
"description": "This change enables multipart download for S3 Transfer Manager with the java-based Multipart S3 Async Client."
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.concurrent.ExecutorService;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
Expand All @@ -41,11 +42,19 @@ public final class FileTransformerConfiguration implements ToCopyableBuilder<Fil
private final FileWriteOption fileWriteOption;
private final FailureBehavior failureBehavior;
private final ExecutorService executorService;
private final Long position;

private FileTransformerConfiguration(DefaultBuilder builder) {
this.fileWriteOption = Validate.paramNotNull(builder.fileWriteOption, "fileWriteOption");
this.failureBehavior = Validate.paramNotNull(builder.failureBehavior, "failureBehavior");
this.executorService = builder.executorService;
this.position = Validate.isNotNegativeOrNull(builder.position, "position");
if (fileWriteOption != FileWriteOption.WRITE_TO_POSITION && position != null) {
throw new IllegalArgumentException(String.format(
"'position' can only be used with 'WRITE_TO_POSITION' file write option, but was used with '%s'",
fileWriteOption
));
}
}

/**
Expand All @@ -72,6 +81,18 @@ public Optional<ExecutorService> executorService() {
return Optional.ofNullable(executorService);
}

/**
* Exclusively used with {@link FileWriteOption#WRITE_TO_POSITION}. Configures the position, where to start writing to the
* existing file. The location correspond to the first byte where new data will be written. For example, if {@code 128} is
* configured, bytes 0-127 of the existing file will remain untouched and data will be written starting at byte 128. If not
* specified, defaults to 0.
*
* @return The offset at which to start overwriting data in the file.
*/
public Long position() {
return position;
}

/**
* Create a {@link Builder}, used to create a {@link FileTransformerConfiguration}.
*/
Expand Down Expand Up @@ -137,6 +158,9 @@ public boolean equals(Object o) {
if (failureBehavior != that.failureBehavior) {
return false;
}
if (!Objects.equals(position, that.position)) {
return false;
}
return Objects.equals(executorService, that.executorService);
}

Expand All @@ -145,6 +169,7 @@ public int hashCode() {
int result = fileWriteOption != null ? fileWriteOption.hashCode() : 0;
result = 31 * result + (failureBehavior != null ? failureBehavior.hashCode() : 0);
result = 31 * result + (executorService != null ? executorService.hashCode() : 0);
result = 31 * result + (position != null ? position.hashCode() : 0);
return result;
}

Expand All @@ -165,7 +190,15 @@ public enum FileWriteOption {
/**
* Create a new file if it doesn't exist, otherwise append to the existing file.
*/
CREATE_OR_APPEND_TO_EXISTING
CREATE_OR_APPEND_TO_EXISTING,

/**
* Write to an existing file at the specified position, defined by the {@link FileTransformerConfiguration#position()}. If
* the file does not exist, a {@link java.nio.file.NoSuchFileException} will be thrown. If
* {@link FileTransformerConfiguration#position()} is not configured, start overwriting data at the beginning of the file
* (byte 0).
*/
WRITE_TO_POSITION
}

/**
Expand Down Expand Up @@ -209,12 +242,24 @@ public interface Builder extends CopyableBuilder<Builder, FileTransformerConfigu
* @return This object for method chaining.
*/
Builder executorService(ExecutorService executorService);

/**
* Exclusively used with {@link FileWriteOption#WRITE_TO_POSITION}. Configures the position, where to start writing to the
* existing file. The location correspond to the first byte where new data will be written. For example, if {@code 128} is
* configured, bytes 0-127 of the existing file will remain untouched and data will be written starting at byte 128. If
* not specified, defaults to 0.
*
* @param writePosition the position at where to start writing data to the file.
* @return This object for method chaining.
*/
Builder position(Long writePosition);
}

private static final class DefaultBuilder implements Builder {
private FileWriteOption fileWriteOption;
private FailureBehavior failureBehavior;
private ExecutorService executorService;
private Long position;

private DefaultBuilder() {
}
Expand All @@ -223,6 +268,7 @@ private DefaultBuilder(FileTransformerConfiguration fileTransformerConfiguration
this.fileWriteOption = fileTransformerConfiguration.fileWriteOption;
this.failureBehavior = fileTransformerConfiguration.failureBehavior;
this.executorService = fileTransformerConfiguration.executorService;
this.position = fileTransformerConfiguration.position;
}

@Override
Expand All @@ -243,10 +289,25 @@ public Builder executorService(ExecutorService executorService) {
return this;
}

@Override
public Builder position(Long position) {
this.position = position;
return this;
}

@Override
public FileTransformerConfiguration build() {
return new FileTransformerConfiguration(this);
}
}

}
@Override
public String toString() {
return ToString.builder("FileTransformerConfiguration")
.add("fileWriteOption", this.fileWriteOption)
.add("failureBehavior", this.failureBehavior)
.add("executorService", this.executorService)
.add("position", this.position)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.awssdk.core;

import java.util.Objects;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.core.internal.async.SplittingTransformer;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;

/**
* Configuration options for {@link AsyncResponseTransformer#split(SplittingTransformerConfiguration)} to configure how the SDK
* should split the {@link AsyncResponseTransformer}.
*
* @see #builder()
*/
@SdkPublicApi
public final class SplittingTransformerConfiguration implements ToCopyableBuilder<SplittingTransformerConfiguration.Builder,
SplittingTransformerConfiguration> {

private final Long bufferSizeInBytes;

private SplittingTransformerConfiguration(DefaultBuilder builder) {
this.bufferSizeInBytes = Validate.paramNotNull(builder.bufferSize, "bufferSize");
}

/**
* Create a {@link Builder}, used to create a {@link SplittingTransformerConfiguration}.
*/
public static Builder builder() {
return new DefaultBuilder();
}

/**
* @return the buffer size
*/
public Long bufferSizeInBytes() {
return bufferSizeInBytes;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

SplittingTransformerConfiguration that = (SplittingTransformerConfiguration) o;

return Objects.equals(bufferSizeInBytes, that.bufferSizeInBytes);
}

@Override
public int hashCode() {
return bufferSizeInBytes != null ? bufferSizeInBytes.hashCode() : 0;
}

@Override
public String toString() {
return ToString.builder("SplittingTransformerConfiguration")
.add("bufferSizeInBytes", bufferSizeInBytes)
.build();
}

@Override
public Builder toBuilder() {
return new DefaultBuilder(this);
}

public interface Builder extends CopyableBuilder<Builder, SplittingTransformerConfiguration> {

/**
* Configures the maximum amount of memory in bytes buffered by the {@link SplittingTransformer}.
*
* @param bufferSize the buffer size in bytes
* @return This object for method chaining.
*/
Builder bufferSizeInBytes(Long bufferSize);
}

private static final class DefaultBuilder implements Builder {
private Long bufferSize;

private DefaultBuilder(SplittingTransformerConfiguration configuration) {
this.bufferSize = configuration.bufferSizeInBytes;
}

private DefaultBuilder() {
}

@Override
public Builder bufferSizeInBytes(Long bufferSize) {
this.bufferSize = bufferSize;
return this;
}

@Override
public SplittingTransformerConfiguration build() {
return new SplittingTransformerConfiguration(this);
}
}
}
Loading
Loading