summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2025-05-12 15:51:24 +0300
committerthegeorg <[email protected]>2025-05-12 16:06:27 +0300
commitd629bb70c8773d2c0c43f5088ddbb5a86d8c37ea (patch)
tree4f678e0d65ad08c800db21c657d3b0f71fafed06 /contrib/restricted/aws/aws-c-s3/source/s3_default_meta_request.c
parent92c4b696d7a1c03d54e13aff7a7c20a078d90dd7 (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.c179
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 */