49
49
import org .apache .hadoop .fs .s3a .Invoker ;
50
50
import org .apache .hadoop .fs .s3a .Retries ;
51
51
import org .apache .hadoop .fs .s3a .S3AStore ;
52
+ import org .apache .hadoop .fs .s3a .api .IORateLimiting ;
52
53
import org .apache .hadoop .fs .s3a .api .RequestFactory ;
53
54
import org .apache .hadoop .fs .statistics .DurationTrackerFactory ;
54
55
import org .apache .hadoop .fs .store .audit .AuditSpan ;
55
56
import org .apache .hadoop .service .AbstractService ;
56
57
import org .apache .hadoop .util .Preconditions ;
57
58
59
+ import static java .util .Objects .requireNonNull ;
58
60
import static org .apache .hadoop .fs .s3a .Statistic .MULTIPART_UPLOAD_LIST ;
59
61
import static org .apache .hadoop .fs .s3a .Statistic .MULTIPART_UPLOAD_PART_PUT ;
60
62
import static org .apache .hadoop .fs .s3a .Statistic .OBJECT_MULTIPART_UPLOAD_ABORTED ;
63
65
import static org .apache .hadoop .fs .statistics .impl .IOStatisticsBinding .trackDuration ;
64
66
import static org .apache .hadoop .fs .statistics .impl .IOStatisticsBinding .trackDurationOfOperation ;
65
67
import static org .apache .hadoop .fs .statistics .impl .IOStatisticsBinding .trackDurationOfSupplier ;
68
+ import static org .apache .hadoop .util .Preconditions .checkArgument ;
66
69
70
+ /**
71
+ * All Multipart IO Operations.
72
+ * The service is not ready to use until {@link #bind(S3AStore, ClientManager, IORateLimiting)}
73
+ * is invoked and the service started.
74
+ */
67
75
public class MultipartIOService extends AbstractService
68
76
implements MultipartIO {
69
77
70
78
private static final Logger LOG =
71
79
LoggerFactory .getLogger (MultipartIOService .class );
72
80
81
+ /**
82
+ * Store for some statistics invocations.
83
+ */
73
84
private S3AStore store ;
74
85
86
+ /**
87
+ * Rate limiter (likely to be the store)
88
+ */
89
+ private IORateLimiting limiting ;
90
+
91
+ /**
92
+ * SDK client.
93
+ */
75
94
private ClientManager clientManager ;
76
95
96
+ /**
97
+ * Create the Service with the service name {@link #MULTIPART_IO}.
98
+ */
77
99
public MultipartIOService () {
78
- super (MULTIPART_IO );
100
+ this (MULTIPART_IO );
79
101
}
80
102
103
+ /**
104
+ * Constructor.
105
+ * @param name service name
106
+ */
107
+ public MultipartIOService (final String name ) {
108
+ super (name );
109
+ }
81
110
82
- public void bind (final S3AStore store , ClientManager clientManager ) {
83
- this .store = store ;
111
+ /**
112
+ * Bind to dependencies.
113
+ * This MUST be called before service start
114
+ * @param store store
115
+ * @param clientManager sdk client manager
116
+ * @param limiting rate limiting.
117
+ */
118
+ public void bind (final S3AStore store ,
119
+ ClientManager clientManager ,
120
+ IORateLimiting limiting ) {
121
+ this .store = requireNonNull (store );
84
122
this .clientManager = clientManager ;
123
+ this .limiting = store ;
124
+ }
125
+
126
+
127
+ @ Override
128
+ protected void serviceStart () throws Exception {
129
+ super .serviceStart ();
130
+ requireNonNull (store );
85
131
}
86
132
87
133
/**
@@ -104,7 +150,6 @@ public CreateMultipartUploadResponse initiateMultipartUpload(
104
150
() -> getS3ClientUnchecked ().createMultipartUpload (request ));
105
151
}
106
152
107
-
108
153
@ Retries .OnceRaw
109
154
@ Override
110
155
public UploadPartResponse uploadPart (
@@ -158,26 +203,24 @@ public AbortMultipartUploadResponse abortMultipartUpload(String destKey, String
158
203
checkRunning ();
159
204
LOG .debug ("Aborting multipart upload {} to {}" , uploadId , destKey );
160
205
return trackDurationOfSupplier (store .getInstrumentation (), OBJECT_MULTIPART_UPLOAD_ABORTED .getSymbol (), () -> {
161
- store .acquireWriteCapacity (InternalConstants .MULTIPART_ABORT_WRITE_CAPACITY );
206
+ limiting .acquireWriteCapacity (InternalConstants .MULTIPART_ABORT_WRITE_CAPACITY );
162
207
return getS3ClientUnchecked ().abortMultipartUpload (
163
208
store .getRequestFactory ().newAbortMultipartUploadRequestBuilder (
164
209
destKey ,
165
210
uploadId ).build ());
166
211
});
167
212
}
168
213
169
-
170
214
@ Retries .RetryTranslated
171
215
@ Override
172
- public void abortOutstandingMultipartUploads (long seconds , @ Nullable String prefix , int maxKeys )
216
+ public void abortOutstandingMultipartUploads (long seconds , @ Nullable String prefix , int maxKeys ,
217
+ StoreContext context )
173
218
throws IOException {
174
- Preconditions . checkArgument (seconds >= 0 );
219
+ checkArgument (seconds >= 0 );
175
220
checkRunning ();
176
- Instant purgeBefore =
177
- Instant .now ().minusSeconds (seconds );
221
+ Instant purgeBefore = Instant .now ().minusSeconds (seconds );
178
222
LOG .debug ("Purging outstanding multipart uploads older than {}" ,
179
223
purgeBefore );
180
- final StoreContext context = store .createStoreContext ();
181
224
context .getInvoker ().retry ("Purging multipart uploads" ,
182
225
context .getBucket (), true ,
183
226
() -> {
@@ -208,7 +251,7 @@ public List<MultipartUpload> listMultipartUploads(@Nullable String prefix)
208
251
final ListMultipartUploadsRequest request = store .getRequestFactory ()
209
252
.newListMultipartUploadsRequestBuilder (p ).build ();
210
253
return trackDuration (store .getInstrumentation (), MULTIPART_UPLOAD_LIST .getSymbol (), () -> {
211
- store .acquireReadCapacity (InternalConstants .MULTIPART_LIST_READ_CAPACITY );
254
+ limiting .acquireReadCapacity (InternalConstants .MULTIPART_LIST_READ_CAPACITY );
212
255
return getS3ClientUnchecked ().listMultipartUploads (request ).uploads ();
213
256
});
214
257
});
@@ -258,7 +301,6 @@ public class ListingIterator implements
258
301
259
302
private final int maxKeys ;
260
303
261
-
262
304
private final Invoker invoker ;
263
305
264
306
private final AuditSpan auditSpan ;
@@ -345,8 +387,8 @@ private void requestNextBatch() throws IOException {
345
387
checkRunning ();
346
388
347
389
try (AuditSpan span = auditSpan .activate ()) {
348
- ListMultipartUploadsRequest .Builder requestBuilder = requestFactory
349
- .newListMultipartUploadsRequestBuilder (prefix );
390
+ ListMultipartUploadsRequest .Builder requestBuilder =
391
+ requestFactory .newListMultipartUploadsRequestBuilder (prefix );
350
392
if (!firstListing ) {
351
393
requestBuilder .keyMarker (listing .nextKeyMarker ());
352
394
requestBuilder .uploadIdMarker (listing .nextUploadIdMarker ());
@@ -364,7 +406,7 @@ private void requestNextBatch() throws IOException {
364
406
trackDurationOfOperation (storeContext .getInstrumentation (),
365
407
OBJECT_MULTIPART_UPLOAD_LIST .getSymbol (),
366
408
() -> {
367
- store .acquireReadCapacity (InternalConstants .MULTIPART_LIST_READ_CAPACITY );
409
+ limiting .acquireReadCapacity (InternalConstants .MULTIPART_LIST_READ_CAPACITY );
368
410
return getS3ClientUnchecked ().listMultipartUploads (requestBuilder .build ());
369
411
}));
370
412
LOG .debug ("Listing found {} upload(s)" ,
@@ -375,7 +417,7 @@ private void requestNextBatch() throws IOException {
375
417
}
376
418
377
419
private S3Client getS3ClientUnchecked () {
378
- return store .getOrCreateS3ClientUnchecked ();
420
+ return clientManager .getOrCreateS3ClientUnchecked ();
379
421
}
380
422
381
423
/**
0 commit comments