| 2102 | } |
| 2103 | |
| 2104 | static void HandleUploadPartOutcome(const std::shared_ptr<UploadState>& state, |
| 2105 | int part_number, |
| 2106 | const S3Model::UploadPartRequest& req, |
| 2107 | const S3Model::UploadPartOutcome& outcome) { |
| 2108 | std::unique_lock<std::mutex> lock(state->mutex); |
| 2109 | if (!outcome.IsSuccess()) { |
| 2110 | state->status &= UploadPartError(req, outcome); |
| 2111 | } else { |
| 2112 | AddCompletedPart(state, part_number, outcome.GetResult()); |
| 2113 | } |
| 2114 | |
| 2115 | // Notify completion |
| 2116 | if (--state->uploads_in_progress == 0) { |
| 2117 | // GH-41862: avoid potential deadlock if the Future's callback is called |
| 2118 | // with the mutex taken. |
| 2119 | auto fut = state->pending_uploads_completed; |
| 2120 | lock.unlock(); |
| 2121 | // State could be mutated concurrently if another thread writes to the |
| 2122 | // stream, but in this case the Flush() call is only advisory anyway. |
| 2123 | // Besides, it's not generally sound to write to an OutputStream from |
| 2124 | // several threads at once. |
| 2125 | fut.MarkFinished(state->status); |
| 2126 | } |
| 2127 | } |
| 2128 | |
| 2129 | static void AddCompletedPart(const std::shared_ptr<UploadState>& state, int part_number, |
| 2130 | const S3Model::UploadPartResult& result) { |
nothing calls this directly
no test coverage detected