| 230 | } |
| 231 | |
| 232 | void RequestContext::OperDone(RequestRange* range, const Status& status) { |
| 233 | DCHECK(range != nullptr); |
| 234 | |
| 235 | // Copy disk_id before running callback: the callback may modify range. |
| 236 | int disk_id = range->disk_id(); |
| 237 | |
| 238 | // Execute the callback before decrementing the thread count. Otherwise |
| 239 | // RequestContext::Cancel() that waits for the disk ref count to be 0 will |
| 240 | // return, creating a race, e.g. see IMPALA-1890. |
| 241 | // The status of the operation does not affect the status of the request context. |
| 242 | if (range->request_type() == RequestType::WRITE) { |
| 243 | (static_cast<WriteRange*>(range))->callback()(status); |
| 244 | } else { |
| 245 | DCHECK(range->request_type() == RequestType::FILE_UPLOAD |
| 246 | || range->request_type() == RequestType::FILE_FETCH); |
| 247 | (static_cast<RemoteOperRange*>(range))->callback()(status); |
| 248 | } |
| 249 | { |
| 250 | unique_lock<mutex> lock(lock_); |
| 251 | DCHECK(Validate()) << endl << DebugString(); |
| 252 | RequestContext::PerDiskState& state = disk_states_[disk_id]; |
| 253 | state.DecrementDiskThread(lock, this); |
| 254 | --state.num_remaining_ranges(); |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | // Cancellation of a RequestContext requires coordination from multiple threads that may |
| 259 | // hold references to the context: |
no test coverage detected