| 2161 | } |
| 2162 | |
| 2163 | static void HandleUploadPartOutcome(const std::shared_ptr<UploadState>& state, |
| 2164 | int part_number, |
| 2165 | const S3Model::UploadPartRequest& req, |
| 2166 | const S3Model::UploadPartOutcome& outcome) { |
| 2167 | std::unique_lock<std::mutex> lock(state->mutex); |
| 2168 | if (!outcome.IsSuccess()) { |
| 2169 | state->status &= UploadPartError(req, outcome); |
| 2170 | } else { |
| 2171 | AddCompletedPart(state, part_number, outcome.GetResult()); |
| 2172 | } |
| 2173 | |
| 2174 | // Notify completion |
| 2175 | if (--state->uploads_in_progress == 0) { |
| 2176 | // GH-41862: avoid potential deadlock if the Future's callback is called |
| 2177 | // with the mutex taken. |
| 2178 | auto fut = state->pending_uploads_completed; |
| 2179 | lock.unlock(); |
| 2180 | // State could be mutated concurrently if another thread writes to the |
| 2181 | // stream, but in this case the Flush() call is only advisory anyway. |
| 2182 | // Besides, it's not generally sound to write to an OutputStream from |
| 2183 | // several threads at once. |
| 2184 | fut.MarkFinished(state->status); |
| 2185 | } |
| 2186 | } |
| 2187 | |
| 2188 | static void AddCompletedPart(const std::shared_ptr<UploadState>& state, int part_number, |
| 2189 | const S3Model::UploadPartResult& result) { |
nothing calls this directly
no test coverage detected