in source/s3_client.c [1471:1616]
void aws_s3_client_notify_connection_finished(
struct aws_s3_client *client,
struct aws_s3_connection *connection,
int error_code,
enum aws_s3_connection_finish_code finish_code) {
AWS_PRECONDITION(client);
AWS_PRECONDITION(connection);
struct aws_s3_request *request = connection->request;
AWS_PRECONDITION(request);
struct aws_s3_meta_request *meta_request = request->meta_request;
AWS_PRECONDITION(meta_request);
AWS_PRECONDITION(meta_request->initial_request_message);
struct aws_s3_endpoint *endpoint = meta_request->endpoint;
AWS_PRECONDITION(endpoint);
/* If we're trying to setup a retry... */
if (finish_code == AWS_S3_CONNECTION_FINISH_CODE_RETRY) {
if (connection->retry_token == NULL) {
AWS_LOGF_ERROR(
AWS_LS_S3_CLIENT,
"id=%p Client could not schedule retry of request %p for meta request %p",
(void *)client,
(void *)request,
(void *)meta_request);
goto reset_connection;
}
if (aws_s3_meta_request_is_finished(meta_request)) {
AWS_LOGF_DEBUG(
AWS_LS_S3_CLIENT,
"id=%p Client not scheduling retry of request %p for meta request %p with token %p because meta "
"request has been flagged as finished.",
(void *)client,
(void *)request,
(void *)meta_request,
(void *)connection->retry_token);
goto reset_connection;
}
AWS_LOGF_DEBUG(
AWS_LS_S3_CLIENT,
"id=%p Client scheduling retry of request %p for meta request %p with token %p.",
(void *)client,
(void *)request,
(void *)meta_request,
(void *)connection->retry_token);
enum aws_retry_error_type error_type = AWS_RETRY_ERROR_TYPE_TRANSIENT;
switch (error_code) {
case AWS_ERROR_S3_INTERNAL_ERROR:
error_type = AWS_RETRY_ERROR_TYPE_SERVER_ERROR;
break;
case AWS_ERROR_S3_SLOW_DOWN:
error_type = AWS_RETRY_ERROR_TYPE_THROTTLING;
break;
}
if (connection->http_connection != NULL) {
AWS_ASSERT(endpoint->http_connection_manager);
aws_http_connection_manager_release_connection(
endpoint->http_connection_manager, connection->http_connection);
connection->http_connection = NULL;
}
/* Ask the retry strategy to schedule a retry of the request. */
if (aws_retry_strategy_schedule_retry(
connection->retry_token, error_type, s_s3_client_retry_ready, connection)) {
error_code = aws_last_error_or_unknown();
AWS_LOGF_ERROR(
AWS_LS_S3_CLIENT,
"id=%p Client could not retry request %p for meta request %p with token %p due to error %d (%s)",
(void *)client,
(void *)request,
(void *)meta_request,
(void *)connection->retry_token,
error_code,
aws_error_str(error_code));
goto reset_connection;
}
return;
}
reset_connection:
if (connection->retry_token != NULL) {
/* If we have a retry token and successfully finished, record that success. */
if (finish_code == AWS_S3_CONNECTION_FINISH_CODE_SUCCESS) {
aws_retry_token_record_success(connection->retry_token);
}
aws_retry_token_release(connection->retry_token);
connection->retry_token = NULL;
}
/* If we weren't successful, and we're here, that means this failure is not eligible for a retry. So finish the
* request, and close our HTTP connection. */
if (finish_code != AWS_S3_CONNECTION_FINISH_CODE_SUCCESS) {
if (connection->http_connection != NULL) {
aws_http_connection_close(connection->http_connection);
}
}
aws_atomic_fetch_sub(&client->stats.num_requests_network_io[meta_request->type], 1);
aws_s3_meta_request_finished_request(meta_request, request, error_code);
if (connection->http_connection != NULL) {
AWS_ASSERT(endpoint->http_connection_manager);
aws_http_connection_manager_release_connection(endpoint->http_connection_manager, connection->http_connection);
connection->http_connection = NULL;
}
if (connection->request != NULL) {
aws_s3_request_release(connection->request);
connection->request = NULL;
}
aws_retry_token_release(connection->retry_token);
connection->retry_token = NULL;
aws_s3_endpoint_release(connection->endpoint);
connection->endpoint = NULL;
aws_mem_release(client->allocator, connection);
connection = NULL;
aws_s3_client_lock_synced_data(client);
s_s3_client_schedule_process_work_synced(client);
aws_s3_client_unlock_synced_data(client);
}