| 411 | } |
| 412 | |
| 413 | Status RemoteOperRange::DoFetch() { |
| 414 | hdfsFS hdfs_conn = disk_file_src_->hdfs_conn_; |
| 415 | DCHECK(hdfs_conn != nullptr); |
| 416 | // Fetch the data from the source file (remote) to the destination file (local). |
| 417 | DCHECK(disk_file_dst_ != nullptr); |
| 418 | DCHECK(disk_file_src_ != nullptr); |
| 419 | int64_t buffer_idx = disk_file_dst_->GetReadBufferIndex(offset_); |
| 420 | int64_t local_file_size = disk_file_dst_->GetReadBuffActualSize(buffer_idx); |
| 421 | const string& remote_file_path = disk_file_src_->path(); |
| 422 | DiskQueue* queue = io_mgr_->disk_queues_[disk_id_]; |
| 423 | Status status = Status::OK(); |
| 424 | |
| 425 | // Get the shared lock to prevent the physical files from deletion during the fetching. |
| 426 | // The sequence is to get the local file lock, then remote file lock, or it might meet |
| 427 | // deadlocks. |
| 428 | shared_lock<shared_mutex> dstl(disk_file_dst_->physical_file_lock_); |
| 429 | shared_lock<shared_mutex> srcl(disk_file_src_->physical_file_lock_); |
| 430 | |
| 431 | // Check if the remote file is deleted. |
| 432 | auto src_status = disk_file_src_->GetFileStatus(); |
| 433 | if (src_status != io::DiskFileStatus::PERSISTED) { |
| 434 | DCHECK(src_status == io::DiskFileStatus::DELETED); |
| 435 | return Status(Substitute("File has been deleted, path: '$0'", remote_file_path)); |
| 436 | } |
| 437 | |
| 438 | unique_lock<SpinLock> read_buffer_lock( |
| 439 | *(disk_file_dst_->GetBufferBlockLock(buffer_idx))); |
| 440 | MemBlock* read_buffer_bloc = disk_file_dst_->GetBufferBlock(buffer_idx); |
| 441 | if (disk_file_dst_->IsReadBufferBlockStatus( |
| 442 | read_buffer_bloc, MemBlockStatus::DISABLED, dstl, &read_buffer_lock)) { |
| 443 | // If the read block is disabled, the status doesn't allow any writes to |
| 444 | // the block, probably the query ends or is cancelled. |
| 445 | return Status(Substitute( |
| 446 | "Mem block '$0' has been deleted, path: '$1'", buffer_idx, remote_file_path)); |
| 447 | } |
| 448 | RETURN_IF_ERROR(disk_file_dst_->AllocReadBufferBlockLocked( |
| 449 | read_buffer_bloc, local_file_size, dstl, read_buffer_lock)); |
| 450 | DCHECK(read_buffer_bloc->data() != nullptr); |
| 451 | hdfsFile remote_hdfs_file = |
| 452 | hdfsOpenFile(hdfs_conn, remote_file_path.c_str(), O_RDONLY, 0, 0, block_size_); |
| 453 | if (remote_hdfs_file == nullptr) { |
| 454 | status = Status(TErrorCode::DISK_IO_ERROR, GetBackendString(), |
| 455 | Substitute("Could not open file: $0: $1", remote_file_path, GetStrErrMsg())); |
| 456 | } else { |
| 457 | int ret = [&]() { |
| 458 | ScopedHistogramTimer read_timer(queue->read_latency()); |
| 459 | return hdfsPreadFully(hdfs_conn, remote_hdfs_file, offset_, |
| 460 | read_buffer_bloc->data(), local_file_size); |
| 461 | }(); |
| 462 | if (ret != -1) { |
| 463 | queue->read_size()->Update(local_file_size); |
| 464 | disk_file_dst_->SetReadBufferBlockStatus( |
| 465 | read_buffer_bloc, MemBlockStatus::WRITTEN, dstl, &read_buffer_lock); |
| 466 | } else { |
| 467 | // The caller may need to handle the error, and deal with the read buffer block. |
| 468 | status = Status(TErrorCode::DISK_IO_ERROR, GetBackendString(), |
| 469 | GetHdfsErrorMsg("Error reading from HDFS file: ", remote_file_path)); |
| 470 | } |
no test coverage detected