Skip to content

Commit 651171f

Browse files
authored
Adding max connections override (#108)
1 parent 3276dfe commit 651171f

5 files changed

Lines changed: 97 additions & 4 deletions

File tree

include/aws/s3/private/s3_client_impl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ struct aws_s3_client {
173173
/* The calculated ideal number of VIP's based on throughput target and throughput per vip. */
174174
const uint32_t ideal_vip_count;
175175

176+
/* Hard limit on max connections set through the client config. */
177+
const uint32_t max_active_connections_override;
178+
176179
/* Retry strategy used for scheduling request retries. */
177180
struct aws_retry_strategy *retry_strategy;
178181

@@ -372,6 +375,9 @@ void aws_s3_client_lock_synced_data(struct aws_s3_client *client);
372375
AWS_S3_API
373376
void aws_s3_client_unlock_synced_data(struct aws_s3_client *client);
374377

378+
AWS_S3_API
379+
extern const uint32_t g_max_num_connections_per_vip;
380+
375381
AWS_EXTERN_C_END
376382

377383
#endif /* AWS_S3_CLIENT_IMPL_H */

include/aws/s3/s3_client.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ enum aws_s3_meta_request_tls_mode {
6161
/* Options for a new client. */
6262
struct aws_s3_client_config {
6363

64+
/* When set, this will cap the number of active connections. When 0, the client will determine this value based on
65+
* throughput_target_gbps. (Recommended) */
66+
uint32_t max_active_connections_override;
67+
6468
/* Region that the S3 bucket lives in. */
6569
struct aws_byte_cursor region;
6670

source/s3_client.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static const uint32_t s_num_conns_per_vip_meta_request_look_up[AWS_S3_META_REQUE
5656
};
5757

5858
/* Should be max of s_num_conns_per_vip_meta_request_look_up */
59-
static const uint32_t s_num_connections_per_vip = 10;
59+
const uint32_t g_max_num_connections_per_vip = 10;
6060

6161
/* 50 = 0.5 * 100, where 100 is the max number of requests allowed per connection */
6262
static const uint8_t s_max_request_jitter_range = 50;
@@ -168,10 +168,17 @@ uint32_t aws_s3_client_get_max_active_connections(struct aws_s3_client *client,
168168
AWS_PRECONDITION(client);
169169

170170
if (num_connections_per_vip == 0) {
171-
num_connections_per_vip = s_num_connections_per_vip;
171+
num_connections_per_vip = g_max_num_connections_per_vip;
172172
}
173173

174-
return client->ideal_vip_count * num_connections_per_vip;
174+
uint32_t max_active_connections = client->ideal_vip_count * num_connections_per_vip;
175+
176+
if (client->max_active_connections_override > 0 &&
177+
client->max_active_connections_override < max_active_connections) {
178+
max_active_connections = client->max_active_connections_override;
179+
}
180+
181+
return max_active_connections;
175182
}
176183

177184
uint32_t aws_s3_client_get_max_requests_in_flight(struct aws_s3_client *client) {
@@ -247,6 +254,8 @@ struct aws_s3_client *aws_s3_client_new(
247254
aws_atomic_init_int(&client->stats.num_active_vip_connections, 0);
248255
aws_atomic_init_int(&client->stats.num_warm_vip_connections, 0);
249256

257+
*((uint32_t *)&client->max_active_connections_override) = client_config->max_active_connections_override;
258+
250259
/* Store our client bootstrap. */
251260
client->client_bootstrap = aws_client_bootstrap_acquire(client_config->client_bootstrap);
252261

@@ -2301,7 +2310,7 @@ static int s_s3_client_add_vips_default(struct aws_s3_client *client, const stru
23012310
client,
23022311
&host_address_byte_cursor,
23032312
&server_name,
2304-
s_num_connections_per_vip,
2313+
g_max_num_connections_per_vip,
23052314
&vip_connections,
23062315
s_s3_client_vip_shutdown_callback,
23072316
client);

tests/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ file(GLOB TEST_HDRS "*.h")
66
file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC})
77

88
add_net_test_case(test_s3_client_create_destroy)
9+
add_net_test_case(test_s3_client_max_active_connections_override)
10+
add_test_case(test_s3_client_get_max_active_connections)
911
add_test_case(test_s3_request_create_destroy)
1012
add_test_case(test_s3_client_queue_requests)
1113
add_test_case(test_s3_meta_request_body_streaming)
@@ -82,5 +84,6 @@ add_net_test_case(test_s3_default_sending_meta_request)
8284
add_test_case(test_get_existing_compute_platform_info)
8385
add_test_case(test_get_nonexistent_compute_platform_info)
8486

87+
8588
set(TEST_BINARY_NAME ${PROJECT_NAME}-tests)
8689
generate_test_driver(${TEST_BINARY_NAME})

tests/s3_data_plane_tests.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,77 @@ static int s_test_s3_client_create_destroy(struct aws_allocator *allocator, void
4747
return 0;
4848
}
4949

50+
AWS_TEST_CASE(test_s3_client_max_active_connections_override, s_test_s3_client_max_active_connections_override)
51+
static int s_test_s3_client_max_active_connections_override(struct aws_allocator *allocator, void *ctx) {
52+
(void)allocator;
53+
(void)ctx;
54+
55+
struct aws_s3_tester tester;
56+
AWS_ZERO_STRUCT(tester);
57+
ASSERT_SUCCESS(aws_s3_tester_init(allocator, &tester));
58+
59+
struct aws_s3_client_config client_config = {
60+
.max_active_connections_override = 10,
61+
};
62+
63+
ASSERT_SUCCESS(aws_s3_tester_bind_client(&tester, &client_config, 0));
64+
65+
struct aws_s3_client *client = aws_s3_client_new(allocator, &client_config);
66+
67+
ASSERT_TRUE(client->max_active_connections_override == client_config.max_active_connections_override);
68+
69+
aws_s3_client_release(client);
70+
aws_s3_tester_clean_up(&tester);
71+
72+
return 0;
73+
}
74+
75+
AWS_TEST_CASE(test_s3_client_get_max_active_connections, s_test_s3_client_get_max_active_connections)
76+
static int s_test_s3_client_get_max_active_connections(struct aws_allocator *allocator, void *ctx) {
77+
(void)ctx;
78+
79+
struct aws_s3_tester tester;
80+
AWS_ZERO_STRUCT(tester);
81+
ASSERT_SUCCESS(aws_s3_tester_init(allocator, &tester));
82+
83+
const uint32_t num_connections_per_vip_override = 5;
84+
85+
struct aws_s3_client *mock_client = aws_s3_tester_mock_client_new(&tester);
86+
*((uint32_t *)&mock_client->ideal_vip_count) = 5;
87+
*((uint32_t *)&mock_client->max_active_connections_override) = 0;
88+
89+
/* Behavior should not be affected by max_active_connections_override since it is 0. */
90+
ASSERT_TRUE(
91+
aws_s3_client_get_max_active_connections(mock_client, 0) ==
92+
mock_client->ideal_vip_count * g_max_num_connections_per_vip);
93+
ASSERT_TRUE(
94+
aws_s3_client_get_max_active_connections(mock_client, num_connections_per_vip_override) ==
95+
mock_client->ideal_vip_count * num_connections_per_vip_override);
96+
97+
*((uint32_t *)&mock_client->max_active_connections_override) = 3;
98+
99+
/* Max active connections override should now cap the calculated amount of active connections. */
100+
ASSERT_TRUE(
101+
aws_s3_client_get_max_active_connections(mock_client, 0) == mock_client->max_active_connections_override);
102+
ASSERT_TRUE(
103+
aws_s3_client_get_max_active_connections(mock_client, num_connections_per_vip_override) ==
104+
mock_client->max_active_connections_override);
105+
106+
/* Max active connections override should be ignored since the calculated amount of connections is less. */
107+
*((uint32_t *)&mock_client->max_active_connections_override) = 100;
108+
ASSERT_TRUE(
109+
aws_s3_client_get_max_active_connections(mock_client, 0) ==
110+
mock_client->ideal_vip_count * g_max_num_connections_per_vip);
111+
ASSERT_TRUE(
112+
aws_s3_client_get_max_active_connections(mock_client, num_connections_per_vip_override) ==
113+
mock_client->ideal_vip_count * num_connections_per_vip_override);
114+
115+
aws_s3_client_release(mock_client);
116+
aws_s3_tester_clean_up(&tester);
117+
118+
return 0;
119+
}
120+
50121
AWS_TEST_CASE(test_s3_request_create_destroy, s_test_s3_request_create_destroy)
51122
static int s_test_s3_request_create_destroy(struct aws_allocator *allocator, void *ctx) {
52123
(void)ctx;

0 commit comments

Comments
 (0)