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.services.s3.multipart; 17 18 import java.util.function.Consumer; 19 import software.amazon.awssdk.annotations.SdkPublicApi; 20 import software.amazon.awssdk.core.async.AsyncRequestBody; 21 import software.amazon.awssdk.core.async.AsyncResponseTransformer; 22 import software.amazon.awssdk.services.s3.S3AsyncClient; 23 import software.amazon.awssdk.services.s3.S3AsyncClientBuilder; 24 import software.amazon.awssdk.services.s3.model.CopyObjectRequest; 25 import software.amazon.awssdk.services.s3.model.GetObjectRequest; 26 import software.amazon.awssdk.utils.builder.CopyableBuilder; 27 import software.amazon.awssdk.utils.builder.ToCopyableBuilder; 28 29 /** 30 * Class that hold configuration properties related to multipart operation for a {@link S3AsyncClient}. Passing this class to the 31 * {@link S3AsyncClientBuilder#multipartConfiguration(MultipartConfiguration)} will enable automatic conversion of 32 * {@link S3AsyncClient#putObject(Consumer, AsyncRequestBody)}, {@link S3AsyncClient#copyObject(CopyObjectRequest)} to their 33 * respective multipart operation. 34 * <p> 35 * <em>Note</em>: The multipart operation for {@link S3AsyncClient#getObject(GetObjectRequest, AsyncResponseTransformer)} is 36 * temporarily disabled and will result in throwing a {@link UnsupportedOperationException} if called when configured for 37 * multipart operation. 38 */ 39 @SdkPublicApi 40 public final class MultipartConfiguration implements ToCopyableBuilder<MultipartConfiguration.Builder, MultipartConfiguration> { 41 42 private final Long thresholdInBytes; 43 private final Long minimumPartSizeInBytes; 44 private final Long apiCallBufferSizeInBytes; 45 MultipartConfiguration(DefaultMultipartConfigBuilder builder)46 private MultipartConfiguration(DefaultMultipartConfigBuilder builder) { 47 this.thresholdInBytes = builder.thresholdInBytes; 48 this.minimumPartSizeInBytes = builder.minimumPartSizeInBytes; 49 this.apiCallBufferSizeInBytes = builder.apiCallBufferSizeInBytes; 50 } 51 builder()52 public static Builder builder() { 53 return new DefaultMultipartConfigBuilder(); 54 } 55 56 @Override toBuilder()57 public Builder toBuilder() { 58 return builder() 59 .apiCallBufferSizeInBytes(apiCallBufferSizeInBytes) 60 .minimumPartSizeInBytes(minimumPartSizeInBytes) 61 .thresholdInBytes(thresholdInBytes); 62 } 63 64 /** 65 * Indicates the value of the configured threshold, in bytes. Any request whose size is less than the configured value will 66 * not use multipart operation 67 * @return the value of the configured threshold. 68 */ thresholdInBytes()69 public Long thresholdInBytes() { 70 return this.thresholdInBytes; 71 } 72 73 /** 74 * Indicated the size, in bytes, of each individual part of the part requests. The actual part size used might be bigger to 75 * conforms to the maximum number of parts allowed per multipart requests. 76 * @return the value of the configured part size. 77 */ minimumPartSizeInBytes()78 public Long minimumPartSizeInBytes() { 79 return this.minimumPartSizeInBytes; 80 } 81 82 /** 83 * The maximum memory, in bytes, that the SDK will use to buffer requests content into memory. 84 * @return the value of the configured maximum memory usage. 85 */ apiCallBufferSizeInBytes()86 public Long apiCallBufferSizeInBytes() { 87 return this.apiCallBufferSizeInBytes; 88 } 89 90 /** 91 * Builder for a {@link MultipartConfiguration}. 92 */ 93 public interface Builder extends CopyableBuilder<Builder, MultipartConfiguration> { 94 95 /** 96 * Configure the size threshold, in bytes, for when to use multipart upload. Uploads/copies over this size will 97 * automatically use a multipart upload strategy, while uploads/copies smaller than this threshold will use a single 98 * connection to upload/copy the whole object. 99 * 100 * <p> 101 * Multipart uploads are easier to recover from and also potentially faster than single part uploads, especially when the 102 * upload parts can be uploaded in parallel. Because there are additional network API calls, small objects are still 103 * recommended to use a single connection for the upload. See 104 * <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html">Uploading and copying objects using 105 * multipart upload</a>. 106 * 107 * <p> 108 * By default, it is the same as {@link #minimumPartSizeInBytes(Long)}. 109 * 110 * @param thresholdInBytes the value of the threshold to set. 111 * @return an instance of this builder. 112 */ thresholdInBytes(Long thresholdInBytes)113 Builder thresholdInBytes(Long thresholdInBytes); 114 115 /** 116 * Indicates the value of the configured threshold. 117 * @return the value of the threshold. 118 */ thresholdInBytes()119 Long thresholdInBytes(); 120 121 /** 122 * Configures the part size, in bytes, to be used in each individual part requests. 123 * Only used for putObject and copyObject operations. 124 * <p> 125 * When uploading large payload, the size of the payload of each individual part requests might actually be 126 * bigger than 127 * the configured value since there is a limit to the maximum number of parts possible per multipart request. If the 128 * configured part size would lead to a number of parts higher than the maximum allowed, a larger part size will be 129 * calculated instead to allow fewer part to be uploaded, to avoid the limit imposed on the maximum number of parts. 130 * <p> 131 * In the case where the {@code minimumPartSizeInBytes} is set to a value higher than the {@code thresholdInBytes}, when 132 * the client receive a request with a size smaller than a single part multipart operation will <em>NOT</em> be performed 133 * even if the size of the request is larger than the threshold. 134 * <p> 135 * Default value: 8 Mib 136 * 137 * @param minimumPartSizeInBytes the value of the part size to set 138 * @return an instance of this builder. 139 */ minimumPartSizeInBytes(Long minimumPartSizeInBytes)140 Builder minimumPartSizeInBytes(Long minimumPartSizeInBytes); 141 142 /** 143 * Indicated the value of the part configured size. 144 * @return the value of the part size 145 */ minimumPartSizeInBytes()146 Long minimumPartSizeInBytes(); 147 148 /** 149 * Configures the maximum amount of memory, in bytes, the SDK will use to buffer content of requests in memory. 150 * Increasing this value may lead to better performance at the cost of using more memory. 151 * <p> 152 * Default value: If not specified, the SDK will use the equivalent of four parts worth of memory, so 32 Mib by default. 153 * 154 * @param apiCallBufferSizeInBytes the value of the maximum memory usage. 155 * @return an instance of this builder. 156 */ apiCallBufferSizeInBytes(Long apiCallBufferSizeInBytes)157 Builder apiCallBufferSizeInBytes(Long apiCallBufferSizeInBytes); 158 159 /** 160 * Indicates the value of the maximum memory usage that the SDK will use. 161 * @return the value of the maximum memory usage. 162 */ apiCallBufferSizeInBytes()163 Long apiCallBufferSizeInBytes(); 164 } 165 166 private static class DefaultMultipartConfigBuilder implements Builder { 167 private Long thresholdInBytes; 168 private Long minimumPartSizeInBytes; 169 private Long apiCallBufferSizeInBytes; 170 thresholdInBytes(Long thresholdInBytes)171 public Builder thresholdInBytes(Long thresholdInBytes) { 172 this.thresholdInBytes = thresholdInBytes; 173 return this; 174 } 175 thresholdInBytes()176 public Long thresholdInBytes() { 177 return this.thresholdInBytes; 178 } 179 minimumPartSizeInBytes(Long minimumPartSizeInBytes)180 public Builder minimumPartSizeInBytes(Long minimumPartSizeInBytes) { 181 this.minimumPartSizeInBytes = minimumPartSizeInBytes; 182 return this; 183 } 184 minimumPartSizeInBytes()185 public Long minimumPartSizeInBytes() { 186 return this.minimumPartSizeInBytes; 187 } 188 189 @Override apiCallBufferSizeInBytes(Long maximumMemoryUsageInBytes)190 public Builder apiCallBufferSizeInBytes(Long maximumMemoryUsageInBytes) { 191 this.apiCallBufferSizeInBytes = maximumMemoryUsageInBytes; 192 return this; 193 } 194 195 @Override apiCallBufferSizeInBytes()196 public Long apiCallBufferSizeInBytes() { 197 return apiCallBufferSizeInBytes; 198 } 199 200 @Override build()201 public MultipartConfiguration build() { 202 return new MultipartConfiguration(this); 203 } 204 } 205 } 206