in source/s3_auto_ranged_put.c [128:297]
static bool s_s3_auto_ranged_put_update(
struct aws_s3_meta_request *meta_request,
uint32_t flags,
struct aws_s3_request **out_request) {
AWS_PRECONDITION(meta_request);
AWS_PRECONDITION(out_request);
struct aws_s3_request *request = NULL;
bool work_remaining = false;
struct aws_s3_auto_ranged_put *auto_ranged_put = meta_request->impl;
aws_s3_meta_request_lock_synced_data(meta_request);
if (!aws_s3_meta_request_has_finish_result_synced(meta_request)) {
/* If we haven't already sent a create-multipart-upload message, do so now. */
if (!auto_ranged_put->synced_data.create_multipart_upload_sent) {
request = aws_s3_request_new(
meta_request,
AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD,
0,
AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS);
auto_ranged_put->synced_data.create_multipart_upload_sent = true;
goto has_work_remaining;
}
/* If the create-multipart-upload message hasn't been completed, then there is still additional work to do, but
* it can't be done yet. */
if (!auto_ranged_put->synced_data.create_multipart_upload_completed) {
goto has_work_remaining;
}
/* If we haven't sent all of the parts yet, then set up to send a new part now. */
if (auto_ranged_put->synced_data.num_parts_sent < auto_ranged_put->synced_data.total_num_parts) {
if ((flags & AWS_S3_META_REQUEST_UPDATE_FLAG_CONSERVATIVE) != 0) {
uint32_t num_parts_in_flight =
(auto_ranged_put->synced_data.num_parts_sent - auto_ranged_put->synced_data.num_parts_completed);
/* Because uploads must read from their streams serially, we try to limit the amount of in flight
* requests for a given multipart upload if we can. */
if (num_parts_in_flight > 0) {
goto has_work_remaining;
}
}
/* Allocate a request for another part. */
request = aws_s3_request_new(
meta_request, AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_PART, 0, AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS);
request->part_number = auto_ranged_put->threaded_update_data.next_part_number;
++auto_ranged_put->threaded_update_data.next_part_number;
++auto_ranged_put->synced_data.num_parts_sent;
AWS_LOGF_DEBUG(
AWS_LS_S3_META_REQUEST,
"id=%p: Returning request %p for part %d",
(void *)meta_request,
(void *)request,
request->part_number);
goto has_work_remaining;
}
/* There is one more request to send after all of the parts (the complete-multipart-upload) but it can't be done
* until all of the parts have been completed.*/
if (auto_ranged_put->synced_data.num_parts_completed != auto_ranged_put->synced_data.total_num_parts) {
goto has_work_remaining;
}
/* If the complete-multipart-upload request hasn't been set yet, then send it now. */
if (!auto_ranged_put->synced_data.complete_multipart_upload_sent) {
request = aws_s3_request_new(
meta_request,
AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD,
0,
AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS);
auto_ranged_put->synced_data.complete_multipart_upload_sent = true;
goto has_work_remaining;
}
/* Wait for the complete-multipart-upload request to finish. */
if (!auto_ranged_put->synced_data.complete_multipart_upload_completed) {
goto has_work_remaining;
}
goto no_work_remaining;
} else {
/* If the create multipart upload hasn't been sent, then there is nothing left to do when canceling. */
if (!auto_ranged_put->synced_data.create_multipart_upload_sent) {
goto no_work_remaining;
}
/* If the create-multipart-upload request is still in flight, wait for it to finish. */
if (!auto_ranged_put->synced_data.create_multipart_upload_completed) {
goto has_work_remaining;
}
/* If the number of parts completed is less than the number of parts sent, then we need to wait until all of
* those parts are done sending before aborting. */
if (auto_ranged_put->synced_data.num_parts_completed < auto_ranged_put->synced_data.num_parts_sent) {
goto has_work_remaining;
}
/* If the complete-multipart-upload is already in flight, then we can't necessarily send an abort. */
if (auto_ranged_put->synced_data.complete_multipart_upload_sent &&
!auto_ranged_put->synced_data.complete_multipart_upload_completed) {
goto has_work_remaining;
}
/* If the complete-multipart-upload completed successfully, then there is nothing to abort since the transfer
* has already finished. */
if (auto_ranged_put->synced_data.complete_multipart_upload_completed &&
auto_ranged_put->synced_data.complete_multipart_upload_error_code == AWS_ERROR_SUCCESS) {
goto no_work_remaining;
}
/* If we made it here, and the abort-multipart-upload message hasn't been sent yet, then do so now. */
if (!auto_ranged_put->synced_data.abort_multipart_upload_sent) {
if (auto_ranged_put->upload_id == NULL) {
goto no_work_remaining;
}
request = aws_s3_request_new(
meta_request,
AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD,
0,
AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS | AWS_S3_REQUEST_FLAG_ALWAYS_SEND);
auto_ranged_put->synced_data.abort_multipart_upload_sent = true;
goto has_work_remaining;
}
/* Wait for the multipart upload to be completed. */
if (!auto_ranged_put->synced_data.abort_multipart_upload_completed) {
goto has_work_remaining;
}
goto no_work_remaining;
}
has_work_remaining:
work_remaining = true;
no_work_remaining:
if (!work_remaining) {
aws_s3_meta_request_set_success_synced(meta_request, AWS_S3_RESPONSE_STATUS_SUCCESS);
}
aws_s3_meta_request_unlock_synced_data(meta_request);
if (work_remaining) {
*out_request = request;
} else {
AWS_ASSERT(request == NULL);
aws_s3_meta_request_finish(meta_request);
}
return work_remaining;
}