Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: awslabs/aws-c-http
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.8.8
Choose a base ref
...
head repository: awslabs/aws-c-http
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.8.9
Choose a head ref
  • 1 commit
  • 5 files changed
  • 1 contributor

Commits on Sep 10, 2024

  1. Fix max_pending_connection_acquisitions to respect connection pool si…

    …ze (#485)
    waahm7 authored Sep 10, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    4b1634b View commit details
Showing with 62 additions and 10 deletions.
  1. +1 −1 .github/workflows/ci.yml
  2. +3 −2 include/aws/http/connection_manager.h
  3. +2 −1 source/connection_manager.c
  4. +1 −0 tests/CMakeLists.txt
  5. +55 −6 tests/test_connection_manager.c
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ on:
- 'main'

env:
BUILDER_VERSION: v0.9.62
BUILDER_VERSION: v0.9.64
BUILDER_SOURCE: releases
BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net
PACKAGE_NAME: aws-c-http
5 changes: 3 additions & 2 deletions include/aws/http/connection_manager.h
Original file line number Diff line number Diff line change
@@ -134,8 +134,9 @@ struct aws_http_connection_manager_options {

/*
* If set to a non-zero value, aws_http_connection_manager_acquire_connection() calls will fail with
* AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED if there are already pending acquisitions
* equal to `max_pending_connection_acquisitions`.
* AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED if the number of pending acquisitions
* reaches `max_pending_connection_acquisitions` after the connection pool has reached its capacity (i.e., all
* `num_connections` have been vended).
*/
uint64_t max_pending_connection_acquisitions;

3 changes: 2 additions & 1 deletion source/connection_manager.c
Original file line number Diff line number Diff line change
@@ -1311,7 +1311,8 @@ void aws_http_connection_manager_acquire_connection(
AWS_FATAL_ASSERT(manager->state == AWS_HCMST_READY);

if (manager->max_pending_connection_acquisitions == 0 ||
manager->pending_acquisition_count < manager->max_pending_connection_acquisitions) {
manager->pending_acquisition_count + manager->internal_ref[AWS_HCMCT_VENDED_CONNECTION] <
manager->max_pending_connection_acquisitions + manager->max_connections) {
aws_linked_list_push_back(&manager->pending_acquisitions, &request->node);
++manager->pending_acquisition_count;
} else {
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -546,6 +546,7 @@ add_net_test_case(test_connection_manager_acquire_release)
add_net_test_case(test_connection_manager_close_and_release)
add_net_test_case(test_connection_manager_acquire_release_mix)
add_net_test_case(test_connection_manager_max_pending_acquisitions)
add_net_test_case(test_connection_manager_max_pending_acquisitions_with_vended_connections)

# Integration test that requires proxy envrionment in us-east-1 region.
# TODO: test the server name validation properly
61 changes: 55 additions & 6 deletions tests/test_connection_manager.c
Original file line number Diff line number Diff line change
@@ -749,32 +749,81 @@ static int s_test_connection_manager_max_pending_acquisitions(struct aws_allocat
(void)ctx;

size_t num_connections = 2;
size_t num_pending_connections = 3;
size_t max_pending_connection_acquisitions = 2;
size_t num_connections_pending_error = 4;
struct cm_tester_options options = {
.allocator = allocator,
.max_connections = num_connections,
.max_pending_connection_acquisitions = num_connections,
.max_pending_connection_acquisitions = max_pending_connection_acquisitions,
};

ASSERT_SUCCESS(s_cm_tester_init(&options));

s_acquire_connections(num_connections + num_pending_connections);
s_acquire_connections(num_connections + max_pending_connection_acquisitions + num_connections_pending_error);

ASSERT_SUCCESS(s_wait_on_connection_reply_count(num_connections + num_pending_connections));
ASSERT_UINT_EQUALS(num_pending_connections, s_tester.connection_errors);
for (size_t i = 0; i < num_pending_connections; i++) {
ASSERT_SUCCESS(s_wait_on_connection_reply_count(num_connections + num_connections_pending_error));
ASSERT_UINT_EQUALS(num_connections_pending_error, s_tester.connection_errors);
for (size_t i = 0; i < num_connections_pending_error; i++) {
uint32_t error_code;
aws_array_list_get_at(&s_tester.connection_errors_list, &error_code, i);
ASSERT_UINT_EQUALS(AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED, error_code);
}

ASSERT_SUCCESS(s_release_connections(num_connections, false));
ASSERT_SUCCESS(s_wait_on_connection_reply_count(
num_connections + max_pending_connection_acquisitions + num_connections_pending_error));
ASSERT_SUCCESS(s_release_connections(max_pending_connection_acquisitions, false));

ASSERT_SUCCESS(s_cm_tester_clean_up());

return AWS_OP_SUCCESS;
}
AWS_TEST_CASE(test_connection_manager_max_pending_acquisitions, s_test_connection_manager_max_pending_acquisitions);

static int s_test_connection_manager_max_pending_acquisitions_with_vended_connections(
struct aws_allocator *allocator,
void *ctx) {
(void)ctx;

size_t num_connections = 2;
size_t max_pending_connection_acquisitions = 2;
size_t num_connections_pending_error = 4;
struct cm_tester_options options = {
.allocator = allocator,
.max_connections = num_connections,
.max_pending_connection_acquisitions = max_pending_connection_acquisitions,
};

ASSERT_SUCCESS(s_cm_tester_init(&options));

// fill the connection pool
s_acquire_connections(num_connections);
ASSERT_SUCCESS(s_wait_on_connection_reply_count(num_connections));

// try to acquire over max_pending_connection_acquisitions
s_acquire_connections(max_pending_connection_acquisitions + num_connections_pending_error);
ASSERT_SUCCESS(s_wait_on_connection_reply_count(num_connections + num_connections_pending_error));

ASSERT_UINT_EQUALS(num_connections_pending_error, s_tester.connection_errors);
for (size_t i = 0; i < num_connections_pending_error; i++) {
uint32_t error_code;
aws_array_list_get_at(&s_tester.connection_errors_list, &error_code, i);
ASSERT_UINT_EQUALS(AWS_ERROR_HTTP_CONNECTION_MANAGER_MAX_PENDING_ACQUISITIONS_EXCEEDED, error_code);
}

ASSERT_SUCCESS(s_release_connections(num_connections, false));
ASSERT_SUCCESS(s_wait_on_connection_reply_count(
num_connections + max_pending_connection_acquisitions + num_connections_pending_error));
ASSERT_SUCCESS(s_release_connections(max_pending_connection_acquisitions, false));

ASSERT_SUCCESS(s_cm_tester_clean_up());

return AWS_OP_SUCCESS;
}
AWS_TEST_CASE(
test_connection_manager_max_pending_acquisitions_with_vended_connections,
s_test_connection_manager_max_pending_acquisitions_with_vended_connections);

static int s_aws_http_connection_manager_create_connection_sync_mock(
const struct aws_http_client_connection_options *options) {
struct cm_tester *tester = &s_tester;