Skip to content

Commit ed9e237

Browse files
authored
S3 Async Client - Multipart download (#5164)
Multipart Download for S3 Async Client release
1 parent d03c7ac commit ed9e237

File tree

77 files changed

+5171
-709
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+5171
-709
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "S3 Transfer Manager",
4+
"contributor": "",
5+
"description": "This change enables multipart download for S3 Transfer Manager with the java-based Multipart S3 Async Client."
6+
}

core/sdk-core/src/main/java/software/amazon/awssdk/core/FileTransformerConfiguration.java

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.concurrent.ExecutorService;
2424
import software.amazon.awssdk.annotations.SdkPublicApi;
2525
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
26+
import software.amazon.awssdk.utils.ToString;
2627
import software.amazon.awssdk.utils.Validate;
2728
import software.amazon.awssdk.utils.builder.CopyableBuilder;
2829
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
@@ -41,11 +42,19 @@ public final class FileTransformerConfiguration implements ToCopyableBuilder<Fil
4142
private final FileWriteOption fileWriteOption;
4243
private final FailureBehavior failureBehavior;
4344
private final ExecutorService executorService;
45+
private final Long position;
4446

4547
private FileTransformerConfiguration(DefaultBuilder builder) {
4648
this.fileWriteOption = Validate.paramNotNull(builder.fileWriteOption, "fileWriteOption");
4749
this.failureBehavior = Validate.paramNotNull(builder.failureBehavior, "failureBehavior");
4850
this.executorService = builder.executorService;
51+
this.position = Validate.isNotNegativeOrNull(builder.position, "position");
52+
if (fileWriteOption != FileWriteOption.WRITE_TO_POSITION && position != null) {
53+
throw new IllegalArgumentException(String.format(
54+
"'position' can only be used with 'WRITE_TO_POSITION' file write option, but was used with '%s'",
55+
fileWriteOption
56+
));
57+
}
4958
}
5059

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

84+
/**
85+
* Exclusively used with {@link FileWriteOption#WRITE_TO_POSITION}. Configures the position, where to start writing to the
86+
* existing file. The location correspond to the first byte where new data will be written. For example, if {@code 128} is
87+
* configured, bytes 0-127 of the existing file will remain untouched and data will be written starting at byte 128. If not
88+
* specified, defaults to 0.
89+
*
90+
* @return The offset at which to start overwriting data in the file.
91+
*/
92+
public Long position() {
93+
return position;
94+
}
95+
7596
/**
7697
* Create a {@link Builder}, used to create a {@link FileTransformerConfiguration}.
7798
*/
@@ -137,6 +158,9 @@ public boolean equals(Object o) {
137158
if (failureBehavior != that.failureBehavior) {
138159
return false;
139160
}
161+
if (!Objects.equals(position, that.position)) {
162+
return false;
163+
}
140164
return Objects.equals(executorService, that.executorService);
141165
}
142166

@@ -145,6 +169,7 @@ public int hashCode() {
145169
int result = fileWriteOption != null ? fileWriteOption.hashCode() : 0;
146170
result = 31 * result + (failureBehavior != null ? failureBehavior.hashCode() : 0);
147171
result = 31 * result + (executorService != null ? executorService.hashCode() : 0);
172+
result = 31 * result + (position != null ? position.hashCode() : 0);
148173
return result;
149174
}
150175

@@ -165,7 +190,15 @@ public enum FileWriteOption {
165190
/**
166191
* Create a new file if it doesn't exist, otherwise append to the existing file.
167192
*/
168-
CREATE_OR_APPEND_TO_EXISTING
193+
CREATE_OR_APPEND_TO_EXISTING,
194+
195+
/**
196+
* Write to an existing file at the specified position, defined by the {@link FileTransformerConfiguration#position()}. If
197+
* the file does not exist, a {@link java.nio.file.NoSuchFileException} will be thrown. If
198+
* {@link FileTransformerConfiguration#position()} is not configured, start overwriting data at the beginning of the file
199+
* (byte 0).
200+
*/
201+
WRITE_TO_POSITION
169202
}
170203

171204
/**
@@ -209,12 +242,24 @@ public interface Builder extends CopyableBuilder<Builder, FileTransformerConfigu
209242
* @return This object for method chaining.
210243
*/
211244
Builder executorService(ExecutorService executorService);
245+
246+
/**
247+
* Exclusively used with {@link FileWriteOption#WRITE_TO_POSITION}. Configures the position, where to start writing to the
248+
* existing file. The location correspond to the first byte where new data will be written. For example, if {@code 128} is
249+
* configured, bytes 0-127 of the existing file will remain untouched and data will be written starting at byte 128. If
250+
* not specified, defaults to 0.
251+
*
252+
* @param writePosition the position at where to start writing data to the file.
253+
* @return This object for method chaining.
254+
*/
255+
Builder position(Long writePosition);
212256
}
213257

