From aab51014fc3e9e538f496fdd20e29d60a053e0c9 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 21 Nov 2023 15:59:36 -0800 Subject: [PATCH 01/13] Report S3 operation name of specific request that failed. --- .../aws/s3/private/s3_default_meta_request.h | 2 + include/aws/s3/private/s3_meta_request_impl.h | 12 ++- include/aws/s3/private/s3_request.h | 14 ++- include/aws/s3/s3_client.h | 50 ++++++++++- source/s3_auto_ranged_get.c | 4 +- source/s3_auto_ranged_put.c | 2 +- source/s3_copy_object.c | 5 +- source/s3_default_meta_request.c | 13 +++ source/s3_meta_request.c | 7 ++ source/s3_request.c | 86 +++++++++++++++++-- tests/s3_data_plane_tests.c | 13 +++ tests/s3_mock_server_tests.c | 12 +++ tests/s3_tester.c | 8 ++ tests/s3_tester.h | 1 + 14 files changed, 209 insertions(+), 20 deletions(-) diff --git a/include/aws/s3/private/s3_default_meta_request.h b/include/aws/s3/private/s3_default_meta_request.h index 123c963b5..2b16214bc 100644 --- a/include/aws/s3/private/s3_default_meta_request.h +++ b/include/aws/s3/private/s3_default_meta_request.h @@ -15,6 +15,8 @@ struct aws_s3_meta_request_default { size_t content_length; + struct aws_string *operation_name; + /* Members to only be used when the mutex in the base type is locked. */ struct { int cached_response_status; diff --git a/include/aws/s3/private/s3_meta_request_impl.h b/include/aws/s3/private/s3_meta_request_impl.h index 93ebb191a..0a603c26b 100644 --- a/include/aws/s3/private/s3_meta_request_impl.h +++ b/include/aws/s3/private/s3_meta_request_impl.h @@ -118,8 +118,16 @@ struct aws_s3_meta_request_vtable { /* Pause the given request */ int (*pause)(struct aws_s3_meta_request *meta_request, struct aws_s3_meta_request_resume_token **resume_token); - /* Get the type of the aws_s3_request */ - int (*get_request_type)(const struct aws_s3_request *request); + /* Get the type of the aws_s3_request. + * Not implemented for DEFAULT type, which doesn't know its aws_s3_request_type enum value */ + enum aws_s3_request_type (*get_request_type)(const struct aws_s3_request *request); + + /* Get the S3 operation name for the meta-request. + * This is only implemented for DEFAULT type, which doesn't know its + * aws_s3_request_type enum value, but might know its operation name. + * Returns empty string if the name isn't known. + * Note that this C-string's lifetime is tied to the meta-request. */ + const char *(*get_operation_name)(const struct aws_s3_meta_request *meta_request); }; /** diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index ae00a9f18..5e85b77b0 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -75,6 +75,8 @@ struct aws_s3_request_metrics { struct aws_string *host_address; /* The the request ID header value. */ struct aws_string *request_id; + /* S3 operation name for the request (NULL if unknown) */ + struct aws_string *operation_name; /* The type of request made */ enum aws_s3_request_type request_type; } req_resp_info_metrics; @@ -242,10 +244,20 @@ struct aws_s3_request *aws_s3_request_acquire(struct aws_s3_request *request); AWS_S3_API struct aws_s3_request *aws_s3_request_release(struct aws_s3_request *request); +/* Return type enum, if it is known. Otherwise AWS_S3_REQUEST_TYPE_MAX is returned. */ +AWS_S3_API +enum aws_s3_request_type aws_s3_request_get_type(const struct aws_s3_request *request); + +/* Return S3 operation name, if it is known. Otherwise an empty string is returned. + * Note that this C-string's lifetime is tied to the aws_s3_request. */ +AWS_S3_API +const char *aws_s3_request_get_operation_name(const struct aws_s3_request *request); + AWS_S3_API struct aws_s3_request_metrics *aws_s3_request_metrics_new( struct aws_allocator *allocator, - struct aws_http_message *message); + const struct aws_s3_request *request, + const struct aws_http_message *message); AWS_EXTERN_C_END diff --git a/include/aws/s3/s3_client.h b/include/aws/s3/s3_client.h index 71f95d75d..327506d10 100644 --- a/include/aws/s3/s3_client.h +++ b/include/aws/s3/s3_client.h @@ -86,6 +86,9 @@ enum aws_s3_meta_request_type { /** * The type of S3 request made. Used by metrics. + * aws_s3_request_type_operation_name() returns the S3 operation name + * for types that map (e.g. AWS_S3_REQUEST_TYPE_HEAD_OBJECT -> "HeadObject"), + * or empty string for types that don't map (e.g. AWS_S3_REQUEST_TYPE_DEFAULT -> ""). */ enum aws_s3_request_type { /* Same as the original HTTP request passed to aws_s3_meta_request_options */ @@ -100,6 +103,7 @@ enum aws_s3_request_type { AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY, + AWS_S3_REQUEST_TYPE_COPY_OBJECT, AWS_S3_REQUEST_TYPE_MAX, }; @@ -481,6 +485,15 @@ struct aws_s3_meta_request_options { /* The type of meta request we will be trying to accelerate. */ enum aws_s3_meta_request_type type; + /** + * Optional. + * The S3 operation name (e.g. "CreateBucket"). + * You should only set this when type is AWS_S3_META_REQUEST_TYPE_DEFAULT; + * it is automatically populated for other meta-request types. + * This name is used to fill out details in metrics and error reports. + */ + struct aws_byte_cursor operation_name; + /* Signing options to be used for each request created for this meta request. If NULL, options in the client will * be used. If not NULL, these options will override the client options. */ const struct aws_signing_config_aws *signing_config; @@ -602,12 +615,23 @@ struct aws_s3_meta_request_options { */ struct aws_s3_meta_request_result { - /* HTTP Headers for the failed request that triggered finish of the meta request. NULL if no request failed. */ + /* If meta request failed due to an HTTP error response from S3, these are the headers. + * NULL if meta request failed for another reason. */ struct aws_http_headers *error_response_headers; - /* Response body for the failed request that triggered finishing of the meta request. NULL if no request failed.*/ + /* If meta request failed due to an HTTP error response from S3, this the body. + * NULL if meta request failed for another reason, or if the response had no body (such as a HEAD response). */ struct aws_byte_buf *error_response_body; + /* If meta request failed due to an HTTP error response from S3, + * this is the name of the S3 operation it was responding to. + * For example, if a AWS_S3_META_REQUEST_TYPE_PUT_OBJECT fails, this could be + * "CreateMultipartUpload", "UploadPart", "CompleteMultipartUpload", or others. + * For AWS_S3_META_REQUEST_TYPE_DEFAULT, this is the same value passed to + * aws_s3_meta_request_options.operation_name. + * NULL if the meta request failed for another reason, or the operation name is not known. */ + struct aws_string *error_response_operation_name; + /* Response status of the failed request or of the entire meta request. */ int response_status; @@ -823,6 +847,17 @@ void aws_s3_init_default_signing_config( const struct aws_byte_cursor region, struct aws_credentials_provider *credentials_provider); +/** + * Return operation name for aws_s3_request_type, + * or empty string if the type doesn't map to an actual operation. + * For example: + * AWS_S3_REQUEST_TYPE_HEAD_OBJECT -> "HeadObject" + * AWS_S3_REQUEST_TYPE_DEFAULT -> "" + * AWS_S3_REQUEST_TYPE_MAX -> "" + */ +AWS_S3_API +const char *aws_s3_request_type_operation_name(enum aws_s3_request_type type); + /** * Add a reference, keeping this object alive. * The reference must be released when you are done with it, or it's memory will never be cleaned up. @@ -974,6 +1009,17 @@ int aws_s3_request_metrics_get_thread_id(const struct aws_s3_request_metrics *me AWS_S3_API int aws_s3_request_metrics_get_request_stream_id(const struct aws_s3_request_metrics *metrics, uint32_t *out_stream_id); +/** + * Get the S3 operation name of the request (e.g. "HeadObject"). + * If unavailable, AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised. + * If available, out_operation_name will be set to a string. + * Be warned this string's lifetime is tied to the metrics object. + */ +AWS_S3_API +int aws_s3_request_metrics_get_operation_name( + const struct aws_s3_request_metrics *metrics, + const struct aws_string **out_operation_name); + /* Get the request type from request metrics. */ AWS_S3_API void aws_s3_request_metrics_get_request_type( diff --git a/source/s3_auto_ranged_get.c b/source/s3_auto_ranged_get.c index e338d7f4a..ce881bc2d 100644 --- a/source/s3_auto_ranged_get.c +++ b/source/s3_auto_ranged_get.c @@ -28,7 +28,7 @@ static void s_s3_auto_ranged_get_request_finished( struct aws_s3_request *request, int error_code); -static int s_s3_auto_ranged_get_request_type(const struct aws_s3_request *request); +static enum aws_s3_request_type s_s3_auto_ranged_get_request_type(const struct aws_s3_request *request); static struct aws_s3_meta_request_vtable s_s3_auto_ranged_get_vtable = { .update = s_s3_auto_ranged_get_update, @@ -42,7 +42,7 @@ static struct aws_s3_meta_request_vtable s_s3_auto_ranged_get_vtable = { .get_request_type = s_s3_auto_ranged_get_request_type, }; -static int s_s3_auto_ranged_get_request_type(const struct aws_s3_request *request) { +static enum aws_s3_request_type s_s3_auto_ranged_get_request_type(const struct aws_s3_request *request) { switch (request->request_tag) { case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_HEAD_OBJECT: return AWS_S3_REQUEST_TYPE_HEAD_OBJECT; diff --git a/source/s3_auto_ranged_put.c b/source/s3_auto_ranged_put.c index adcfb086f..4384fed3e 100644 --- a/source/s3_auto_ranged_put.c +++ b/source/s3_auto_ranged_put.c @@ -294,7 +294,7 @@ static int s_try_init_resume_state_from_persisted_data( return AWS_OP_SUCCESS; } -static int s_s3_auto_ranged_put_request_type(const struct aws_s3_request *request) { +static enum aws_s3_request_type s_s3_auto_ranged_put_request_type(const struct aws_s3_request *request) { switch (request->request_tag) { case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_LIST_PARTS: return AWS_S3_REQUEST_TYPE_LIST_PARTS; diff --git a/source/s3_copy_object.c b/source/s3_copy_object.c index a619f0959..0e87f98c6 100644 --- a/source/s3_copy_object.c +++ b/source/s3_copy_object.c @@ -37,14 +37,13 @@ static void s_s3_copy_object_request_finished( struct aws_s3_request *request, int error_code); -static int s_s3_copy_object_request_type(const struct aws_s3_request *request) { +static enum aws_s3_request_type s_s3_copy_object_request_type(const struct aws_s3_request *request) { switch (request->request_tag) { case AWS_S3_COPY_OBJECT_REQUEST_TAG_GET_OBJECT_SIZE: /* It's a HEAD request of GetObject call */ return AWS_S3_REQUEST_TYPE_HEAD_OBJECT; case AWS_S3_COPY_OBJECT_REQUEST_TAG_BYPASS: - /* A single copy object request, same as default */ - return AWS_S3_REQUEST_TYPE_DEFAULT; + return AWS_S3_REQUEST_TYPE_COPY_OBJECT; case AWS_S3_COPY_OBJECT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD: return AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD; case AWS_S3_COPY_OBJECT_REQUEST_TAG_MULTIPART_COPY: diff --git a/source/s3_default_meta_request.c b/source/s3_default_meta_request.c index 420eecf80..38dc24d86 100644 --- a/source/s3_default_meta_request.c +++ b/source/s3_default_meta_request.c @@ -36,6 +36,8 @@ static void s_s3_meta_request_default_request_finished( struct aws_s3_request *request, int error_code); +static const char *s_s3_meta_request_default_operation_name(const struct aws_s3_meta_request *meta_request); + 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_default, @@ -45,6 +47,7 @@ static struct aws_s3_meta_request_vtable s_s3_meta_request_default_vtable = { .finished_request = s_s3_meta_request_default_request_finished, .destroy = s_s3_meta_request_default_destroy, .finish = aws_s3_meta_request_finish_default, + .get_operation_name = s_s3_meta_request_default_operation_name, }; /* Allocate a new default meta request. */ @@ -104,6 +107,10 @@ struct aws_s3_meta_request *aws_s3_meta_request_default_new( meta_request_default->content_length = (size_t)content_length; + 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); return &meta_request_default->base; @@ -399,3 +406,9 @@ static void s_s3_meta_request_default_request_finished( } /* END CRITICAL SECTION */ } + +static const char *s_s3_meta_request_default_operation_name(const struct aws_s3_meta_request *meta_request) { + struct aws_s3_meta_request_default *meta_request_default = meta_request->impl; + const struct aws_string *operation_name = meta_request_default->operation_name; + return operation_name ? aws_string_c_str(operation_name) : ""; +} diff --git a/source/s3_meta_request.c b/source/s3_meta_request.c index 12639aa31..2bdb9d5b1 100644 --- a/source/s3_meta_request.c +++ b/source/s3_meta_request.c @@ -1811,6 +1811,11 @@ void aws_s3_meta_request_result_setup( aws_byte_buf_init_copy( result->error_response_body, meta_request->allocator, &failed_request->send_data.response_body); } + + const char *operation_name = aws_s3_request_get_operation_name(failed_request); + if (operation_name[0] != '\0') { + result->error_response_operation_name = aws_string_new_from_c_str(meta_request->allocator, operation_name); + } } result->response_status = response_status; @@ -1830,6 +1835,8 @@ void aws_s3_meta_request_result_clean_up( aws_mem_release(meta_request->allocator, result->error_response_body); } + aws_string_destroy(result->error_response_operation_name); + AWS_ZERO_STRUCT(*result); } diff --git a/source/s3_request.c b/source/s3_request.c index d1f91f218..680403c9c 100644 --- a/source/s3_request.c +++ b/source/s3_request.c @@ -45,14 +45,7 @@ void aws_s3_request_setup_send_data(struct aws_s3_request *request, struct aws_h aws_s3_request_clean_up_send_data(request); request->send_data.message = message; - struct aws_s3_meta_request *meta_request = request->meta_request; - request->send_data.metrics = aws_s3_request_metrics_new(request->allocator, message); - if (!meta_request->vtable->get_request_type) { - request->send_data.metrics->req_resp_info_metrics.request_type = AWS_S3_REQUEST_TYPE_DEFAULT; - } else { - request->send_data.metrics->req_resp_info_metrics.request_type = - meta_request->vtable->get_request_type(request); - } + request->send_data.metrics = aws_s3_request_metrics_new(request->allocator, request, message); /* Start the timestamp */ aws_high_res_clock_get_ticks((uint64_t *)&request->send_data.metrics->time_metrics.start_timestamp_ns); @@ -128,6 +121,59 @@ static void s_s3_request_destroy(void *user_data) { aws_mem_release(request->allocator, request); } +enum aws_s3_request_type aws_s3_request_get_type(const struct aws_s3_request *request) { + if (!request->meta_request->vtable->get_request_type) { + return AWS_S3_REQUEST_TYPE_DEFAULT; + } else { + return request->meta_request->vtable->get_request_type(request); + } +} + +const char *aws_s3_request_get_operation_name(const struct aws_s3_request *request) { + /* Try to get name from type */ + enum aws_s3_request_type request_type = aws_s3_request_get_type(request); + const char *operation_name = aws_s3_request_type_operation_name(request_type); + if (operation_name[0] != '\0') { + return operation_name; + } + + /* Try to get name from meta-request */ + const struct aws_s3_meta_request *meta_request = request->meta_request; + if (meta_request->vtable->get_operation_name != NULL) { + operation_name = meta_request->vtable->get_operation_name(meta_request); + if (operation_name[0] != '\0') { + return operation_name; + } + } + + /* Name unknown */ + return ""; +} + +const char *aws_s3_request_type_operation_name(enum aws_s3_request_type type) { + switch (type) { + case AWS_S3_REQUEST_TYPE_HEAD_OBJECT: + return "HeadObject"; + case AWS_S3_REQUEST_TYPE_GET_OBJECT: + return "GetObject"; + case AWS_S3_REQUEST_TYPE_LIST_PARTS: + return "ListParts"; + case AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD: + return "CreateMultipartUpload"; + case AWS_S3_REQUEST_TYPE_UPLOAD_PART: + return "UploadPart"; + case AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD: + return "AbortMultipartUpload"; + case AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD: + return "CompleteMultipartUpload"; + case AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY: + return "UploadPartCopy"; + case AWS_S3_REQUEST_TYPE_COPY_OBJECT: + return "CopyObject"; + default: + return ""; + } +} static void s_s3_request_metrics_destroy(void *arg) { struct aws_s3_request_metrics *metrics = arg; @@ -138,6 +184,7 @@ static void s_s3_request_metrics_destroy(void *arg) { aws_string_destroy(metrics->req_resp_info_metrics.request_path_query); aws_string_destroy(metrics->req_resp_info_metrics.host_address); aws_string_destroy(metrics->req_resp_info_metrics.request_id); + aws_string_destroy(metrics->req_resp_info_metrics.operation_name); aws_string_destroy(metrics->crt_info_metrics.ip_address); aws_mem_release(metrics->allocator, metrics); @@ -145,7 +192,9 @@ static void s_s3_request_metrics_destroy(void *arg) { struct aws_s3_request_metrics *aws_s3_request_metrics_new( struct aws_allocator *allocator, - struct aws_http_message *message) { + const struct aws_s3_request *request, + const struct aws_http_message *message) { + struct aws_s3_request_metrics *metrics = aws_mem_calloc(allocator, 1, sizeof(struct aws_s3_request_metrics)); metrics->allocator = allocator; struct aws_byte_cursor out_path; @@ -166,6 +215,13 @@ struct aws_s3_request_metrics *aws_s3_request_metrics_new( metrics->req_resp_info_metrics.host_address = aws_string_new_from_cursor(allocator, &host_header_value); AWS_ASSERT(metrics->req_resp_info_metrics.host_address != NULL); + metrics->req_resp_info_metrics.request_type = aws_s3_request_get_type(request); + + const char *operation_name = aws_s3_request_get_operation_name(request); + if (operation_name[0] != '\0') { + metrics->req_resp_info_metrics.operation_name = aws_string_new_from_c_str(allocator, operation_name); + } + metrics->time_metrics.start_timestamp_ns = -1; metrics->time_metrics.end_timestamp_ns = -1; metrics->time_metrics.total_duration_ns = -1; @@ -384,6 +440,18 @@ int aws_s3_request_metrics_get_request_stream_id(const struct aws_s3_request_met return AWS_OP_SUCCESS; } +int aws_s3_request_metrics_get_operation_name( + const struct aws_s3_request_metrics *metrics, + const struct aws_string **out_operation_name) { + AWS_PRECONDITION(metrics); + AWS_PRECONDITION(out_operation_name); + if (metrics->req_resp_info_metrics.operation_name == NULL) { + return aws_raise_error(AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE); + } + *out_operation_name = metrics->req_resp_info_metrics.operation_name; + return AWS_OP_SUCCESS; +} + void aws_s3_request_metrics_get_request_type( const struct aws_s3_request_metrics *metrics, enum aws_s3_request_type *out_request_type) { diff --git a/tests/s3_data_plane_tests.c b/tests/s3_data_plane_tests.c index bcd03f293..fffaffae0 100644 --- a/tests/s3_data_plane_tests.c +++ b/tests/s3_data_plane_tests.c @@ -4043,6 +4043,11 @@ static int s_test_s3_error_missing_file(struct aws_allocator *allocator, void *c ASSERT_TRUE(meta_request_test_results.error_response_headers != NULL); + ASSERT_NOT_NULL(meta_request_test_results.error_response_operation_name); + ASSERT_TRUE( + aws_string_eq_c_str(meta_request_test_results.error_response_operation_name, "GetObject") || + aws_string_eq_c_str(meta_request_test_results.error_response_operation_name, "HeadObject")); + meta_request = aws_s3_meta_request_release(meta_request); aws_s3_tester_wait_for_meta_request_shutdown(&tester); @@ -5416,6 +5421,10 @@ static int s_test_s3_not_satisfiable_range(struct aws_allocator *allocator, void ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(&tester, &options, &results)); ASSERT_TRUE(results.finished_response_status == AWS_HTTP_STATUS_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE); + ASSERT_NOT_NULL(results.error_response_operation_name); + ASSERT_TRUE( + aws_string_eq_c_str(results.error_response_operation_name, "GetObject") || + aws_string_eq_c_str(results.error_response_operation_name, "HeadObject")); aws_s3_meta_request_test_results_clean_up(&results); @@ -6859,6 +6868,10 @@ static int s_test_s3_upload_review_rejection(struct aws_allocator *allocator, vo }; ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(&tester, &get_options, &test_results)); ASSERT_INT_EQUALS(AWS_HTTP_STATUS_CODE_404_NOT_FOUND, test_results.finished_response_status); + ASSERT_NOT_NULL(test_results.error_response_operation_name); + ASSERT_TRUE( + aws_string_eq_c_str(test_results.error_response_operation_name, "GetObject") || + aws_string_eq_c_str(test_results.error_response_operation_name, "HeadObject")); aws_s3_meta_request_test_results_clean_up(&test_results); aws_s3_client_release(client); diff --git a/tests/s3_mock_server_tests.c b/tests/s3_mock_server_tests.c index 47a538071..66e0d3913 100644 --- a/tests/s3_mock_server_tests.c +++ b/tests/s3_mock_server_tests.c @@ -85,6 +85,10 @@ static int s_validate_mpu_mock_server_metrics(struct aws_array_list *metrics_lis aws_s3_request_metrics_get_request_type(metrics, &request_type); ASSERT_UINT_EQUALS(AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, request_type); + const struct aws_string *operation_name = NULL; + ASSERT_SUCCESS(aws_s3_request_metrics_get_operation_name(metrics, &operation_name)); + ASSERT_STR_EQUALS("CreateMultipartUpload", aws_string_c_str(operation_name)); + /* Second metrics should be the Upload Part */ aws_array_list_get_at(metrics_list, (void **)&metrics, 1); struct aws_byte_cursor header_value; @@ -98,18 +102,24 @@ static int s_validate_mpu_mock_server_metrics(struct aws_array_list *metrics_lis request_type = 0; aws_s3_request_metrics_get_request_type(metrics, &request_type); ASSERT_UINT_EQUALS(AWS_S3_REQUEST_TYPE_UPLOAD_PART, request_type); + ASSERT_SUCCESS(aws_s3_request_metrics_get_operation_name(metrics, &operation_name)); + ASSERT_STR_EQUALS("UploadPart", aws_string_c_str(operation_name)); /* Third metrics still be Upload Part */ aws_array_list_get_at(metrics_list, (void **)&metrics, 2); request_type = 0; aws_s3_request_metrics_get_request_type(metrics, &request_type); ASSERT_UINT_EQUALS(AWS_S3_REQUEST_TYPE_UPLOAD_PART, request_type); + ASSERT_SUCCESS(aws_s3_request_metrics_get_operation_name(metrics, &operation_name)); + ASSERT_STR_EQUALS("UploadPart", aws_string_c_str(operation_name)); /* Fourth should be complete MPU */ aws_array_list_get_at(metrics_list, (void **)&metrics, 3); request_type = 0; aws_s3_request_metrics_get_request_type(metrics, &request_type); ASSERT_UINT_EQUALS(AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, request_type); + ASSERT_SUCCESS(aws_s3_request_metrics_get_operation_name(metrics, &operation_name)); + ASSERT_STR_EQUALS("CompleteMultipartUpload", aws_string_c_str(operation_name)); /* All the rest should be similar */ return AWS_OP_SUCCESS; @@ -321,6 +331,7 @@ TEST_CASE(async_access_denied_from_complete_multipart_mock_server) { ASSERT_UINT_EQUALS(AWS_ERROR_S3_NON_RECOVERABLE_ASYNC_ERROR, out_results.finished_error_code); ASSERT_UINT_EQUALS(AWS_S3_RESPONSE_STATUS_SUCCESS, out_results.finished_response_status); ASSERT_TRUE(out_results.error_response_body.len != 0); + ASSERT_STR_EQUALS("CompleteMultipartUpload", aws_string_c_str(out_results.error_response_operation_name)); aws_s3_meta_request_test_results_clean_up(&out_results); aws_s3_client_release(client); @@ -363,6 +374,7 @@ TEST_CASE(get_object_modified_mock_server) { ASSERT_UINT_EQUALS(AWS_ERROR_S3_OBJECT_MODIFIED, out_results.finished_error_code); ASSERT_UINT_EQUALS(AWS_HTTP_STATUS_CODE_412_PRECONDITION_FAILED, out_results.finished_response_status); + ASSERT_STR_EQUALS("GetObject", aws_string_c_str(out_results.error_response_operation_name)); aws_s3_meta_request_test_results_clean_up(&out_results); aws_s3_client_release(client); diff --git a/tests/s3_tester.c b/tests/s3_tester.c index a3425cf5f..7428cf4f0 100644 --- a/tests/s3_tester.c +++ b/tests/s3_tester.c @@ -171,6 +171,11 @@ static void s_s3_test_meta_request_finish( &meta_request_test_results->error_response_body, tester->allocator, result->error_response_body); } + if (result->error_response_operation_name != NULL) { + meta_request_test_results->error_response_operation_name = + aws_string_new_from_string(tester->allocator, result->error_response_operation_name); + } + meta_request_test_results->finished_response_status = result->response_status; meta_request_test_results->finished_error_code = result->error_code; @@ -496,6 +501,7 @@ void aws_s3_meta_request_test_results_clean_up(struct aws_s3_meta_request_test_r aws_http_headers_release(test_meta_request->error_response_headers); aws_byte_buf_clean_up(&test_meta_request->error_response_body); + aws_string_destroy(test_meta_request->error_response_operation_name); aws_http_headers_release(test_meta_request->response_headers); while (aws_array_list_length(&test_meta_request->synced_data.metrics) > 0) { struct aws_s3_request_metrics *metrics = NULL; @@ -1830,6 +1836,7 @@ int aws_s3_tester_validate_get_object_results( ASSERT_TRUE(meta_request_test_results->error_response_headers == NULL); ASSERT_TRUE(meta_request_test_results->error_response_body.len == 0); + ASSERT_NULL(meta_request_test_results->error_response_operation_name); struct aws_byte_cursor sse_byte_cursor; @@ -1967,6 +1974,7 @@ int aws_s3_tester_validate_put_object_results( ASSERT_TRUE(meta_request_test_results->error_response_headers == NULL); ASSERT_TRUE(meta_request_test_results->error_response_body.len == 0); + ASSERT_NULL(meta_request_test_results->error_response_operation_name); struct aws_byte_cursor etag_byte_cursor; AWS_ZERO_STRUCT(etag_byte_cursor); diff --git a/tests/s3_tester.h b/tests/s3_tester.h index c35462f62..66ab52435 100644 --- a/tests/s3_tester.h +++ b/tests/s3_tester.h @@ -222,6 +222,7 @@ struct aws_s3_meta_request_test_results { struct aws_http_headers *error_response_headers; struct aws_byte_buf error_response_body; + struct aws_string *error_response_operation_name; size_t part_size; int headers_response_status; From c44f70e53c331a3735c01603ab0c701963a364e8 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 21 Nov 2023 17:06:15 -0800 Subject: [PATCH 02/13] test that operation_name from DEFAULT meta-request carries through. also, whoopsie fix memory leak --- source/s3_default_meta_request.c | 1 + tests/CMakeLists.txt | 1 + tests/s3_data_plane_tests.c | 36 ++++++++++++++++++++++++++++++++ tests/s3_tester.c | 1 + tests/s3_tester.h | 1 + 5 files changed, 40 insertions(+) diff --git a/source/s3_default_meta_request.c b/source/s3_default_meta_request.c index 38dc24d86..9b8a06300 100644 --- a/source/s3_default_meta_request.c +++ b/source/s3_default_meta_request.c @@ -121,6 +121,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); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ec59e1285..88f624f8c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -159,6 +159,7 @@ add_net_test_case(test_s3_get_object_invoke_headers_callback_on_error) add_net_test_case(test_s3_put_object_invoke_headers_callback_on_error) add_net_test_case(test_s3_put_object_invoke_headers_callback_on_error_with_user_cancellation) add_net_test_case(test_s3_default_fail_body_callback) +add_net_test_case(test_s3_default_fail_operation_name) add_net_test_case(test_s3_error_missing_file) add_net_test_case(test_s3_existing_host_entry) add_net_test_case(test_s3_put_fail_object_invalid_request) diff --git a/tests/s3_data_plane_tests.c b/tests/s3_data_plane_tests.c index fffaffae0..7cc460936 100644 --- a/tests/s3_data_plane_tests.c +++ b/tests/s3_data_plane_tests.c @@ -4582,6 +4582,42 @@ static int s_test_s3_default_fail_body_callback(struct aws_allocator *allocator, return 0; } +/* Test that if a DEFAULt meta-request sets the operation_name, and gets an error response, + * then aws_s3_meta_request_result.error_response_operation_name is set. */ +AWS_TEST_CASE(test_s3_default_fail_operation_name, s_test_s3_default_fail_operation_name) +static int s_test_s3_default_fail_operation_name(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + struct aws_s3_meta_request_test_results meta_request_test_results; + aws_s3_meta_request_test_results_init(&meta_request_test_results, allocator); + + struct aws_byte_cursor invalid_path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("___INVALID_PATH___"); + + struct aws_s3_tester_meta_request_options options = { + .allocator = allocator, + .meta_request_type = AWS_S3_META_REQUEST_TYPE_DEFAULT, + + .validate_type = AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_FAILURE, + .default_type_options = + { + .mode = AWS_S3_TESTER_DEFAULT_TYPE_MODE_GET, + .operation_name = aws_byte_cursor_from_c_str("GetObject"), + }, + .get_options = + { + .object_path = invalid_path, + }, + }; + + ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(NULL, &options, &meta_request_test_results)); + ASSERT_TRUE(meta_request_test_results.finished_error_code == AWS_ERROR_S3_INVALID_RESPONSE_STATUS); + ASSERT_STR_EQUALS("GetObject", aws_string_c_str(meta_request_test_results.error_response_operation_name)); + + aws_s3_meta_request_test_results_clean_up(&meta_request_test_results); + + return 0; +} + AWS_TEST_CASE(test_s3_put_fail_object_invalid_request, s_test_s3_put_fail_object_invalid_request) static int s_test_s3_put_fail_object_invalid_request(struct aws_allocator *allocator, void *ctx) { (void)ctx; diff --git a/tests/s3_tester.c b/tests/s3_tester.c index 7428cf4f0..cb8b9afa6 100644 --- a/tests/s3_tester.c +++ b/tests/s3_tester.c @@ -1402,6 +1402,7 @@ int aws_s3_tester_send_meta_request_with_options( struct aws_s3_meta_request_options meta_request_options = { .type = options->meta_request_type, + .operation_name = options->default_type_options.operation_name, .message = options->message, .checksum_config = &checksum_config, .resume_token = options->put_options.resume_token, diff --git a/tests/s3_tester.h b/tests/s3_tester.h index 66ab52435..624e797b4 100644 --- a/tests/s3_tester.h +++ b/tests/s3_tester.h @@ -169,6 +169,7 @@ struct aws_s3_tester_meta_request_options { /* Default Meta Request specific options. */ struct { enum aws_s3_tester_default_type_mode mode; + struct aws_byte_cursor operation_name; } default_type_options; /* Get Object Meta Request specific options.*/ From ceb4cf090456c54373d9a2f7a74e0376235bcf78 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 21 Nov 2023 22:48:03 -0800 Subject: [PATCH 03/13] Directly declare request_type and operation_name, instead of getting them via vtable calls. In my opinion, the previous approach was complicated, hard to use, and easy to mess up. I didn't realize we weren't handling the case where singlepart operations use DEFAULT request type under the hood. Now our code MUST declare request-type and operation-name up front. It's obvious. It works. Yay. --- .../aws/s3/private/s3_default_meta_request.h | 19 +++++- include/aws/s3/private/s3_meta_request_impl.h | 11 ---- include/aws/s3/private/s3_request.h | 14 +++- include/aws/s3/s3_client.h | 22 ++----- source/s3_auto_ranged_get.c | 31 ++++----- source/s3_auto_ranged_put.c | 42 +++++------- source/s3_client.c | 20 +++++- source/s3_copy_object.c | 47 +++++-------- source/s3_default_meta_request.c | 19 +++++- source/s3_meta_request.c | 14 ++-- source/s3_request.c | 66 +++---------------- tests/s3_data_plane_tests.c | 45 +++++++++---- tests/s3_mock_server_tests.c | 1 + 13 files changed, 167 insertions(+), 184 deletions(-) diff --git a/include/aws/s3/private/s3_default_meta_request.h b/include/aws/s3/private/s3_default_meta_request.h index 2b16214bc..b519fd597 100644 --- a/include/aws/s3/private/s3_default_meta_request.h +++ b/include/aws/s3/private/s3_default_meta_request.h @@ -15,6 +15,10 @@ struct aws_s3_meta_request_default { size_t content_length; + /* Actual type for the single request (AWS_S3_REQUEST_TYPE_DEFAULT if unknown) */ + enum aws_s3_request_type request_type; + + /* S3 operation name for the single request (NULL if unknown) */ struct aws_string *operation_name; /* Members to only be used when the mutex in the base type is locked. */ @@ -28,10 +32,23 @@ struct aws_s3_meta_request_default { } synced_data; }; -/* Creates a new default meta request. This will send the request as is and pass back the response. */ +/* Creates a new default meta request. This will send the request as is and pass back the response. + * + * Sometimes, a default meta-request is used for other aws_s3_meta_request_types. + * For example, if the request is simple (e.g. single part upload or download), + * or if there's a header that's too complex to deal with. + * In these cases, request_type and operation_name_override should be set. + * + * But if the user literally asked for a AWS_S3_META_REQUEST_TYPE_DEFAULT, + * the request_type should be AWS_S3_META_REQUEST_TYPE_DEFAULT and + * operation_name_override should be NULL (options->operation_name will be used + * if it is set). + */ 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, + const char *operation_name_override, uint64_t content_length, bool should_compute_content_md5, const struct aws_s3_meta_request_options *options); diff --git a/include/aws/s3/private/s3_meta_request_impl.h b/include/aws/s3/private/s3_meta_request_impl.h index 0a603c26b..2a44606dd 100644 --- a/include/aws/s3/private/s3_meta_request_impl.h +++ b/include/aws/s3/private/s3_meta_request_impl.h @@ -117,17 +117,6 @@ struct aws_s3_meta_request_vtable { /* Pause the given request */ int (*pause)(struct aws_s3_meta_request *meta_request, struct aws_s3_meta_request_resume_token **resume_token); - - /* Get the type of the aws_s3_request. - * Not implemented for DEFAULT type, which doesn't know its aws_s3_request_type enum value */ - enum aws_s3_request_type (*get_request_type)(const struct aws_s3_request *request); - - /* Get the S3 operation name for the meta-request. - * This is only implemented for DEFAULT type, which doesn't know its - * aws_s3_request_type enum value, but might know its operation name. - * Returns empty string if the name isn't known. - * Note that this C-string's lifetime is tied to the meta-request. */ - const char *(*get_operation_name)(const struct aws_s3_meta_request *meta_request); }; /** diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index 5e85b77b0..a99040c4a 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -160,6 +160,12 @@ struct aws_s3_request { /* TODO: this should be a union type to make it clear that this could be one of two enums for puts, and gets. */ int request_tag; + /* Actual S3 type for the single request (AWS_S3_REQUEST_TYPE_DEFAULT if unknown) */ + enum aws_s3_request_type request_type; + + /* S3 operation name for the single request (e.g. "CompleteMultipartUpload") (empty string if unknown) */ + const char *operation_name; + /* Members of this structure will be repopulated each time the request is sent. If the request fails, and needs to * be retried, then the members of this structure will be cleaned up and re-populated on the next send. */ @@ -221,11 +227,17 @@ struct aws_s3_request { AWS_EXTERN_C_BEGIN -/* Create a new s3 request structure with the given options. */ +/* Create a new s3 request structure with the given options. + * @param operation_name Official S3 operation name (e.g. "CreateMultipartUpload"). + * Pass an empty string if unknown. + * The string's memory must outlive the request (static string, or live on meta_request) + */ AWS_S3_API struct aws_s3_request *aws_s3_request_new( struct aws_s3_meta_request *meta_request, int request_tag, + enum aws_s3_request_type request_type, + const char *operation_name, uint32_t part_number, uint32_t flags); diff --git a/include/aws/s3/s3_client.h b/include/aws/s3/s3_client.h index 327506d10..d08786934 100644 --- a/include/aws/s3/s3_client.h +++ b/include/aws/s3/s3_client.h @@ -86,9 +86,6 @@ enum aws_s3_meta_request_type { /** * The type of S3 request made. Used by metrics. - * aws_s3_request_type_operation_name() returns the S3 operation name - * for types that map (e.g. AWS_S3_REQUEST_TYPE_HEAD_OBJECT -> "HeadObject"), - * or empty string for types that don't map (e.g. AWS_S3_REQUEST_TYPE_DEFAULT -> ""). */ enum aws_s3_request_type { /* Same as the original HTTP request passed to aws_s3_meta_request_options */ @@ -98,6 +95,7 @@ enum aws_s3_request_type { AWS_S3_REQUEST_TYPE_HEAD_OBJECT, AWS_S3_REQUEST_TYPE_GET_OBJECT, AWS_S3_REQUEST_TYPE_LIST_PARTS, + AWS_S3_REQUEST_TYPE_PUT_OBJECT, AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_UPLOAD_PART, AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD, @@ -625,8 +623,8 @@ struct aws_s3_meta_request_result { /* If meta request failed due to an HTTP error response from S3, * this is the name of the S3 operation it was responding to. - * For example, if a AWS_S3_META_REQUEST_TYPE_PUT_OBJECT fails, this could be - * "CreateMultipartUpload", "UploadPart", "CompleteMultipartUpload", or others. + * For example, if a AWS_S3_META_REQUEST_TYPE_PUT_OBJECT fails this could be + * "PutObject, "CreateMultipartUpload", "UploadPart", "CompleteMultipartUpload", or others. * For AWS_S3_META_REQUEST_TYPE_DEFAULT, this is the same value passed to * aws_s3_meta_request_options.operation_name. * NULL if the meta request failed for another reason, or the operation name is not known. */ @@ -847,17 +845,6 @@ void aws_s3_init_default_signing_config( const struct aws_byte_cursor region, struct aws_credentials_provider *credentials_provider); -/** - * Return operation name for aws_s3_request_type, - * or empty string if the type doesn't map to an actual operation. - * For example: - * AWS_S3_REQUEST_TYPE_HEAD_OBJECT -> "HeadObject" - * AWS_S3_REQUEST_TYPE_DEFAULT -> "" - * AWS_S3_REQUEST_TYPE_MAX -> "" - */ -AWS_S3_API -const char *aws_s3_request_type_operation_name(enum aws_s3_request_type type); - /** * Add a reference, keeping this object alive. * The reference must be released when you are done with it, or it's memory will never be cleaned up. @@ -1020,7 +1007,8 @@ int aws_s3_request_metrics_get_operation_name( const struct aws_s3_request_metrics *metrics, const struct aws_string **out_operation_name); -/* Get the request type from request metrics. */ +/* Get the request type from request metrics. + * If you just need a string, aws_s3_request_metrics_get_operation_name() is more reliable. */ AWS_S3_API void aws_s3_request_metrics_get_request_type( const struct aws_s3_request_metrics *metrics, diff --git a/source/s3_auto_ranged_get.c b/source/s3_auto_ranged_get.c index ce881bc2d..aee8b9fd1 100644 --- a/source/s3_auto_ranged_get.c +++ b/source/s3_auto_ranged_get.c @@ -28,8 +28,6 @@ static void s_s3_auto_ranged_get_request_finished( struct aws_s3_request *request, int error_code); -static enum aws_s3_request_type s_s3_auto_ranged_get_request_type(const struct aws_s3_request *request); - static struct aws_s3_meta_request_vtable s_s3_auto_ranged_get_vtable = { .update = s_s3_auto_ranged_get_update, .send_request_finish = aws_s3_meta_request_send_request_finish_default, @@ -39,21 +37,8 @@ static struct aws_s3_meta_request_vtable s_s3_auto_ranged_get_vtable = { .finished_request = s_s3_auto_ranged_get_request_finished, .destroy = s_s3_meta_request_auto_ranged_get_destroy, .finish = aws_s3_meta_request_finish_default, - .get_request_type = s_s3_auto_ranged_get_request_type, }; -static enum aws_s3_request_type s_s3_auto_ranged_get_request_type(const struct aws_s3_request *request) { - switch (request->request_tag) { - case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_HEAD_OBJECT: - return AWS_S3_REQUEST_TYPE_HEAD_OBJECT; - case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART: - case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_INITIAL_MESSAGE: - return AWS_S3_REQUEST_TYPE_GET_OBJECT; - } - AWS_ASSERT(false); - return AWS_S3_REQUEST_TYPE_MAX; -} - static int s_s3_auto_ranged_get_success_status(struct aws_s3_meta_request *meta_request) { AWS_PRECONDITION(meta_request); @@ -176,7 +161,9 @@ static bool s_s3_auto_ranged_get_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_HEAD_OBJECT, - 0, + AWS_S3_REQUEST_TYPE_HEAD_OBJECT, + "HeadObject", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); request->discovers_object_size = true; @@ -197,7 +184,9 @@ static bool s_s3_auto_ranged_get_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART, - 1, + AWS_S3_REQUEST_TYPE_UPLOAD_PART, + "UploadPart", + 1 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_PART_SIZE_RESPONSE_BODY); request->ticket = ticket; @@ -223,7 +212,9 @@ static bool s_s3_auto_ranged_get_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_INITIAL_MESSAGE, - 0, + AWS_S3_REQUEST_TYPE_GET_OBJECT, + "GetObject", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); auto_ranged_get->synced_data.get_without_range_sent = true; @@ -272,7 +263,9 @@ static bool s_s3_auto_ranged_get_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART, - auto_ranged_get->synced_data.num_parts_requested + 1, + AWS_S3_REQUEST_TYPE_GET_OBJECT, + "GetObject", + auto_ranged_get->synced_data.num_parts_requested + 1 /*part_number*/, AWS_S3_REQUEST_FLAG_PART_SIZE_RESPONSE_BODY); request->ticket = ticket; diff --git a/source/s3_auto_ranged_put.c b/source/s3_auto_ranged_put.c index 4384fed3e..ce078df52 100644 --- a/source/s3_auto_ranged_put.c +++ b/source/s3_auto_ranged_put.c @@ -294,23 +294,6 @@ static int s_try_init_resume_state_from_persisted_data( return AWS_OP_SUCCESS; } -static enum aws_s3_request_type s_s3_auto_ranged_put_request_type(const struct aws_s3_request *request) { - switch (request->request_tag) { - case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_LIST_PARTS: - return AWS_S3_REQUEST_TYPE_LIST_PARTS; - case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD: - return AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD; - case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_PART: - return AWS_S3_REQUEST_TYPE_UPLOAD_PART; - case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD: - return AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD; - case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD: - return AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD; - } - AWS_ASSERT(false); - return AWS_S3_REQUEST_TYPE_MAX; -} - static struct aws_s3_meta_request_vtable s_s3_auto_ranged_put_vtable = { .update = s_s3_auto_ranged_put_update, .send_request_finish = s_s3_auto_ranged_put_send_request_finish, @@ -321,7 +304,6 @@ static struct aws_s3_meta_request_vtable s_s3_auto_ranged_put_vtable = { .destroy = s_s3_meta_request_auto_ranged_put_destroy, .finish = aws_s3_meta_request_finish_default, .pause = s_s3_auto_ranged_put_pause, - .get_request_type = s_s3_auto_ranged_put_request_type, }; /* Allocate a new auto-ranged put meta request */ @@ -480,7 +462,9 @@ static bool s_s3_auto_ranged_put_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_LIST_PARTS, - 0, + AWS_S3_REQUEST_TYPE_LIST_PARTS, + "ListParts", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); auto_ranged_put->synced_data.list_parts_state.started = true; @@ -494,7 +478,9 @@ static bool s_s3_auto_ranged_put_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_LIST_PARTS, - 0, + AWS_S3_REQUEST_TYPE_LIST_PARTS, + "ListParts", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); auto_ranged_put->synced_data.list_parts_state.continues = false; goto has_work_remaining; @@ -510,7 +496,9 @@ static bool s_s3_auto_ranged_put_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD, - 0, + AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, + "CreateMultipartUpload", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); auto_ranged_put->synced_data.create_multipart_upload_sent = true; @@ -564,7 +552,9 @@ static bool s_s3_auto_ranged_put_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_PART, - 0, + AWS_S3_REQUEST_TYPE_UPLOAD_PART, + "UploadPart", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_PART_SIZE_REQUEST_BODY); request->part_number = auto_ranged_put->threaded_update_data.next_part_number; @@ -610,7 +600,9 @@ static bool s_s3_auto_ranged_put_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD, - 0, + AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, + "CompleteMultipartUpload", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); auto_ranged_put->synced_data.complete_multipart_upload_sent = true; @@ -675,7 +667,9 @@ static bool s_s3_auto_ranged_put_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD, - 0, + AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD, + "AbortMultipartUpload", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_ALWAYS_SEND); auto_ranged_put->synced_data.abort_multipart_upload_sent = true; diff --git a/source/s3_client.c b/source/s3_client.c index 0d071c212..38cf7df8d 100644 --- a/source/s3_client.c +++ b/source/s3_client.c @@ -1043,7 +1043,14 @@ static struct aws_s3_meta_request *s_s3_client_meta_request_factory_default( * TODO: Still need tests to verify that the request of a part is * splittable or not */ if (aws_http_headers_has(initial_message_headers, aws_byte_cursor_from_c_str("partNumber"))) { - return aws_s3_meta_request_default_new(client->allocator, client, content_length, false, options); + return aws_s3_meta_request_default_new( + client->allocator, + client, + AWS_S3_REQUEST_TYPE_GET_OBJECT, + "GetObject", + content_length, + false /*should_compute_content_md5*/, + options); } return aws_s3_meta_request_auto_ranged_get_new(client->allocator, client, client->part_size, options); @@ -1092,6 +1099,8 @@ static struct aws_s3_meta_request *s_s3_client_meta_request_factory_default( return aws_s3_meta_request_default_new( client->allocator, client, + AWS_S3_REQUEST_TYPE_PUT_OBJECT, + "PutObject", content_length, client->compute_content_md5 == AWS_MR_CONTENT_MD5_ENABLED && !aws_http_headers_has(initial_message_headers, g_content_md5_header_name), @@ -1138,7 +1147,14 @@ static struct aws_s3_meta_request *s_s3_client_meta_request_factory_default( return aws_s3_meta_request_copy_object_new(client->allocator, client, options); } case AWS_S3_META_REQUEST_TYPE_DEFAULT: - return aws_s3_meta_request_default_new(client->allocator, client, content_length, false, options); + return aws_s3_meta_request_default_new( + client->allocator, + client, + AWS_S3_REQUEST_TYPE_DEFAULT, + NULL /*operation_name_override*/, + content_length, + false /*should_compute_content_md5*/, + options); default: AWS_FATAL_ASSERT(false); } diff --git a/source/s3_copy_object.c b/source/s3_copy_object.c index 0e87f98c6..4bdf5588e 100644 --- a/source/s3_copy_object.c +++ b/source/s3_copy_object.c @@ -37,26 +37,6 @@ static void s_s3_copy_object_request_finished( struct aws_s3_request *request, int error_code); -static enum aws_s3_request_type s_s3_copy_object_request_type(const struct aws_s3_request *request) { - switch (request->request_tag) { - case AWS_S3_COPY_OBJECT_REQUEST_TAG_GET_OBJECT_SIZE: - /* It's a HEAD request of GetObject call */ - return AWS_S3_REQUEST_TYPE_HEAD_OBJECT; - case AWS_S3_COPY_OBJECT_REQUEST_TAG_BYPASS: - return AWS_S3_REQUEST_TYPE_COPY_OBJECT; - case AWS_S3_COPY_OBJECT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD: - return AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD; - case AWS_S3_COPY_OBJECT_REQUEST_TAG_MULTIPART_COPY: - return AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY; - case AWS_S3_COPY_OBJECT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD: - return AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD; - case AWS_S3_COPY_OBJECT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD: - return AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD; - } - AWS_ASSERT(false); - return AWS_S3_REQUEST_TYPE_MAX; -} - static struct aws_s3_meta_request_vtable s_s3_copy_object_vtable = { .update = s_s3_copy_object_update, .send_request_finish = aws_s3_meta_request_send_request_finish_default, @@ -66,7 +46,6 @@ static struct aws_s3_meta_request_vtable s_s3_copy_object_vtable = { .finished_request = s_s3_copy_object_request_finished, .destroy = s_s3_meta_request_copy_object_destroy, .finish = aws_s3_meta_request_finish_default, - .get_request_type = s_s3_copy_object_request_type, }; /* Allocate a new copy object meta request */ @@ -157,7 +136,9 @@ static bool s_s3_copy_object_update( request = aws_s3_request_new( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_GET_OBJECT_SIZE, - 0, + AWS_S3_REQUEST_TYPE_HEAD_OBJECT, + "HeadObject", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); copy_object->synced_data.head_object_sent = true; @@ -176,7 +157,9 @@ static bool s_s3_copy_object_update( request = aws_s3_request_new( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_BYPASS, - 1, + AWS_S3_REQUEST_TYPE_COPY_OBJECT, + "CopyObject", + 1 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); AWS_LOGF_DEBUG( @@ -203,7 +186,9 @@ static bool s_s3_copy_object_update( request = aws_s3_request_new( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD, - 0, + AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, + "CreateMultipartUpload", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); copy_object->synced_data.create_multipart_upload_sent = true; @@ -233,11 +218,11 @@ static bool s_s3_copy_object_update( request = aws_s3_request_new( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_MULTIPART_COPY, - 0, + AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY, + "UploadPartCopy", + copy_object->threaded_update_data.next_part_number, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); - request->part_number = copy_object->threaded_update_data.next_part_number; - ++copy_object->threaded_update_data.next_part_number; ++copy_object->synced_data.num_parts_sent; @@ -262,7 +247,9 @@ static bool s_s3_copy_object_update( request = aws_s3_request_new( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD, - 0, + AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, + "CompleteMultipartUpload", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); copy_object->synced_data.complete_multipart_upload_sent = true; @@ -315,7 +302,9 @@ static bool s_s3_copy_object_update( request = aws_s3_request_new( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD, - 0, + AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD, + "AbortMultipartUpload", + 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_ALWAYS_SEND); copy_object->synced_data.abort_multipart_upload_sent = true; diff --git a/source/s3_default_meta_request.c b/source/s3_default_meta_request.c index 9b8a06300..52159d53b 100644 --- a/source/s3_default_meta_request.c +++ b/source/s3_default_meta_request.c @@ -54,11 +54,15 @@ 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, + const char *operation_name_override, 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(operation_name_override == NULL || operation_name_override[0] != '\0'); /* NULL or non-empty */ AWS_PRECONDITION(options); AWS_PRECONDITION(options->message); @@ -106,6 +110,13 @@ 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; + + if (operation_name_override != NULL) { + meta_request_default->operation_name = aws_string_new_from_c_str(allocator, operation_name_override); + } else if (options->operation_name.len != 0) { + meta_request_default->operation_name = aws_string_new_from_cursor(allocator, &options->operation_name); + } if (options->operation_name.len != 0) { meta_request_default->operation_name = aws_string_new_from_cursor(allocator, &options->operation_name); @@ -151,7 +162,13 @@ 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*/, + AWS_S3_REQUEST_TYPE_DEFAULT, + meta_request_default->operation_name ? aws_string_c_str(meta_request_default->operation_name) : "", + 1 /*part_number*/, + AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); AWS_LOGF_DEBUG( AWS_LS_S3_META_REQUEST, diff --git a/source/s3_meta_request.c b/source/s3_meta_request.c index 2bdb9d5b1..b7d9d5e78 100644 --- a/source/s3_meta_request.c +++ b/source/s3_meta_request.c @@ -847,12 +847,6 @@ static void s_s3_meta_request_request_on_signed( s_s3_prepare_request_payload_callback_and_destroy(payload, error_code); } -static bool s_s3_request_is_upload_part(struct aws_s3_request *request) { - struct aws_s3_meta_request *meta_request = request->meta_request; - return meta_request->type == AWS_S3_META_REQUEST_TYPE_PUT_OBJECT && meta_request->vtable->get_request_type && - meta_request->vtable->get_request_type(request) == AWS_S3_REQUEST_TYPE_UPLOAD_PART; -} - void aws_s3_meta_request_send_request(struct aws_s3_meta_request *meta_request, struct aws_s3_connection *connection) { AWS_PRECONDITION(meta_request); AWS_PRECONDITION(connection); @@ -875,7 +869,7 @@ void aws_s3_meta_request_send_request(struct aws_s3_meta_request *meta_request, options.on_metrics = s_s3_meta_request_stream_metrics; } options.on_complete = s_s3_meta_request_stream_complete; - if (s_s3_request_is_upload_part(request)) { + if (request->request_type == AWS_S3_REQUEST_TYPE_UPLOAD_PART) { options.response_first_byte_timeout_ms = aws_atomic_load_int(&meta_request->client->upload_timeout_ms); request->upload_timeout_ms = (size_t)options.response_first_byte_timeout_ms; } @@ -1812,9 +1806,9 @@ void aws_s3_meta_request_result_setup( result->error_response_body, meta_request->allocator, &failed_request->send_data.response_body); } - const char *operation_name = aws_s3_request_get_operation_name(failed_request); - if (operation_name[0] != '\0') { - result->error_response_operation_name = aws_string_new_from_c_str(meta_request->allocator, operation_name); + if (failed_request->operation_name[0] != '\0') { + result->error_response_operation_name = + aws_string_new_from_c_str(meta_request->allocator, failed_request->operation_name); } } diff --git a/source/s3_request.c b/source/s3_request.c index 680403c9c..093b21754 100644 --- a/source/s3_request.c +++ b/source/s3_request.c @@ -16,10 +16,14 @@ static void s_s3_request_destroy(void *user_data); struct aws_s3_request *aws_s3_request_new( struct aws_s3_meta_request *meta_request, int request_tag, + enum aws_s3_request_type request_type, + const char *operation_name, uint32_t part_number, uint32_t flags) { + AWS_PRECONDITION(meta_request); AWS_PRECONDITION(meta_request->allocator); + AWS_PRECONDITION(operation_name); struct aws_s3_request *request = aws_mem_calloc(meta_request->allocator, 1, sizeof(struct aws_s3_request)); @@ -29,6 +33,8 @@ struct aws_s3_request *aws_s3_request_new( request->meta_request = aws_s3_meta_request_acquire(meta_request); request->request_tag = request_tag; + request->request_type = request_type; + request->operation_name = operation_name; request->part_number = part_number; request->record_response_headers = (flags & AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS) != 0; request->has_part_size_response_body = (flags & AWS_S3_REQUEST_FLAG_PART_SIZE_RESPONSE_BODY) != 0; @@ -121,59 +127,6 @@ static void s_s3_request_destroy(void *user_data) { aws_mem_release(request->allocator, request); } -enum aws_s3_request_type aws_s3_request_get_type(const struct aws_s3_request *request) { - if (!request->meta_request->vtable->get_request_type) { - return AWS_S3_REQUEST_TYPE_DEFAULT; - } else { - return request->meta_request->vtable->get_request_type(request); - } -} - -const char *aws_s3_request_get_operation_name(const struct aws_s3_request *request) { - /* Try to get name from type */ - enum aws_s3_request_type request_type = aws_s3_request_get_type(request); - const char *operation_name = aws_s3_request_type_operation_name(request_type); - if (operation_name[0] != '\0') { - return operation_name; - } - - /* Try to get name from meta-request */ - const struct aws_s3_meta_request *meta_request = request->meta_request; - if (meta_request->vtable->get_operation_name != NULL) { - operation_name = meta_request->vtable->get_operation_name(meta_request); - if (operation_name[0] != '\0') { - return operation_name; - } - } - - /* Name unknown */ - return ""; -} - -const char *aws_s3_request_type_operation_name(enum aws_s3_request_type type) { - switch (type) { - case AWS_S3_REQUEST_TYPE_HEAD_OBJECT: - return "HeadObject"; - case AWS_S3_REQUEST_TYPE_GET_OBJECT: - return "GetObject"; - case AWS_S3_REQUEST_TYPE_LIST_PARTS: - return "ListParts"; - case AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD: - return "CreateMultipartUpload"; - case AWS_S3_REQUEST_TYPE_UPLOAD_PART: - return "UploadPart"; - case AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD: - return "AbortMultipartUpload"; - case AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD: - return "CompleteMultipartUpload"; - case AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY: - return "UploadPartCopy"; - case AWS_S3_REQUEST_TYPE_COPY_OBJECT: - return "CopyObject"; - default: - return ""; - } -} static void s_s3_request_metrics_destroy(void *arg) { struct aws_s3_request_metrics *metrics = arg; @@ -215,11 +168,10 @@ struct aws_s3_request_metrics *aws_s3_request_metrics_new( metrics->req_resp_info_metrics.host_address = aws_string_new_from_cursor(allocator, &host_header_value); AWS_ASSERT(metrics->req_resp_info_metrics.host_address != NULL); - metrics->req_resp_info_metrics.request_type = aws_s3_request_get_type(request); + metrics->req_resp_info_metrics.request_type = request->request_type; - const char *operation_name = aws_s3_request_get_operation_name(request); - if (operation_name[0] != '\0') { - metrics->req_resp_info_metrics.operation_name = aws_string_new_from_c_str(allocator, operation_name); + if (request->operation_name[0] != '\0') { + metrics->req_resp_info_metrics.operation_name = aws_string_new_from_c_str(allocator, request->operation_name); } metrics->time_metrics.start_timestamp_ns = -1; diff --git a/tests/s3_data_plane_tests.c b/tests/s3_data_plane_tests.c index 7cc460936..c7e29f2ae 100644 --- a/tests/s3_data_plane_tests.c +++ b/tests/s3_data_plane_tests.c @@ -368,6 +368,8 @@ static int s_test_s3_request_create_destroy(struct aws_allocator *allocator, voi (void)ctx; const int request_tag = 1234; + const enum aws_s3_request_type request_type = (enum aws_s3_request_type)9876; + const char *operation_name = "BlibbityBlob"; const uint32_t part_number = 5678; struct aws_s3_tester tester; @@ -384,14 +386,21 @@ static int s_test_s3_request_create_destroy(struct aws_allocator *allocator, voi struct aws_http_message *request_message = aws_s3_tester_dummy_http_request_new(&tester); ASSERT_TRUE(request_message != NULL); - struct aws_s3_request *request = - aws_s3_request_new(meta_request, request_tag, part_number, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); + struct aws_s3_request *request = aws_s3_request_new( + meta_request, + request_tag, + request_type, + operation_name, + part_number, + AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); ASSERT_TRUE(request != NULL); ASSERT_TRUE(request->meta_request == meta_request); ASSERT_TRUE(request->part_number == part_number); ASSERT_TRUE(request->request_tag == request_tag); + ASSERT_TRUE(request->request_type == request_type); + ASSERT_STR_EQUALS(operation_name, request->operation_name); ASSERT_TRUE(request->record_response_headers == true); aws_s3_request_setup_send_data(request, request_message); @@ -493,7 +502,8 @@ static int s_test_s3_meta_request_body_streaming(struct aws_allocator *allocator /* Queue the first range of parts in order. Each part should be flushed one-by-one. */ { for (uint32_t part_number = part_range0_start; part_number <= part_range0_end; ++part_number) { - struct aws_s3_request *request = aws_s3_request_new(meta_request, 0, part_number, 0); + struct aws_s3_request *request = aws_s3_request_new( + meta_request, 0 /*request_tag*/, AWS_S3_REQUEST_TYPE_GET_OBJECT, "GetObject", part_number, 0 /*flags*/); aws_s3_get_part_range( 0ULL, @@ -529,7 +539,8 @@ static int s_test_s3_meta_request_body_streaming(struct aws_allocator *allocator ASSERT_TRUE(part_range1_start != part_range1_end); for (uint32_t part_number = part_range1_start + 1; part_number <= part_range1_end; ++part_number) { - struct aws_s3_request *request = aws_s3_request_new(meta_request, 0, part_number, 0); + struct aws_s3_request *request = aws_s3_request_new( + meta_request, 0 /*request_tag*/, AWS_S3_REQUEST_TYPE_GET_OBJECT, "GetObject", part_number, 0 /*flags*/); aws_s3_get_part_range( 0ULL, @@ -557,7 +568,13 @@ static int s_test_s3_meta_request_body_streaming(struct aws_allocator *allocator /* Stream the last part of the body, which should flush the priority queue. */ { - struct aws_s3_request *request = aws_s3_request_new(meta_request, 0, part_range1_start, 0); + struct aws_s3_request *request = aws_s3_request_new( + meta_request, + 0 /*request_tag*/, + AWS_S3_REQUEST_TYPE_GET_OBJECT, + "GetObject", + part_range1_start, + 0 /*flags*/); aws_s3_get_part_range( 0ULL, @@ -607,15 +624,15 @@ static int s_test_s3_client_queue_requests(struct aws_allocator *allocator, void struct aws_s3_meta_request *mock_meta_request = aws_s3_tester_mock_meta_request_new(&tester); mock_meta_request->client = aws_s3_client_acquire(mock_client); - struct aws_s3_request *pivot_request = aws_s3_request_new(mock_meta_request, 0, 0, 0); + struct aws_s3_request *pivot_request = aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0); struct aws_linked_list pivot_request_list; aws_linked_list_init(&pivot_request_list); struct aws_s3_request *requests[] = { - aws_s3_request_new(mock_meta_request, 0, 0, 0), - aws_s3_request_new(mock_meta_request, 0, 0, 0), - aws_s3_request_new(mock_meta_request, 0, 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0), }; const uint32_t num_requests = AWS_ARRAY_SIZE(requests); @@ -728,7 +745,7 @@ static bool s_s3_test_work_meta_request_update( if (out_request) { if (user_data->has_work_remaining) { - *out_request = aws_s3_request_new(meta_request, 0, 0, 0); + *out_request = aws_s3_request_new(meta_request, 0, 0, "", 0, 0); } } @@ -989,7 +1006,7 @@ static int s_test_s3_client_update_connections_finish_result(struct aws_allocato /* Verify that the request does not get sent because the meta request has finish-result. */ { - struct aws_s3_request *request = aws_s3_request_new(mock_meta_request, 0, 0, 0); + struct aws_s3_request *request = aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0); aws_linked_list_push_back(&mock_client->threaded_data.request_queue, &request->node); ++mock_client->threaded_data.request_queue_size; @@ -1010,7 +1027,8 @@ static int s_test_s3_client_update_connections_finish_result(struct aws_allocato /* Verify that a request with the 'always send' flag still gets sent when the meta request has a finish-result. */ { - struct aws_s3_request *request = aws_s3_request_new(mock_meta_request, 0, 0, AWS_S3_REQUEST_FLAG_ALWAYS_SEND); + struct aws_s3_request *request = + aws_s3_request_new(mock_meta_request, 0, 0, "", 0, AWS_S3_REQUEST_FLAG_ALWAYS_SEND); aws_linked_list_push_back(&mock_client->threaded_data.request_queue, &request->node); ++mock_client->threaded_data.request_queue_size; @@ -4639,6 +4657,9 @@ static int s_test_s3_put_fail_object_invalid_request(struct aws_allocator *alloc ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(NULL, &options, &meta_request_test_results)); ASSERT_UINT_EQUALS(AWS_ERROR_S3_INVALID_RESPONSE_STATUS, meta_request_test_results.finished_error_code); + /* Since 1MB is under part_size, there will be a single PutObject request */ + ASSERT_STR_EQUALS("PutObject", aws_string_c_str(meta_request_test_results.error_response_operation_name)); + aws_s3_meta_request_test_results_clean_up(&meta_request_test_results); return 0; diff --git a/tests/s3_mock_server_tests.c b/tests/s3_mock_server_tests.c index 66e0d3913..5d24e5a9e 100644 --- a/tests/s3_mock_server_tests.c +++ b/tests/s3_mock_server_tests.c @@ -755,6 +755,7 @@ TEST_CASE(resume_list_parts_failed_mock_server) { ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(&tester, &put_options, &out_results)); ASSERT_UINT_EQUALS(AWS_ERROR_S3_INVALID_RESPONSE_STATUS, out_results.finished_error_code); ASSERT_UINT_EQUALS(AWS_HTTP_STATUS_CODE_404_NOT_FOUND, out_results.finished_response_status); + ASSERT_STR_EQUALS("ListParts", aws_string_c_str(out_results.error_response_operation_name)); aws_s3_meta_request_test_results_clean_up(&out_results); aws_s3_meta_request_resume_token_release(token); From 5d9337ffdcc8da66d5a865fffb0f085e1ce38b63 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 21 Nov 2023 22:51:39 -0800 Subject: [PATCH 04/13] I heart code that compiles --- include/aws/s3/private/s3_request.h | 9 --------- source/s3_default_meta_request.c | 9 --------- 2 files changed, 18 deletions(-) diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index a99040c4a..30052af30 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -256,15 +256,6 @@ struct aws_s3_request *aws_s3_request_acquire(struct aws_s3_request *request); AWS_S3_API struct aws_s3_request *aws_s3_request_release(struct aws_s3_request *request); -/* Return type enum, if it is known. Otherwise AWS_S3_REQUEST_TYPE_MAX is returned. */ -AWS_S3_API -enum aws_s3_request_type aws_s3_request_get_type(const struct aws_s3_request *request); - -/* Return S3 operation name, if it is known. Otherwise an empty string is returned. - * Note that this C-string's lifetime is tied to the aws_s3_request. */ -AWS_S3_API -const char *aws_s3_request_get_operation_name(const struct aws_s3_request *request); - AWS_S3_API struct aws_s3_request_metrics *aws_s3_request_metrics_new( struct aws_allocator *allocator, diff --git a/source/s3_default_meta_request.c b/source/s3_default_meta_request.c index 52159d53b..4e06caea6 100644 --- a/source/s3_default_meta_request.c +++ b/source/s3_default_meta_request.c @@ -36,8 +36,6 @@ static void s_s3_meta_request_default_request_finished( struct aws_s3_request *request, int error_code); -static const char *s_s3_meta_request_default_operation_name(const struct aws_s3_meta_request *meta_request); - 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_default, @@ -47,7 +45,6 @@ static struct aws_s3_meta_request_vtable s_s3_meta_request_default_vtable = { .finished_request = s_s3_meta_request_default_request_finished, .destroy = s_s3_meta_request_default_destroy, .finish = aws_s3_meta_request_finish_default, - .get_operation_name = s_s3_meta_request_default_operation_name, }; /* Allocate a new default meta request. */ @@ -424,9 +421,3 @@ static void s_s3_meta_request_default_request_finished( } /* END CRITICAL SECTION */ } - -static const char *s_s3_meta_request_default_operation_name(const struct aws_s3_meta_request *meta_request) { - struct aws_s3_meta_request_default *meta_request_default = meta_request->impl; - const struct aws_string *operation_name = meta_request_default->operation_name; - return operation_name ? aws_string_c_str(operation_name) : ""; -} From f9fa31549255d8ff9f9ec4e138bbeacd0e237961 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 21 Nov 2023 23:07:16 -0800 Subject: [PATCH 05/13] use NULL for unknown operation_name Instead of weird inconsistency storing NULL for unknown aws_string, but "" for unknown c-string. --- include/aws/s3/private/s3_request.h | 2 +- source/s3_default_meta_request.c | 4 ++-- source/s3_meta_request.c | 2 +- source/s3_request.c | 4 ++-- tests/s3_data_plane_tests.c | 14 +++++++------- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index 30052af30..b0bdb76fa 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -163,7 +163,7 @@ struct aws_s3_request { /* Actual S3 type for the single request (AWS_S3_REQUEST_TYPE_DEFAULT if unknown) */ enum aws_s3_request_type request_type; - /* S3 operation name for the single request (e.g. "CompleteMultipartUpload") (empty string if unknown) */ + /* S3 operation name for the single request (e.g. "CompleteMultipartUpload") (NULL if unknown) */ const char *operation_name; /* Members of this structure will be repopulated each time the request is sent. If the request fails, and needs to diff --git a/source/s3_default_meta_request.c b/source/s3_default_meta_request.c index 4e06caea6..a77974eab 100644 --- a/source/s3_default_meta_request.c +++ b/source/s3_default_meta_request.c @@ -59,7 +59,6 @@ struct aws_s3_meta_request *aws_s3_meta_request_default_new( AWS_PRECONDITION(allocator); AWS_PRECONDITION(client); - AWS_PRECONDITION(operation_name_override == NULL || operation_name_override[0] != '\0'); /* NULL or non-empty */ AWS_PRECONDITION(options); AWS_PRECONDITION(options->message); @@ -163,7 +162,8 @@ static bool s_s3_meta_request_default_update( meta_request, 0 /*request_tag*/, AWS_S3_REQUEST_TYPE_DEFAULT, - meta_request_default->operation_name ? aws_string_c_str(meta_request_default->operation_name) : "", + meta_request_default->operation_name ? aws_string_c_str(meta_request_default->operation_name) + : NULL, 1 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); diff --git a/source/s3_meta_request.c b/source/s3_meta_request.c index b7d9d5e78..79e5e4ba7 100644 --- a/source/s3_meta_request.c +++ b/source/s3_meta_request.c @@ -1806,7 +1806,7 @@ void aws_s3_meta_request_result_setup( result->error_response_body, meta_request->allocator, &failed_request->send_data.response_body); } - if (failed_request->operation_name[0] != '\0') { + if (failed_request->operation_name != NULL) { result->error_response_operation_name = aws_string_new_from_c_str(meta_request->allocator, failed_request->operation_name); } diff --git a/source/s3_request.c b/source/s3_request.c index 093b21754..557057c18 100644 --- a/source/s3_request.c +++ b/source/s3_request.c @@ -23,7 +23,7 @@ struct aws_s3_request *aws_s3_request_new( AWS_PRECONDITION(meta_request); AWS_PRECONDITION(meta_request->allocator); - AWS_PRECONDITION(operation_name); + AWS_PRECONDITION(operation_name == NULL || operation_name[0] != '\0'); /* should be NULL or non-empty */ struct aws_s3_request *request = aws_mem_calloc(meta_request->allocator, 1, sizeof(struct aws_s3_request)); @@ -170,7 +170,7 @@ struct aws_s3_request_metrics *aws_s3_request_metrics_new( metrics->req_resp_info_metrics.request_type = request->request_type; - if (request->operation_name[0] != '\0') { + if (request->operation_name != NULL) { metrics->req_resp_info_metrics.operation_name = aws_string_new_from_c_str(allocator, request->operation_name); } diff --git a/tests/s3_data_plane_tests.c b/tests/s3_data_plane_tests.c index c7e29f2ae..d74ecd202 100644 --- a/tests/s3_data_plane_tests.c +++ b/tests/s3_data_plane_tests.c @@ -624,15 +624,15 @@ static int s_test_s3_client_queue_requests(struct aws_allocator *allocator, void struct aws_s3_meta_request *mock_meta_request = aws_s3_tester_mock_meta_request_new(&tester); mock_meta_request->client = aws_s3_client_acquire(mock_client); - struct aws_s3_request *pivot_request = aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0); + struct aws_s3_request *pivot_request = aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0); struct aws_linked_list pivot_request_list; aws_linked_list_init(&pivot_request_list); struct aws_s3_request *requests[] = { - aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0), - aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0), - aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0), }; const uint32_t num_requests = AWS_ARRAY_SIZE(requests); @@ -745,7 +745,7 @@ static bool s_s3_test_work_meta_request_update( if (out_request) { if (user_data->has_work_remaining) { - *out_request = aws_s3_request_new(meta_request, 0, 0, "", 0, 0); + *out_request = aws_s3_request_new(meta_request, 0, 0, NULL, 0, 0); } } @@ -1006,7 +1006,7 @@ static int s_test_s3_client_update_connections_finish_result(struct aws_allocato /* Verify that the request does not get sent because the meta request has finish-result. */ { - struct aws_s3_request *request = aws_s3_request_new(mock_meta_request, 0, 0, "", 0, 0); + struct aws_s3_request *request = aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0); aws_linked_list_push_back(&mock_client->threaded_data.request_queue, &request->node); ++mock_client->threaded_data.request_queue_size; @@ -1028,7 +1028,7 @@ static int s_test_s3_client_update_connections_finish_result(struct aws_allocato /* Verify that a request with the 'always send' flag still gets sent when the meta request has a finish-result. */ { struct aws_s3_request *request = - aws_s3_request_new(mock_meta_request, 0, 0, "", 0, AWS_S3_REQUEST_FLAG_ALWAYS_SEND); + aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, AWS_S3_REQUEST_FLAG_ALWAYS_SEND); aws_linked_list_push_back(&mock_client->threaded_data.request_queue, &request->node); ++mock_client->threaded_data.request_queue_size; From 187a73e5d49f9d95744e51130cb998413dbc10cc Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 21 Nov 2023 23:19:21 -0800 Subject: [PATCH 06/13] fix bad merge --- source/s3_default_meta_request.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/s3_default_meta_request.c b/source/s3_default_meta_request.c index a77974eab..b1098e12b 100644 --- a/source/s3_default_meta_request.c +++ b/source/s3_default_meta_request.c @@ -114,11 +114,11 @@ struct aws_s3_meta_request *aws_s3_meta_request_default_new( meta_request_default->operation_name = aws_string_new_from_cursor(allocator, &options->operation_name); } - 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; } From e14e43dc49bd3bcfa4dda2d063cda868b14ea3e3 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 21 Nov 2023 23:19:39 -0800 Subject: [PATCH 07/13] request_type > request_tag --- source/s3_meta_request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/s3_meta_request.c b/source/s3_meta_request.c index 79e5e4ba7..1cb50c261 100644 --- a/source/s3_meta_request.c +++ b/source/s3_meta_request.c @@ -1055,7 +1055,7 @@ static int s_s3_meta_request_incoming_headers( s_s3_meta_request_error_code_from_response_status(request->send_data.response_status) == AWS_ERROR_SUCCESS; if (successful_response && meta_request->checksum_config.validate_response_checksum && - request->request_tag == AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART) { + request->request_type == AWS_S3_REQUEST_TYPE_GET_OBJECT) { s_get_part_response_headers_checksum_helper(connection, meta_request, headers, headers_count); } From 570975e9065815c483ceba6f97de36acbfcad5f4 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Tue, 21 Nov 2023 23:33:11 -0800 Subject: [PATCH 08/13] =?UTF-8?q?=F0=9F=A4=A6=E2=80=8D=E2=99=80=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/s3_auto_ranged_get.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/s3_auto_ranged_get.c b/source/s3_auto_ranged_get.c index aee8b9fd1..e815f0bd7 100644 --- a/source/s3_auto_ranged_get.c +++ b/source/s3_auto_ranged_get.c @@ -184,8 +184,8 @@ static bool s_s3_auto_ranged_get_update( request = aws_s3_request_new( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART, - AWS_S3_REQUEST_TYPE_UPLOAD_PART, - "UploadPart", + AWS_S3_REQUEST_TYPE_GET_OBJECT, + "GetObject", 1 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_PART_SIZE_RESPONSE_BODY); From e03689ec8884a9554271657b91c60db2966f9c1d Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Wed, 22 Nov 2023 11:36:13 -0800 Subject: [PATCH 09/13] Bring back request_type -> operation_name function --- .../aws/s3/private/s3_default_meta_request.h | 3 +- include/aws/s3/private/s3_request.h | 2 +- include/aws/s3/s3_client.h | 33 ++++++++++++++++--- source/s3_client.c | 5 +-- source/s3_default_meta_request.c | 13 +++++--- source/s3_util.c | 27 +++++++++++++++ tests/CMakeLists.txt | 1 + tests/s3_util_tests.c | 24 ++++++++++++++ 8 files changed, 93 insertions(+), 15 deletions(-) diff --git a/include/aws/s3/private/s3_default_meta_request.h b/include/aws/s3/private/s3_default_meta_request.h index b519fd597..4523cf8f2 100644 --- a/include/aws/s3/private/s3_default_meta_request.h +++ b/include/aws/s3/private/s3_default_meta_request.h @@ -15,7 +15,7 @@ struct aws_s3_meta_request_default { size_t content_length; - /* Actual type for the single request (AWS_S3_REQUEST_TYPE_DEFAULT if unknown) */ + /* Actual type for the single request (may be AWS_S3_REQUEST_TYPE_UNKNOWN) */ enum aws_s3_request_type request_type; /* S3 operation name for the single request (NULL if unknown) */ @@ -48,7 +48,6 @@ 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, - const char *operation_name_override, uint64_t content_length, bool should_compute_content_md5, const struct aws_s3_meta_request_options *options); diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index b0bdb76fa..7350cb37b 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -160,7 +160,7 @@ struct aws_s3_request { /* TODO: this should be a union type to make it clear that this could be one of two enums for puts, and gets. */ int request_tag; - /* Actual S3 type for the single request (AWS_S3_REQUEST_TYPE_DEFAULT if unknown) */ + /* Actual S3 type for the single request (may be AWS_S3_REQUEST_TYPE_UNKNOWN) */ enum aws_s3_request_type request_type; /* S3 operation name for the single request (e.g. "CompleteMultipartUpload") (NULL if unknown) */ diff --git a/include/aws/s3/s3_client.h b/include/aws/s3/s3_client.h index d08786934..304ac9ef0 100644 --- a/include/aws/s3/s3_client.h +++ b/include/aws/s3/s3_client.h @@ -85,25 +85,39 @@ enum aws_s3_meta_request_type { }; /** - * The type of S3 request made. Used by metrics. + * The type of a single S3 HTTP request. Used by metrics. + * A meta-request can make multiple S3 HTTP requests under the hood. + * + * For example, AWS_S3_META_REQUEST_TYPE_PUT_OBJECT for a large file will + * do multipart upload, resulting in 3+ HTTP requests: + * AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, one or more AWS_S3_REQUEST_TYPE_UPLOAD_PART, + * and finally AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD. + * + * aws_s3_request_type_operation_name() returns the S3 operation name + * for types that map (e.g. AWS_S3_REQUEST_TYPE_HEAD_OBJECT -> "HeadObject"), + * or empty string for types that don't map (e.g. AWS_S3_REQUEST_TYPE_UNKNOWN -> ""). */ enum aws_s3_request_type { - /* Same as the original HTTP request passed to aws_s3_meta_request_options */ - AWS_S3_REQUEST_TYPE_DEFAULT, + /* The actual type of the single S3 HTTP request is unknown */ + AWS_S3_REQUEST_TYPE_UNKNOWN, /* S3 APIs */ AWS_S3_REQUEST_TYPE_HEAD_OBJECT, AWS_S3_REQUEST_TYPE_GET_OBJECT, AWS_S3_REQUEST_TYPE_LIST_PARTS, - AWS_S3_REQUEST_TYPE_PUT_OBJECT, AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_UPLOAD_PART, AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY, AWS_S3_REQUEST_TYPE_COPY_OBJECT, + AWS_S3_REQUEST_TYPE_PUT_OBJECT, + /* Max enum value */ AWS_S3_REQUEST_TYPE_MAX, + + /** @deprecated Use AWS_S3_REQUEST_TYPE_UNKNOWN if the actual S3 HTTP request type is unknown */ + AWS_S3_REQUEST_TYPE_DEFAULT = AWS_S3_REQUEST_TYPE_UNKNOWN, }; /** @@ -845,6 +859,17 @@ void aws_s3_init_default_signing_config( const struct aws_byte_cursor region, struct aws_credentials_provider *credentials_provider); +/** + * Return operation name for aws_s3_request_type, + * or empty string if the type doesn't map to an actual operation. + * For example: + * AWS_S3_REQUEST_TYPE_HEAD_OBJECT -> "HeadObject" + * AWS_S3_REQUEST_TYPE_UNKNOWN -> "" + * AWS_S3_REQUEST_TYPE_MAX -> "" + */ +AWS_S3_API +const char *aws_s3_request_type_operation_name(enum aws_s3_request_type type); + /** * Add a reference, keeping this object alive. * The reference must be released when you are done with it, or it's memory will never be cleaned up. diff --git a/source/s3_client.c b/source/s3_client.c index 38cf7df8d..03fc32381 100644 --- a/source/s3_client.c +++ b/source/s3_client.c @@ -1047,7 +1047,6 @@ static struct aws_s3_meta_request *s_s3_client_meta_request_factory_default( client->allocator, client, AWS_S3_REQUEST_TYPE_GET_OBJECT, - "GetObject", content_length, false /*should_compute_content_md5*/, options); @@ -1100,7 +1099,6 @@ static struct aws_s3_meta_request *s_s3_client_meta_request_factory_default( client->allocator, client, AWS_S3_REQUEST_TYPE_PUT_OBJECT, - "PutObject", content_length, client->compute_content_md5 == AWS_MR_CONTENT_MD5_ENABLED && !aws_http_headers_has(initial_message_headers, g_content_md5_header_name), @@ -1150,8 +1148,7 @@ static struct aws_s3_meta_request *s_s3_client_meta_request_factory_default( return aws_s3_meta_request_default_new( client->allocator, client, - AWS_S3_REQUEST_TYPE_DEFAULT, - NULL /*operation_name_override*/, + AWS_S3_REQUEST_TYPE_UNKNOWN, content_length, false /*should_compute_content_md5*/, options); diff --git a/source/s3_default_meta_request.c b/source/s3_default_meta_request.c index b1098e12b..ec4d22c5b 100644 --- a/source/s3_default_meta_request.c +++ b/source/s3_default_meta_request.c @@ -52,7 +52,6 @@ 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, - const char *operation_name_override, uint64_t content_length, bool should_compute_content_md5, const struct aws_s3_meta_request_options *options) { @@ -108,8 +107,14 @@ 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; - if (operation_name_override != NULL) { - meta_request_default->operation_name = aws_string_new_from_c_str(allocator, operation_name_override); + /* 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); } @@ -161,7 +166,7 @@ static bool s_s3_meta_request_default_update( request = aws_s3_request_new( meta_request, 0 /*request_tag*/, - AWS_S3_REQUEST_TYPE_DEFAULT, + meta_request_default->request_type, meta_request_default->operation_name ? aws_string_c_str(meta_request_default->operation_name) : NULL, 1 /*part_number*/, diff --git a/source/s3_util.c b/source/s3_util.c index 451179fb0..c1137c41b 100644 --- a/source/s3_util.c +++ b/source/s3_util.c @@ -64,6 +64,33 @@ const struct aws_byte_cursor g_user_agent_header_product_name = const uint32_t g_s3_max_num_upload_parts = 10000; const size_t g_s3_min_upload_part_size = MB_TO_BYTES(5); +const char *aws_s3_request_type_operation_name(enum aws_s3_request_type type) { + switch (type) { + case AWS_S3_REQUEST_TYPE_HEAD_OBJECT: + return "HeadObject"; + case AWS_S3_REQUEST_TYPE_GET_OBJECT: + return "GetObject"; + case AWS_S3_REQUEST_TYPE_LIST_PARTS: + return "ListParts"; + case AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD: + return "CreateMultipartUpload"; + case AWS_S3_REQUEST_TYPE_UPLOAD_PART: + return "UploadPart"; + case AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD: + return "AbortMultipartUpload"; + case AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD: + return "CompleteMultipartUpload"; + case AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY: + return "UploadPartCopy"; + case AWS_S3_REQUEST_TYPE_COPY_OBJECT: + return "CopyObject"; + case AWS_S3_REQUEST_TYPE_PUT_OBJECT: + return "PutObject"; + default: + return ""; + } +} + void copy_http_headers(const struct aws_http_headers *src, struct aws_http_headers *dest) { AWS_PRECONDITION(src); AWS_PRECONDITION(dest); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 88f624f8c..bc9d2c612 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -179,6 +179,7 @@ add_net_test_case(test_s3_not_satisfiable_range) add_net_test_case(test_s3_bad_endpoint) add_net_test_case(test_s3_different_endpoints) +add_test_case(test_s3_request_type_operation_name) add_test_case(test_s3_replace_quote_entities) add_test_case(test_s3_strip_quotes) add_test_case(test_s3_parse_content_range_response_header) diff --git a/tests/s3_util_tests.c b/tests/s3_util_tests.c index 1233c391a..433dd32f2 100644 --- a/tests/s3_util_tests.c +++ b/tests/s3_util_tests.c @@ -22,6 +22,30 @@ #include #include +AWS_TEST_CASE(test_s3_request_type_operation_name, s_test_s3_request_type_operation_name) +static int s_test_s3_request_type_operation_name(struct aws_allocator *allocator, void *ctx) { + (void)allocator; + (void)ctx; + + /* sanity check */ + ASSERT_STR_EQUALS("HeadObject", aws_s3_request_type_operation_name(AWS_S3_REQUEST_TYPE_HEAD_OBJECT)); + + /* check that all valid enums give back valid strings */ + for (enum aws_s3_request_type type = AWS_S3_REQUEST_TYPE_UNKNOWN + 1; type < AWS_S3_REQUEST_TYPE_MAX; ++type) { + const char *operation_name = aws_s3_request_type_operation_name(type); + ASSERT_NOT_NULL(operation_name); + ASSERT_TRUE(strlen(operation_name) > 1); + } + + /* check that invalid enums give back empty strings */ + ASSERT_NOT_NULL(aws_s3_request_type_operation_name(AWS_S3_REQUEST_TYPE_UNKNOWN)); + ASSERT_STR_EQUALS("", aws_s3_request_type_operation_name(AWS_S3_REQUEST_TYPE_UNKNOWN)); + ASSERT_STR_EQUALS("", aws_s3_request_type_operation_name(AWS_S3_REQUEST_TYPE_MAX)); + ASSERT_STR_EQUALS("", aws_s3_request_type_operation_name(-1)); + + return 0; +} + AWS_TEST_CASE(test_s3_replace_quote_entities, s_test_s3_replace_quote_entities) static int s_test_s3_replace_quote_entities(struct aws_allocator *allocator, void *ctx) { (void)ctx; From 3947aafa94632c5a98468aaf08f01e2de22d1158 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Wed, 22 Nov 2023 11:54:48 -0800 Subject: [PATCH 10/13] Stop passing redundant operation-name to request_new(). In the 1 case where the name differed from the type, we'll just set that afterwards. --- include/aws/s3/private/s3_request.h | 8 ++++--- source/s3_auto_ranged_get.c | 4 ---- source/s3_auto_ranged_put.c | 6 ----- source/s3_copy_object.c | 6 ----- source/s3_default_meta_request.c | 9 +++++-- source/s3_meta_request.c | 2 +- source/s3_request.c | 11 +++++---- tests/s3_data_plane_tests.c | 37 ++++++++++------------------- 8 files changed, 33 insertions(+), 50 deletions(-) diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index 7350cb37b..cecd16a63 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -157,14 +157,17 @@ struct aws_s3_request { * by the derived type. Request tags do not necessarily map 1:1 with actual S3 API requests. (For example, they can * be more contextual, like "first part" instead of just "part".) */ - /* TODO: this should be a union type to make it clear that this could be one of two enums for puts, and gets. */ + /* TODO: Eliminate the concept of "request tag" and just use request_type. + * It's confusing having 2 concepts that are so similar. + * There's only 1 case where 2 tags used the same type, + * we can use some other bool/flag to differentiate this 1 case. */ int request_tag; /* Actual S3 type for the single request (may be AWS_S3_REQUEST_TYPE_UNKNOWN) */ enum aws_s3_request_type request_type; /* S3 operation name for the single request (e.g. "CompleteMultipartUpload") (NULL if unknown) */ - const char *operation_name; + struct aws_string *operation_name; /* Members of this structure will be repopulated each time the request is sent. If the request fails, and needs to * be retried, then the members of this structure will be cleaned up and re-populated on the next send. @@ -237,7 +240,6 @@ struct aws_s3_request *aws_s3_request_new( struct aws_s3_meta_request *meta_request, int request_tag, enum aws_s3_request_type request_type, - const char *operation_name, uint32_t part_number, uint32_t flags); diff --git a/source/s3_auto_ranged_get.c b/source/s3_auto_ranged_get.c index e815f0bd7..5e72b3a74 100644 --- a/source/s3_auto_ranged_get.c +++ b/source/s3_auto_ranged_get.c @@ -162,7 +162,6 @@ static bool s_s3_auto_ranged_get_update( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_HEAD_OBJECT, AWS_S3_REQUEST_TYPE_HEAD_OBJECT, - "HeadObject", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -185,7 +184,6 @@ static bool s_s3_auto_ranged_get_update( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART, AWS_S3_REQUEST_TYPE_GET_OBJECT, - "GetObject", 1 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_PART_SIZE_RESPONSE_BODY); @@ -213,7 +211,6 @@ static bool s_s3_auto_ranged_get_update( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_INITIAL_MESSAGE, AWS_S3_REQUEST_TYPE_GET_OBJECT, - "GetObject", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -264,7 +261,6 @@ static bool s_s3_auto_ranged_get_update( meta_request, AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART, AWS_S3_REQUEST_TYPE_GET_OBJECT, - "GetObject", auto_ranged_get->synced_data.num_parts_requested + 1 /*part_number*/, AWS_S3_REQUEST_FLAG_PART_SIZE_RESPONSE_BODY); diff --git a/source/s3_auto_ranged_put.c b/source/s3_auto_ranged_put.c index ce078df52..c77cbce5f 100644 --- a/source/s3_auto_ranged_put.c +++ b/source/s3_auto_ranged_put.c @@ -463,7 +463,6 @@ static bool s_s3_auto_ranged_put_update( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_LIST_PARTS, AWS_S3_REQUEST_TYPE_LIST_PARTS, - "ListParts", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -479,7 +478,6 @@ static bool s_s3_auto_ranged_put_update( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_LIST_PARTS, AWS_S3_REQUEST_TYPE_LIST_PARTS, - "ListParts", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); auto_ranged_put->synced_data.list_parts_state.continues = false; @@ -497,7 +495,6 @@ static bool s_s3_auto_ranged_put_update( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, - "CreateMultipartUpload", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -553,7 +550,6 @@ static bool s_s3_auto_ranged_put_update( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_PART, AWS_S3_REQUEST_TYPE_UPLOAD_PART, - "UploadPart", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_PART_SIZE_REQUEST_BODY); @@ -601,7 +597,6 @@ static bool s_s3_auto_ranged_put_update( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, - "CompleteMultipartUpload", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -668,7 +663,6 @@ static bool s_s3_auto_ranged_put_update( meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD, - "AbortMultipartUpload", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_ALWAYS_SEND); diff --git a/source/s3_copy_object.c b/source/s3_copy_object.c index 4bdf5588e..2bb76a985 100644 --- a/source/s3_copy_object.c +++ b/source/s3_copy_object.c @@ -137,7 +137,6 @@ static bool s_s3_copy_object_update( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_GET_OBJECT_SIZE, AWS_S3_REQUEST_TYPE_HEAD_OBJECT, - "HeadObject", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -158,7 +157,6 @@ static bool s_s3_copy_object_update( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_BYPASS, AWS_S3_REQUEST_TYPE_COPY_OBJECT, - "CopyObject", 1 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -187,7 +185,6 @@ static bool s_s3_copy_object_update( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, - "CreateMultipartUpload", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -219,7 +216,6 @@ static bool s_s3_copy_object_update( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_MULTIPART_COPY, AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY, - "UploadPartCopy", copy_object->threaded_update_data.next_part_number, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -248,7 +244,6 @@ static bool s_s3_copy_object_update( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, - "CompleteMultipartUpload", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); @@ -303,7 +298,6 @@ static bool s_s3_copy_object_update( meta_request, AWS_S3_COPY_OBJECT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD, AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD, - "AbortMultipartUpload", 0 /*part_number*/, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_ALWAYS_SEND); diff --git a/source/s3_default_meta_request.c b/source/s3_default_meta_request.c index ec4d22c5b..746122311 100644 --- a/source/s3_default_meta_request.c +++ b/source/s3_default_meta_request.c @@ -167,11 +167,16 @@ static bool s_s3_meta_request_default_update( meta_request, 0 /*request_tag*/, meta_request_default->request_type, - meta_request_default->operation_name ? aws_string_c_str(meta_request_default->operation_name) - : NULL, 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, "id=%p: Meta Request Default created request %p", diff --git a/source/s3_meta_request.c b/source/s3_meta_request.c index 1cb50c261..6a6f04f16 100644 --- a/source/s3_meta_request.c +++ b/source/s3_meta_request.c @@ -1808,7 +1808,7 @@ void aws_s3_meta_request_result_setup( if (failed_request->operation_name != NULL) { result->error_response_operation_name = - aws_string_new_from_c_str(meta_request->allocator, failed_request->operation_name); + aws_string_new_from_string(meta_request->allocator, failed_request->operation_name); } } diff --git a/source/s3_request.c b/source/s3_request.c index 557057c18..805474d57 100644 --- a/source/s3_request.c +++ b/source/s3_request.c @@ -17,13 +17,11 @@ struct aws_s3_request *aws_s3_request_new( struct aws_s3_meta_request *meta_request, int request_tag, enum aws_s3_request_type request_type, - const char *operation_name, uint32_t part_number, uint32_t flags) { AWS_PRECONDITION(meta_request); AWS_PRECONDITION(meta_request->allocator); - AWS_PRECONDITION(operation_name == NULL || operation_name[0] != '\0'); /* should be NULL or non-empty */ struct aws_s3_request *request = aws_mem_calloc(meta_request->allocator, 1, sizeof(struct aws_s3_request)); @@ -34,7 +32,12 @@ struct aws_s3_request *aws_s3_request_new( request->request_tag = request_tag; request->request_type = request_type; - request->operation_name = operation_name; + + const char *operation_name = aws_s3_request_type_operation_name(request_type); + if (operation_name[0] != '\0') { + request->operation_name = aws_string_new_from_c_str(request->allocator, operation_name); + } + request->part_number = part_number; request->record_response_headers = (flags & AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS) != 0; request->has_part_size_response_body = (flags & AWS_S3_REQUEST_FLAG_PART_SIZE_RESPONSE_BODY) != 0; @@ -171,7 +174,7 @@ struct aws_s3_request_metrics *aws_s3_request_metrics_new( metrics->req_resp_info_metrics.request_type = request->request_type; if (request->operation_name != NULL) { - metrics->req_resp_info_metrics.operation_name = aws_string_new_from_c_str(allocator, request->operation_name); + metrics->req_resp_info_metrics.operation_name = aws_string_new_from_string(allocator, request->operation_name); } metrics->time_metrics.start_timestamp_ns = -1; diff --git a/tests/s3_data_plane_tests.c b/tests/s3_data_plane_tests.c index d74ecd202..c031f2c1c 100644 --- a/tests/s3_data_plane_tests.c +++ b/tests/s3_data_plane_tests.c @@ -368,8 +368,7 @@ static int s_test_s3_request_create_destroy(struct aws_allocator *allocator, voi (void)ctx; const int request_tag = 1234; - const enum aws_s3_request_type request_type = (enum aws_s3_request_type)9876; - const char *operation_name = "BlibbityBlob"; + const enum aws_s3_request_type request_type = AWS_S3_REQUEST_TYPE_LIST_PARTS; const uint32_t part_number = 5678; struct aws_s3_tester tester; @@ -387,12 +386,7 @@ static int s_test_s3_request_create_destroy(struct aws_allocator *allocator, voi ASSERT_TRUE(request_message != NULL); struct aws_s3_request *request = aws_s3_request_new( - meta_request, - request_tag, - request_type, - operation_name, - part_number, - AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); + meta_request, request_tag, request_type, part_number, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS); ASSERT_TRUE(request != NULL); @@ -400,7 +394,7 @@ static int s_test_s3_request_create_destroy(struct aws_allocator *allocator, voi ASSERT_TRUE(request->part_number == part_number); ASSERT_TRUE(request->request_tag == request_tag); ASSERT_TRUE(request->request_type == request_type); - ASSERT_STR_EQUALS(operation_name, request->operation_name); + ASSERT_STR_EQUALS("ListParts", aws_string_c_str(request->operation_name)); ASSERT_TRUE(request->record_response_headers == true); aws_s3_request_setup_send_data(request, request_message); @@ -503,7 +497,7 @@ static int s_test_s3_meta_request_body_streaming(struct aws_allocator *allocator { for (uint32_t part_number = part_range0_start; part_number <= part_range0_end; ++part_number) { struct aws_s3_request *request = aws_s3_request_new( - meta_request, 0 /*request_tag*/, AWS_S3_REQUEST_TYPE_GET_OBJECT, "GetObject", part_number, 0 /*flags*/); + meta_request, 0 /*request_tag*/, AWS_S3_REQUEST_TYPE_GET_OBJECT, part_number, 0 /*flags*/); aws_s3_get_part_range( 0ULL, @@ -540,7 +534,7 @@ static int s_test_s3_meta_request_body_streaming(struct aws_allocator *allocator for (uint32_t part_number = part_range1_start + 1; part_number <= part_range1_end; ++part_number) { struct aws_s3_request *request = aws_s3_request_new( - meta_request, 0 /*request_tag*/, AWS_S3_REQUEST_TYPE_GET_OBJECT, "GetObject", part_number, 0 /*flags*/); + meta_request, 0 /*request_tag*/, AWS_S3_REQUEST_TYPE_GET_OBJECT, part_number, 0 /*flags*/); aws_s3_get_part_range( 0ULL, @@ -569,12 +563,7 @@ static int s_test_s3_meta_request_body_streaming(struct aws_allocator *allocator /* Stream the last part of the body, which should flush the priority queue. */ { struct aws_s3_request *request = aws_s3_request_new( - meta_request, - 0 /*request_tag*/, - AWS_S3_REQUEST_TYPE_GET_OBJECT, - "GetObject", - part_range1_start, - 0 /*flags*/); + meta_request, 0 /*request_tag*/, AWS_S3_REQUEST_TYPE_GET_OBJECT, part_range1_start, 0 /*flags*/); aws_s3_get_part_range( 0ULL, @@ -624,15 +613,15 @@ static int s_test_s3_client_queue_requests(struct aws_allocator *allocator, void struct aws_s3_meta_request *mock_meta_request = aws_s3_tester_mock_meta_request_new(&tester); mock_meta_request->client = aws_s3_client_acquire(mock_client); - struct aws_s3_request *pivot_request = aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0); + struct aws_s3_request *pivot_request = aws_s3_request_new(mock_meta_request, 0, 0, 0, 0); struct aws_linked_list pivot_request_list; aws_linked_list_init(&pivot_request_list); struct aws_s3_request *requests[] = { - aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0), - aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0), - aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, 0, 0), + aws_s3_request_new(mock_meta_request, 0, 0, 0, 0), }; const uint32_t num_requests = AWS_ARRAY_SIZE(requests); @@ -745,7 +734,7 @@ static bool s_s3_test_work_meta_request_update( if (out_request) { if (user_data->has_work_remaining) { - *out_request = aws_s3_request_new(meta_request, 0, 0, NULL, 0, 0); + *out_request = aws_s3_request_new(meta_request, 0, 0, 0, 0); } } @@ -1006,7 +995,7 @@ static int s_test_s3_client_update_connections_finish_result(struct aws_allocato /* Verify that the request does not get sent because the meta request has finish-result. */ { - struct aws_s3_request *request = aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, 0); + struct aws_s3_request *request = aws_s3_request_new(mock_meta_request, 0, 0, 0, 0); aws_linked_list_push_back(&mock_client->threaded_data.request_queue, &request->node); ++mock_client->threaded_data.request_queue_size; @@ -1028,7 +1017,7 @@ static int s_test_s3_client_update_connections_finish_result(struct aws_allocato /* Verify that a request with the 'always send' flag still gets sent when the meta request has a finish-result. */ { struct aws_s3_request *request = - aws_s3_request_new(mock_meta_request, 0, 0, NULL, 0, AWS_S3_REQUEST_FLAG_ALWAYS_SEND); + aws_s3_request_new(mock_meta_request, 0, 0, 0, AWS_S3_REQUEST_FLAG_ALWAYS_SEND); aws_linked_list_push_back(&mock_client->threaded_data.request_queue, &request->node); ++mock_client->threaded_data.request_queue_size; From cce7642cc137b10c410a149177506afbc765fe58 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Wed, 22 Nov 2023 12:02:46 -0800 Subject: [PATCH 11/13] the cool thing about C programming is --- source/s3_request.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/s3_request.c b/source/s3_request.c index 805474d57..f9c92e285 100644 --- a/source/s3_request.c +++ b/source/s3_request.c @@ -126,6 +126,7 @@ static void s_s3_request_destroy(void *user_data) { aws_s3_request_clean_up_send_data(request); aws_byte_buf_clean_up(&request->request_body); aws_s3_buffer_pool_release_ticket(request->meta_request->client->buffer_pool, request->ticket); + aws_string_destroy(request->operation_name); aws_s3_meta_request_release(request->meta_request); aws_mem_release(request->allocator, request); From 77e2a5cf6c19f61170e50d66d2f2bd5205320257 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Wed, 22 Nov 2023 12:28:47 -0800 Subject: [PATCH 12/13] Update comments. Some complex language I'd added isn't needed anymore --- include/aws/s3/private/s3_default_meta_request.h | 13 +------------ include/aws/s3/private/s3_request.h | 6 +----- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/include/aws/s3/private/s3_default_meta_request.h b/include/aws/s3/private/s3_default_meta_request.h index 4523cf8f2..4ce93f91a 100644 --- a/include/aws/s3/private/s3_default_meta_request.h +++ b/include/aws/s3/private/s3_default_meta_request.h @@ -32,18 +32,7 @@ struct aws_s3_meta_request_default { } synced_data; }; -/* Creates a new default meta request. This will send the request as is and pass back the response. - * - * Sometimes, a default meta-request is used for other aws_s3_meta_request_types. - * For example, if the request is simple (e.g. single part upload or download), - * or if there's a header that's too complex to deal with. - * In these cases, request_type and operation_name_override should be set. - * - * But if the user literally asked for a AWS_S3_META_REQUEST_TYPE_DEFAULT, - * the request_type should be AWS_S3_META_REQUEST_TYPE_DEFAULT and - * operation_name_override should be NULL (options->operation_name will be used - * if it is set). - */ +/* Creates a new default meta request. This will send the request as is and pass back the response. */ struct aws_s3_meta_request *aws_s3_meta_request_default_new( struct aws_allocator *allocator, struct aws_s3_client *client, diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index cecd16a63..9d59558b0 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -230,11 +230,7 @@ struct aws_s3_request { AWS_EXTERN_C_BEGIN -/* Create a new s3 request structure with the given options. - * @param operation_name Official S3 operation name (e.g. "CreateMultipartUpload"). - * Pass an empty string if unknown. - * The string's memory must outlive the request (static string, or live on meta_request) - */ +/* Create a new s3 request structure with the given options. */ AWS_S3_API struct aws_s3_request *aws_s3_request_new( struct aws_s3_meta_request *meta_request, From 5181b195c4faccc824d51c39cd842296c6e25f64 Mon Sep 17 00:00:00 2001 From: Michael Graeb Date: Wed, 22 Nov 2023 12:48:40 -0800 Subject: [PATCH 13/13] Update include/aws/s3/s3_client.h Co-authored-by: Waqar Ahmed Khan --- include/aws/s3/s3_client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/aws/s3/s3_client.h b/include/aws/s3/s3_client.h index 304ac9ef0..b9e7e1677 100644 --- a/include/aws/s3/s3_client.h +++ b/include/aws/s3/s3_client.h @@ -500,7 +500,7 @@ struct aws_s3_meta_request_options { /** * Optional. * The S3 operation name (e.g. "CreateBucket"). - * You should only set this when type is AWS_S3_META_REQUEST_TYPE_DEFAULT; + * This will only be used when type is AWS_S3_META_REQUEST_TYPE_DEFAULT; * it is automatically populated for other meta-request types. * This name is used to fill out details in metrics and error reports. */