| 2219 | } |
| 2220 | |
| 2221 | void TmpFileBufferPool::TmpFileSpaceReserveThreadLoop() { |
| 2222 | while (true) { |
| 2223 | { |
| 2224 | unique_lock<mutex> l(lock_); |
| 2225 | while (!shut_down_ && write_ranges_.empty()) { |
| 2226 | // Wait if there are no ranges in the queue. |
| 2227 | work_available_.Wait(l); |
| 2228 | } |
| 2229 | if (shut_down_) return; |
| 2230 | DCHECK(!write_ranges_.empty()); |
| 2231 | cur_write_range_ = write_ranges_.front(); |
| 2232 | write_ranges_.pop_front(); |
| 2233 | DCHECK(cur_write_range_ != nullptr); |
| 2234 | |
| 2235 | // Find out the TmpFile which the current range is associated with, and store the |
| 2236 | // shared_ptr of the file to cur_tmp_file_ in case it is deconstructed while waiting |
| 2237 | // for reservation. |
| 2238 | auto it = write_ranges_iterator_.find(cur_write_range_); |
| 2239 | DCHECK(it != write_ranges_iterator_.end()); |
| 2240 | TmpFile* tmp_file = it->second.second; |
| 2241 | cur_tmp_file_ = tmp_file->FileGroup()->FindTmpFileSharedPtr(tmp_file); |
| 2242 | DCHECK(cur_tmp_file_ != nullptr); |
| 2243 | DCHECK_EQ(cur_write_range_->disk_file(), cur_tmp_file_->GetWriteFile()); |
| 2244 | write_ranges_iterator_.erase(it); |
| 2245 | } |
| 2246 | |
| 2247 | // Reserve space from the tmp_files_avail_pool_. The process could need a long wait. |
| 2248 | Status status = tmp_file_mgr_->ReserveLocalBufferSpace(false); |
| 2249 | vector<TmpFileMgr::WriteDoneCallback> write_callbacks; |
| 2250 | { |
| 2251 | unique_lock<mutex> lock(lock_); |
| 2252 | if (status.ok()) { |
| 2253 | DCHECK(cur_tmp_file_ != nullptr); |
| 2254 | cur_tmp_file_->GetWriteFile()->SetSpaceReserved(); |
| 2255 | if (cur_write_range_ != nullptr) { |
| 2256 | // Send all of the writes of the same disk file to the disk queue. |
| 2257 | status = MoveWriteRangesHelper( |
| 2258 | cur_write_range_->disk_file(), &write_callbacks, false); |
| 2259 | } else { |
| 2260 | // If the current range becomes a nullptr, it must be set by |
| 2261 | // RemoveWriteRanges(). In this case, the io_ctx which the range belongs to is |
| 2262 | // cancelled, and all the writes using that io_ctx are already cancelled. So, we |
| 2263 | // are safe to return the TmpFile to the pool to recycle the buffer space. |
| 2264 | EnqueueTmpFilesPool(cur_tmp_file_, true); |
| 2265 | } |
| 2266 | } else if (!status.ok() && cur_write_range_ != nullptr) { |
| 2267 | // Cancel the spilling if fails to reserve the buffer. |
| 2268 | RemoveWriteRangesInternal(cur_write_range_->io_ctx(), &write_callbacks); |
| 2269 | status = Status::CancelledInternal( |
| 2270 | Substitute("TmpFileBufferPool because: $0", status.GetDetail()).c_str()); |
| 2271 | } |
| 2272 | cur_write_range_ = nullptr; |
| 2273 | cur_tmp_file_.reset(); |
| 2274 | } |
| 2275 | for (const TmpFileMgr::WriteDoneCallback& write_callback : write_callbacks) { |
| 2276 | write_callback(status); |
| 2277 | } |
| 2278 | } |
nothing calls this directly
no test coverage detected