| 1087 | } |
| 1088 | |
| 1089 | void TmpFileRemote::AsyncFetchReadBufferBlock(io::DiskFile* read_buffer_file, |
| 1090 | io::MemBlock* read_buffer_block, int read_buffer_idx, bool* fetched) { |
| 1091 | DCHECK(fetched != nullptr); |
| 1092 | *fetched = false; |
| 1093 | { |
| 1094 | shared_lock<shared_mutex> read_file_lock(*(read_buffer_file->GetFileLock())); |
| 1095 | unique_lock<SpinLock> mem_bloc_lock(*(read_buffer_block->GetLock())); |
| 1096 | // Check the block status. |
| 1097 | // If the block is disabled, the caller won't be able to use this buffer block. |
| 1098 | // If the block is written, the block is already fetched, set the fetched flag and |
| 1099 | // return immediately. |
| 1100 | // If the block is uninitialized, we will fetch the block immediately but without |
| 1101 | // waiting for the fetch, so that it won't block the current page reading. |
| 1102 | // If the block is in reserved or alloc status, means one other thread is handling |
| 1103 | // the block, here we don't wait because the blocking could be expensive. |
| 1104 | if (read_buffer_file->IsReadBufferBlockStatus(read_buffer_block, |
| 1105 | io::MemBlockStatus::DISABLED, read_file_lock, &mem_bloc_lock)) { |
| 1106 | return; |
| 1107 | } else if (read_buffer_file->IsReadBufferBlockStatus(read_buffer_block, |
| 1108 | io::MemBlockStatus::WRITTEN, read_file_lock, &mem_bloc_lock)) { |
| 1109 | *fetched = true; |
| 1110 | return; |
| 1111 | } else if (read_buffer_file->IsReadBufferBlockStatus(read_buffer_block, |
| 1112 | io::MemBlockStatus::UNINIT, read_file_lock, &mem_bloc_lock)) { |
| 1113 | bool dofetch = true; |
| 1114 | int64_t mem_size_limit = |
| 1115 | file_group_->tmp_file_mgr()->GetRemoteMaxTotalReadBufferSize(); |
| 1116 | auto read_mem_counter = |
| 1117 | file_group_->tmp_file_mgr()->scratch_read_memory_buffer_used_metric_; |
| 1118 | if (read_mem_counter->Increment(read_buffer_file->read_buffer_block_size()) |
| 1119 | > mem_size_limit) { |
| 1120 | read_mem_counter->Increment(-1 * read_buffer_file->read_buffer_block_size()); |
| 1121 | dofetch = false; |
| 1122 | } |
| 1123 | if (dofetch) { |
| 1124 | read_buffer_file->SetReadBufferBlockStatus(read_buffer_block, |
| 1125 | io::MemBlockStatus::RESERVED, read_file_lock, &mem_bloc_lock); |
| 1126 | RemoteOperRange::RemoteOperDoneCallback fetch_callback = |
| 1127 | [read_buffer_block, tmp_file = this](const Status& fetch_status) { |
| 1128 | if (!fetch_status.ok()) { |
| 1129 | // Disable the read buffer if fails to fetch. |
| 1130 | tmp_file->TryDeleteReadBufferExcl(read_buffer_block->block_id()); |
| 1131 | } |
| 1132 | }; |
| 1133 | fetch_ranges_[read_buffer_idx].reset(new RemoteOperRange(disk_file_.get(), |
| 1134 | read_buffer_file, file_group_->tmp_file_mgr()->GetRemoteTmpBlockSize(), |
| 1135 | disk_id(true), RequestType::FILE_FETCH, file_group_->io_mgr_, fetch_callback, |
| 1136 | GetReadBuffStartOffset(read_buffer_idx))); |
| 1137 | Status add_status = file_group_->io_ctx_->AddRemoteOperRange( |
| 1138 | fetch_ranges_[read_buffer_idx].get()); |
| 1139 | if (!add_status.ok()) { |
| 1140 | read_buffer_file->SetReadBufferBlockStatus(read_buffer_block, |
| 1141 | io::MemBlockStatus::DISABLED, read_file_lock, &mem_bloc_lock); |
| 1142 | } |
| 1143 | } else { |
| 1144 | read_buffer_file->SetReadBufferBlockStatus(read_buffer_block, |
| 1145 | io::MemBlockStatus::DISABLED, read_file_lock, &mem_bloc_lock); |
| 1146 | } |
nothing calls this directly
no test coverage detected