static void s_s3_auto_ranged_get_request_finished()

in source/s3_auto_ranged_get.c [504:628]


static void s_s3_auto_ranged_get_request_finished(
    struct aws_s3_meta_request *meta_request,
    struct aws_s3_request *request,
    int error_code) {
    AWS_PRECONDITION(meta_request);
    AWS_PRECONDITION(meta_request->impl);
    AWS_PRECONDITION(request);

    struct aws_s3_auto_ranged_get *auto_ranged_get = meta_request->impl;
    AWS_PRECONDITION(auto_ranged_get);

    uint64_t total_object_size = 0ULL;
    uint64_t total_content_length = 0ULL;
    uint64_t object_range_start = 0ULL;
    uint64_t object_range_end = 0ULL;

    bool found_object_size = false;
    bool request_failed = error_code != AWS_ERROR_SUCCESS;

    if (request->discovers_object_size) {

        /* Try to discover the object-range and content length.*/
        if (s_discover_object_range_and_content_length(
                meta_request,
                request,
                error_code,
                &total_content_length,
                &object_range_start,
                &object_range_end,
                &total_object_size)) {

            error_code = aws_last_error_or_unknown();

            goto update_synced_data;
        }

        /* If we were able to discover the object-range/content length successfully, then any error code that was passed
         * into this function is being handled and does not indicate an overall failure.*/
        error_code = AWS_ERROR_SUCCESS;
        found_object_size = true;

        if (meta_request->headers_callback != NULL) {
            struct aws_http_headers *response_headers = aws_http_headers_new(meta_request->allocator);

            copy_http_headers(request->send_data.response_headers, response_headers);

            /* If this request is a part, then the content range isn't applicable. */
            if (request->request_tag == AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART) {
                /* For now, we can assume that discovery of size via the first part of the object does not apply to
                 * breaking up a ranged request. If it ever does, then we will need to repopulate this header. */
                AWS_ASSERT(!auto_ranged_get->initial_message_has_range_header);

                aws_http_headers_erase(response_headers, g_content_range_header_name);
            }

            char content_length_buffer[64] = "";
            snprintf(content_length_buffer, sizeof(content_length_buffer), "%" PRIu64, total_content_length);
            aws_http_headers_set(
                response_headers, g_content_length_header_name, aws_byte_cursor_from_c_str(content_length_buffer));

            if (meta_request->headers_callback(
                    meta_request,
                    response_headers,
                    s_s3_auto_ranged_get_success_status(meta_request),
                    meta_request->user_data)) {

                error_code = aws_last_error_or_unknown();
            }
            meta_request->headers_callback = NULL;

            aws_http_headers_release(response_headers);
        }
    }

update_synced_data:

    aws_s3_meta_request_lock_synced_data(meta_request);

    /* If the object range was found, then record it. */
    if (found_object_size) {
        AWS_ASSERT(!auto_ranged_get->synced_data.object_range_known);

        auto_ranged_get->synced_data.object_range_known = true;
        auto_ranged_get->synced_data.object_range_start = object_range_start;
        auto_ranged_get->synced_data.object_range_end = object_range_end;
        auto_ranged_get->synced_data.total_num_parts =
            aws_s3_get_num_parts(meta_request->part_size, object_range_start, object_range_end);
    }

    switch (request->request_tag) {
        case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_HEAD_OBJECT:
            auto_ranged_get->synced_data.head_object_completed = true;
            AWS_LOGF_DEBUG(AWS_LS_S3_META_REQUEST, "id=%p Head object completed.", (void *)meta_request);
            break;
        case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART:
            ++auto_ranged_get->synced_data.num_parts_completed;

            if (!request_failed) {
                ++auto_ranged_get->synced_data.num_parts_successful;

                aws_s3_meta_request_stream_response_body_synced(meta_request, request);

                AWS_LOGF_DEBUG(
                    AWS_LS_S3_META_REQUEST,
                    "id=%p: %d out of %d parts have completed.",
                    (void *)meta_request,
                    (auto_ranged_get->synced_data.num_parts_successful + auto_ranged_get->synced_data.num_parts_failed),
                    auto_ranged_get->synced_data.total_num_parts);
            } else {
                ++auto_ranged_get->synced_data.num_parts_failed;
            }
            break;
        case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_INITIAL_MESSAGE:
            AWS_LOGF_DEBUG(
                AWS_LS_S3_META_REQUEST, "id=%p Get of file using initial message completed.", (void *)meta_request);
            auto_ranged_get->synced_data.get_without_range_completed = true;
            break;
    }

    if (error_code != AWS_ERROR_SUCCESS) {
        aws_s3_meta_request_set_fail_synced(meta_request, request, error_code);
    }

    aws_s3_meta_request_unlock_synced_data(meta_request);
}