Skip to content

Commit f732c85

Browse files
authored
Refactoring meta request types (#79)
* aws_s3_request is now in its own header/source file. * All meta request types now get their own private header file to make writing tests for those easier. * Meta request types no longer use state machines for tracking what request is to be sent next. Instead, a series of conditions is evaluated each time next_request is called. * The final meta request result is now set with a success or fail function. Once all work that the meta request currently has in progress completes, then the meta request internally calls aws_s3_meta_request_finish, which invokes the finish callback. * Performance Behavior Improvement: added a mitigation for global request limit being hit. Client will first ask for new requests from meta requests with a "conservative" flag, which will cause auto-ranged-gets to limit the amount of requests returned, preventing parts from getting "backed up" waiting for earlier parts. * Bug fix: no header/body callbacks should now ever be invoked after the finish callback. * The client handles when a meta request is scheduled for work, instead of the meta request having to manage that at all.
1 parent e7f3dfe commit f732c85

21 files changed

Lines changed: 1958 additions & 1898 deletions
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef AWS_S3_AUTO_RANGED_GET_H
2+
#define AWS_S3_AUTO_RANGED_GET_H
3+
4+
/**
5+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6+
* SPDX-License-Identifier: Apache-2.0.
7+
*/
8+
9+
#include "aws/s3/private/s3_meta_request_impl.h"
10+
11+
enum aws_s3_auto_ranged_get_request_type {
12+
AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART,
13+
};
14+
15+
struct aws_s3_auto_ranged_get {
16+
struct aws_s3_meta_request base;
17+
18+
/* Members to only be used when the mutex in the base type is locked. */
19+
struct {
20+
uint32_t total_num_parts;
21+
22+
uint32_t num_parts_requested;
23+
uint32_t num_parts_completed;
24+
uint32_t num_parts_successful;
25+
uint32_t num_parts_failed;
26+
27+
size_t total_object_size;
28+
29+
} synced_data;
30+
};
31+
32+
/* Creates a new auto-ranged get meta request. This will do multiple parallel ranged-gets when appropriate. */
33+
struct aws_s3_meta_request *aws_s3_meta_request_auto_ranged_get_new(
34+
struct aws_allocator *allocator,
35+
struct aws_s3_client *client,
36+
size_t part_size,
37+
const struct aws_s3_meta_request_options *options);
38+
39+
#endif

include/aws/s3/private/s3_auto_ranged_put.h

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,7 @@
66
* SPDX-License-Identifier: Apache-2.0.
77
*/
88

9-
#include "aws/s3/private/s3_client_impl.h"
109
#include "aws/s3/private/s3_meta_request_impl.h"
11-
#include "aws/s3/private/s3_util.h"
12-
13-
enum aws_s3_auto_ranged_put_state {
14-
AWS_S3_AUTO_RANGED_PUT_STATE_START,
15-
AWS_S3_AUTO_RANGED_PUT_STATE_WAITING_FOR_CREATE,
16-
AWS_S3_AUTO_RANGED_PUT_STATE_SENDING_PARTS,
17-
AWS_S3_AUTO_RANGED_PUT_STATE_WAITING_FOR_PARTS,
18-
AWS_S3_AUTO_RANGED_PUT_STATE_WAITING_FOR_CANCEL,
19-
AWS_S3_AUTO_RANGED_PUT_STATE_SEND_COMPLETE,
20-
AWS_S3_AUTO_RANGED_PUT_STATE_WAITING_FOR_COMPLETE,
21-
};
2210

2311
enum aws_s3_auto_ranged_put_request_tag {
2412
AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD,
@@ -35,25 +23,44 @@ struct aws_s3_auto_ranged_put {
3523

3624
uint64_t content_length;
3725

26+
/* Only meant for use in the update function, which is never called concurrently. */
3827
struct {
39-
/* Only meant for use in the next_request function, which is never called concurrently. */
4028
uint32_t next_part_number;
41-
} threaded_next_request_data;
29+
} threaded_update_data;
4230

31+
/* Members to only be used when the mutex in the base type is locked. */
4332
struct {
44-
enum aws_s3_auto_ranged_put_state state;
4533
struct aws_array_list etag_list;
4634

4735
uint32_t total_num_parts;
4836
uint32_t num_parts_sent;
4937
uint32_t num_parts_completed;
38+
uint32_t num_parts_successful;
39+
uint32_t num_parts_failed;
5040

5141
struct aws_http_headers *needed_response_headers;
52-
struct aws_s3_meta_request_finish_options *cached_finish_options;
5342

54-
bool create_multipart_upload_successful;
43+
int create_multipart_upload_error_code;
44+
int complete_multipart_upload_error_code;
45+
int abort_multipart_upload_error_code;
46+
47+
uint32_t create_multipart_upload_sent : 1;
48+
uint32_t create_multipart_upload_completed : 1;
49+
uint32_t complete_multipart_upload_sent : 1;
50+
uint32_t complete_multipart_upload_completed : 1;
51+
uint32_t abort_multipart_upload_sent : 1;
52+
uint32_t abort_multipart_upload_completed : 1;
5553

5654
} synced_data;
5755
};
5856

57+
/* Creates a new auto-ranged put meta request. This will do a multipart upload in parallel when appropriate. */
58+
struct aws_s3_meta_request *aws_s3_meta_request_auto_ranged_put_new(
59+
struct aws_allocator *allocator,
60+
struct aws_s3_client *client,
61+
size_t part_size,
62+
uint64_t content_length,
63+
uint32_t num_parts,
64+
const struct aws_s3_meta_request_options *options);
65+
5966
#endif

include/aws/s3/private/s3_client_impl.h

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,16 @@ struct aws_s3_vip_connection {
9292
struct aws_retry_token *retry_token;
9393

9494
/* True if the connection is currently retrying to process the request. */
95-
bool is_retry;
95+
uint32_t is_retry : 1;
96+
97+
uint32_t is_active : 1;
9698
};
9799

98100
struct aws_s3_client_vtable {
99101

100102
struct aws_s3_meta_request *(
101103
*meta_request_factory)(struct aws_s3_client *client, const struct aws_s3_meta_request_options *options);
102104

103-
void (*push_meta_request)(struct aws_s3_client *client, struct aws_s3_meta_request *meta_request);
104-
105-
void (*remove_meta_request)(struct aws_s3_client *client, struct aws_s3_meta_request *meta_request);
106-
107105
void (*acquire_http_connection)(
108106
struct aws_s3_client *client,
109107
struct aws_s3_vip_connection *vip_connection,
@@ -168,6 +166,20 @@ struct aws_s3_client {
168166
aws_s3_client_shutdown_complete_callback_fn *shutdown_callback;
169167
void *shutdown_callback_user_data;
170168

169+
struct {
170+
/* Number of requests being sent/received over network. */
171+
struct aws_atomic_var num_requests_network_io;
172+
173+
/* Number of requests sitting in their meta request priority queue, waiting to be streamed. */
174+
struct aws_atomic_var num_requests_queued_waiting;
175+
176+
/* Number of requests currently scheduled to be streamed or are actively being streamed. */
177+
struct aws_atomic_var num_requests_streaming;
178+
179+
/* Number of allocated VIP connnections. */
180+
struct aws_atomic_var num_allocated_vip_connections;
181+
} stats;
182+
171183
struct {
172184
struct aws_mutex lock;
173185

@@ -230,19 +242,15 @@ struct aws_s3_client {
230242
/* Client list of on going meta requests. */
231243
struct aws_linked_list meta_requests;
232244

233-
/* Next meta request that the work_task will start with on its next update. */
234-
struct aws_s3_meta_request *next_meta_request;
235-
236245
/* Number of requests being processed, either still being sent/received or being streamed to the caller. */
237246
uint32_t num_requests_in_flight;
238247

248+
/* Number of current active aws_s3_vip_connections. */
249+
uint32_t num_active_vip_connections;
250+
239251
} threaded_data;
240252
};
241253

242-
void aws_s3_client_push_meta_request(struct aws_s3_client *client, struct aws_s3_meta_request *meta_request);
243-
244-
void aws_s3_client_remove_meta_request(struct aws_s3_client *client, struct aws_s3_meta_request *meta_request);
245-
246254
int aws_s3_client_make_request(struct aws_s3_client *client, struct aws_s3_vip_connection *vip_connection);
247255

248256
void aws_s3_client_notify_connection_finished(
@@ -253,10 +261,18 @@ void aws_s3_client_notify_connection_finished(
253261

254262
void aws_s3_client_notify_request_destroyed(struct aws_s3_client *client, struct aws_s3_request *request);
255263

264+
typedef void(aws_s3_client_stream_response_body_callback_fn)(
265+
int error_code,
266+
uint32_t num_failed,
267+
uint32_t num_successful,
268+
void *user_data);
269+
256270
void aws_s3_client_stream_response_body(
257271
struct aws_s3_client *client,
258272
struct aws_s3_meta_request *meta_request,
259-
struct aws_linked_list *requests);
273+
struct aws_linked_list *requests,
274+
aws_s3_client_stream_response_body_callback_fn callback,
275+
void *user_data);
260276

261277
AWS_EXTERN_C_BEGIN
262278

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef AWS_S3_DEFAULT_META_REQUEST_H
2+
#define AWS_S3_DEFAULT_META_REQUEST_H
3+
4+
/**
5+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6+
* SPDX-License-Identifier: Apache-2.0.
7+
*/
8+
9+
#include "aws/s3/private/s3_meta_request_impl.h"
10+
11+
struct aws_s3_client;
12+
13+
struct aws_s3_meta_request_default {
14+
struct aws_s3_meta_request base;
15+
16+
size_t content_length;
17+
18+
/* Members to only be used when the mutex in the base type is locked. */
19+
struct {
20+
int cached_response_status;
21+
int request_error_code;
22+
23+
uint32_t request_sent : 1;
24+
uint32_t request_completed : 1;
25+
26+
} synced_data;
27+
};
28+
29+
/* Creates a new default meta request. This will send the request as is and pass back the response. */
30+
struct aws_s3_meta_request *aws_s3_meta_request_default_new(
31+
struct aws_allocator *allocator,
32+
struct aws_s3_client *client,
33+
uint64_t content_length,
34+
const struct aws_s3_meta_request_options *options);
35+
36+
#endif

0 commit comments

Comments
 (0)