diff options
author | thegeorg <[email protected]> | 2025-05-12 15:51:24 +0300 |
---|---|---|
committer | thegeorg <[email protected]> | 2025-05-12 16:06:27 +0300 |
commit | d629bb70c8773d2c0c43f5088ddbb5a86d8c37ea (patch) | |
tree | 4f678e0d65ad08c800db21c657d3b0f71fafed06 /contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c | |
parent | 92c4b696d7a1c03d54e13aff7a7c20a078d90dd7 (diff) |
Update contrib/restricted/aws libraries to nixpkgs 24.05
commit_hash:f8083acb039e6005e820cdee77b84e0a6b6c6d6d
Diffstat (limited to 'contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c')
-rw-r--r-- | contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c | 179 |
1 files changed, 161 insertions, 18 deletions
diff --git a/contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c b/contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c index 5bc39a7316f..0e759ff610e 100644 --- a/contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c +++ b/contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c @@ -6,10 +6,15 @@ #include <aws/common/string.h> #include <inttypes.h> -#ifdef _MSC_VER -/* sscanf warning (not currently scanning for strings) */ -# pragma warning(disable : 4996) -#endif +/* Data for aws_s3_meta_request_default's vtable->prepare_request() job */ +struct aws_s3_default_prepare_request_job { + struct aws_allocator *allocator; + struct aws_s3_request *request; + /* async step: read request body */ + struct aws_future_bool *step1_read_body; + /* future to set when this whole job completes */ + struct aws_future_void *on_complete; +}; static void s_s3_meta_request_default_destroy(struct aws_s3_meta_request *meta_request); @@ -18,9 +23,13 @@ static bool s_s3_meta_request_default_update( uint32_t flags, struct aws_s3_request **out_request); -static int s_s3_meta_request_default_prepare_request( - struct aws_s3_meta_request *meta_request, - struct aws_s3_request *request); +static struct aws_future_void *s_s3_default_prepare_request(struct aws_s3_request *request); + +static void s_s3_default_prepare_request_on_read_done(void *user_data); + +static void s_s3_default_prepare_request_finish( + struct aws_s3_default_prepare_request_job *request_prep, + int error_code); static void s_s3_meta_request_default_request_finished( struct aws_s3_meta_request *meta_request, @@ -29,8 +38,8 @@ static void s_s3_meta_request_default_request_finished( static struct aws_s3_meta_request_vtable s_s3_meta_request_default_vtable = { .update = s_s3_meta_request_default_update, - .send_request_finish = aws_s3_meta_request_send_request_finish_handle_async_error, - .prepare_request = s_s3_meta_request_default_prepare_request, + .send_request_finish = aws_s3_meta_request_send_request_finish_default, + .prepare_request = s_s3_default_prepare_request, .init_signing_date_time = aws_s3_meta_request_init_signing_date_time_default, .sign_request = aws_s3_meta_request_sign_request_default, .finished_request = s_s3_meta_request_default_request_finished, @@ -42,9 +51,11 @@ static struct aws_s3_meta_request_vtable s_s3_meta_request_default_vtable = { struct aws_s3_meta_request *aws_s3_meta_request_default_new( struct aws_allocator *allocator, struct aws_s3_client *client, + enum aws_s3_request_type request_type, uint64_t content_length, bool should_compute_content_md5, const struct aws_s3_meta_request_options *options) { + AWS_PRECONDITION(allocator); AWS_PRECONDITION(client); AWS_PRECONDITION(options); @@ -94,8 +105,25 @@ struct aws_s3_meta_request *aws_s3_meta_request_default_new( } meta_request_default->content_length = (size_t)content_length; + meta_request_default->request_type = request_type; + + /* Try to get operation name. + * When internal aws-c-s3 code creates a default meta-request, + * a valid request_type is always passed in, and we can get its operation name. + * When external users create a default meta-request, they may have provided + * operation name in the options. */ + const char *operation_name = aws_s3_request_type_operation_name(request_type); + if (operation_name[0] != '\0') { + meta_request_default->operation_name = aws_string_new_from_c_str(allocator, operation_name); + } else if (options->operation_name.len != 0) { + meta_request_default->operation_name = aws_string_new_from_cursor(allocator, &options->operation_name); + } - AWS_LOGF_DEBUG(AWS_LS_S3_META_REQUEST, "id=%p Created new Default Meta Request.", (void *)meta_request_default); + AWS_LOGF_DEBUG( + AWS_LS_S3_META_REQUEST, + "id=%p Created new Default Meta Request. operation=%s", + (void *)meta_request_default, + meta_request_default->operation_name ? aws_string_c_str(meta_request_default->operation_name) : "?"); return &meta_request_default->base; } @@ -105,6 +133,7 @@ static void s_s3_meta_request_default_destroy(struct aws_s3_meta_request *meta_r AWS_PRECONDITION(meta_request->impl); struct aws_s3_meta_request_default *meta_request_default = meta_request->impl; + aws_string_destroy(meta_request_default->operation_name); aws_mem_release(meta_request->allocator, meta_request_default); } @@ -134,7 +163,19 @@ static bool s_s3_meta_request_default_update( goto has_work_remaining; } - request = aws_s3_request_new(meta_request, 0, 1, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); + request = aws_s3_request_new( + meta_request, + 0 /*request_tag*/, + meta_request_default->request_type, + 1 /*part_number*/, + AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); + + /* Default meta-request might know operation name, despite not knowing valid request_type. + * If so, pass the name along. */ + if (request->operation_name == NULL && meta_request_default->operation_name != NULL) { + request->operation_name = + aws_string_new_from_string(meta_request->allocator, meta_request_default->operation_name); + } AWS_LOGF_DEBUG( AWS_LS_S3_META_REQUEST, @@ -183,6 +224,10 @@ static bool s_s3_meta_request_default_update( work_remaining = true; no_work_remaining: + /* If some events are still being delivered to caller, then wait for those to finish */ + if (!work_remaining && aws_s3_meta_request_are_events_out_for_delivery_synced(meta_request)) { + work_remaining = true; + } if (!work_remaining) { aws_s3_meta_request_set_success_synced( @@ -208,20 +253,82 @@ static bool s_s3_meta_request_default_update( } /* Given a request, prepare it for sending based on its description. */ -static int s_s3_meta_request_default_prepare_request( - struct aws_s3_meta_request *meta_request, - struct aws_s3_request *request) { +static struct aws_future_void *s_s3_default_prepare_request(struct aws_s3_request *request) { + AWS_PRECONDITION(request); + + struct aws_s3_meta_request *meta_request = request->meta_request; AWS_PRECONDITION(meta_request); struct aws_s3_meta_request_default *meta_request_default = meta_request->impl; AWS_PRECONDITION(meta_request_default); + struct aws_future_void *asyncstep_prepare_request = aws_future_void_new(request->allocator); + + /* Store data for async job */ + struct aws_s3_default_prepare_request_job *request_prep = + aws_mem_calloc(request->allocator, 1, sizeof(struct aws_s3_default_prepare_request_job)); + request_prep->allocator = request->allocator; + request_prep->request = request; + request_prep->on_complete = aws_future_void_acquire(asyncstep_prepare_request); + if (meta_request_default->content_length > 0 && request->num_times_prepared == 0) { aws_byte_buf_init(&request->request_body, meta_request->allocator, meta_request_default->content_length); - if (aws_s3_meta_request_read_body(meta_request, &request->request_body)) { - return AWS_OP_ERR; - } + /* Kick off the async read */ + request_prep->step1_read_body = + aws_s3_meta_request_read_body(meta_request, 0 /*offset*/, &request->request_body); + aws_future_bool_register_callback( + request_prep->step1_read_body, s_s3_default_prepare_request_on_read_done, request_prep); + } else { + /* Don't need to read body, jump directly to the last step */ + s_s3_default_prepare_request_finish(request_prep, AWS_ERROR_SUCCESS); + } + + return asyncstep_prepare_request; +} + +/* Completion callback for reading the body stream */ +static void s_s3_default_prepare_request_on_read_done(void *user_data) { + + struct aws_s3_default_prepare_request_job *request_prep = user_data; + struct aws_s3_request *request = request_prep->request; + struct aws_s3_meta_request *meta_request = request->meta_request; + + int error_code = aws_future_bool_get_error(request_prep->step1_read_body); + + if (error_code != AWS_OP_SUCCESS) { + AWS_LOGF_ERROR( + AWS_LS_S3_META_REQUEST, + "id=%p: Failed reading request body, error %d (%s)", + (void *)meta_request, + error_code, + aws_error_str(error_code)); + goto finish; + } + + if (request->request_body.len < request->request_body.capacity) { + error_code = AWS_ERROR_S3_INCORRECT_CONTENT_LENGTH; + AWS_LOGF_ERROR( + AWS_LS_S3_META_REQUEST, + "id=%p: Request body is smaller than 'Content-Length' header said it would be", + (void *)meta_request); + goto finish; + } + +finish: + s_s3_default_prepare_request_finish(request_prep, error_code); +} + +/* Finish async preparation of the request */ +static void s_s3_default_prepare_request_finish( + struct aws_s3_default_prepare_request_job *request_prep, + int error_code) { + + struct aws_s3_request *request = request_prep->request; + struct aws_s3_meta_request *meta_request = request->meta_request; + + if (error_code != AWS_ERROR_SUCCESS) { + goto finish; } struct aws_http_message *message = aws_s3_message_util_copy_http_message_no_body_all_headers( @@ -251,7 +358,16 @@ static int s_s3_meta_request_default_prepare_request( AWS_LOGF_DEBUG( AWS_LS_S3_META_REQUEST, "id=%p: Meta Request prepared request %p", (void *)meta_request, (void *)request); - return AWS_OP_SUCCESS; +finish: + if (error_code == AWS_ERROR_SUCCESS) { + aws_future_void_set_result(request_prep->on_complete); + } else { + aws_future_void_set_error(request_prep->on_complete, error_code); + } + + aws_future_bool_release(request_prep->step1_read_body); + aws_future_void_release(request_prep->on_complete); + aws_mem_release(request_prep->allocator, request_prep); } static void s_s3_meta_request_default_request_finished( @@ -285,13 +401,40 @@ static void s_s3_meta_request_default_request_finished( meta_request_default->synced_data.cached_response_status = request->send_data.response_status; meta_request_default->synced_data.request_completed = true; meta_request_default->synced_data.request_error_code = error_code; + bool finishing_metrics = true; if (error_code == AWS_ERROR_SUCCESS) { + /* Send progress_callback for delivery on io_event_loop thread. + * For default meta-requests, we invoke the progress_callback once, after the sole HTTP request completes. + * This is simpler than reporting incremental progress as the response body is received, + * or the request body is streamed out, since then we'd also need to handle retries that reset + * progress back to 0% (our existing API only lets us report forward progress). */ + if (meta_request->progress_callback != NULL) { + struct aws_s3_meta_request_event event = {.type = AWS_S3_META_REQUEST_EVENT_PROGRESS}; + if (meta_request->type == AWS_S3_META_REQUEST_TYPE_PUT_OBJECT) { + /* For uploads, report request body size */ + event.u.progress.info.bytes_transferred = request->request_body.len; + event.u.progress.info.content_length = request->request_body.len; + } else { + /* For anything else, report response body size */ + event.u.progress.info.bytes_transferred = request->send_data.response_body.len; + event.u.progress.info.content_length = request->send_data.response_body.len; + } + aws_s3_meta_request_add_event_for_delivery_synced(meta_request, &event); + } + aws_s3_meta_request_stream_response_body_synced(meta_request, request); + /* The body of the request is queued to be streamed, don't record the end timestamp for the request + * yet. */ + finishing_metrics = false; } else { aws_s3_meta_request_set_fail_synced(meta_request, request, error_code); } + if (finishing_metrics) { + aws_s3_request_finish_up_metrics_synced(request, meta_request); + } + aws_s3_meta_request_unlock_synced_data(meta_request); } /* END CRITICAL SECTION */ |