214258
private static final class DefaultBuilder implements Builder {
215259
private FileWriteOption fileWriteOption;
216260
private FailureBehavior failureBehavior;
217261
private ExecutorService executorService;
262+
private Long position;
218263

219264
private DefaultBuilder() {
220265
}
@@ -223,6 +268,7 @@ private DefaultBuilder(FileTransformerConfiguration fileTransformerConfiguration
223268
this.fileWriteOption = fileTransformerConfiguration.fileWriteOption;
224269
this.failureBehavior = fileTransformerConfiguration.failureBehavior;
225270
this.executorService = fileTransformerConfiguration.executorService;
271+
this.position = fileTransformerConfiguration.position;
226272
}
227273

228274
@Override
@@ -243,10 +289,25 @@ public Builder executorService(ExecutorService executorService) {
243289
return this;
244290
}
245291

292+
@Override
293+
public Builder position(Long position) {
294+
this.position = position;
295+
return this;
296+
}
297+
246298
@Override
247299
public FileTransformerConfiguration build() {
248300
return new FileTransformerConfiguration(this);
249301
}
250302
}
251303

252-
}
304+
@Override
305+
public String toString() {
306+
return ToString.builder("FileTransformerConfiguration")
307+
.add("fileWriteOption", this.fileWriteOption)
308+
.add("failureBehavior", this.failureBehavior)
309+
.add("executorService", this.executorService)
310+
.add("position", this.position)
311+
.build();
312+
}
313+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.core;
17+
18+
import java.util.Objects;
19+
import software.amazon.awssdk.annotations.SdkPublicApi;
20+
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
21+
import software.amazon.awssdk.core.internal.async.SplittingTransformer;
22+
import software.amazon.awssdk.utils.ToString;
23+
import software.amazon.awssdk.utils.Validate;
24+
import software.amazon.awssdk.utils.builder.CopyableBuilder;
25+
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
26+
27+
/**
28+
* Configuration options for {@link AsyncResponseTransformer#split(SplittingTransformerConfiguration)} to configure how the SDK
29+
* should split the {@link AsyncResponseTransformer}.
30+
*
31+
* @see #builder()
32+
*/
33+
@SdkPublicApi
34+
public final class SplittingTransformerConfiguration implements ToCopyableBuilder<SplittingTransformerConfiguration.Builder,
35+
SplittingTransformerConfiguration> {
36+
37+
private final Long bufferSizeInBytes;
38+
39+
private SplittingTransformerConfiguration(DefaultBuilder builder) {
40+
this.bufferSizeInBytes = Validate.paramNotNull(builder.bufferSize, "bufferSize");
41+
}
42+
43+
/**
44+
* Create a {@link Builder}, used to create a {@link SplittingTransformerConfiguration}.
45+
*/
46+
public static Builder builder() {
47+
return new DefaultBuilder();
48+
}
49+
50+
/**
51+
* @return the buffer size
52+
*/
53+
public Long bufferSizeInBytes() {
54+
return bufferSizeInBytes;
55+
}
56+
57+
@Override
58+
public boolean equals(Object o) {
59+
if (this == o) {
60+
return true;
61+
}
62+
if (o == null || getClass() != o.getClass()) {
63+
return false;
64+
}
65+
66+
SplittingTransformerConfiguration that = (SplittingTransformerConfiguration) o;
67+
68+
return Objects.equals(bufferSizeInBytes, that.bufferSizeInBytes);
69+
}
70+
71+
@Override
72+
public int hashCode() {
73+
return bufferSizeInBytes != null ? bufferSizeInBytes.hashCode() : 0;
74+
}
75+
76+
@Override
77+
public String toString() {
78+
return ToString.builder("SplittingTransformerConfiguration")
79+
.add("bufferSizeInBytes", bufferSizeInBytes)
80+
.build();
81+
}
82+
83+
@Override
84+
public Builder toBuilder() {
85+
return new DefaultBuilder(this);
86+
}
87+
88+
public interface Builder extends CopyableBuilder<Builder, SplittingTransformerConfiguration> {
89+
90+
/**
91+
* Configures the maximum amount of memory in bytes buffered by the {@link SplittingTransformer}.
92+
*
93+
* @param bufferSize the buffer size in bytes
94+
* @return This object for method chaining.
95+
*/
96+
Builder bufferSizeInBytes(Long bufferSize);
97+
}
98+
99+
private static final class DefaultBuilder implements Builder {
100+
private Long bufferSize;
101+
102+
private DefaultBuilder(SplittingTransformerConfiguration configuration) {
103+
this.bufferSize = configuration.bufferSizeInBytes;
104+
}
105+
106+
private DefaultBuilder() {
107+
}
108+
109+
@Override
110+
public Builder bufferSizeInBytes(Long bufferSize) {
111+
this.bufferSize = bufferSize;
112+
return this;
113+
}
114+
115+
@Override
116+
public SplittingTransformerConfiguration build() {
117+
return new SplittingTransformerConfiguration(this);
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)