| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| #include "runtime/io/disk-file.h" |
| #include <iostream> |
| #include <mutex> |
| #include <thread> |
| #include "common/names.h" |
| #include "runtime/io/local-file-writer.h" |
| #include "util/filesystem-util.h" |
| #include "util/spinlock.h" |
| |
| using namespace impala; |
| using namespace impala::io; |
| |
| static const Status& DISK_FILE_DELETE_FAILED_INCORRECT_STATUS = Status(ErrorMsg::Init( |
| TErrorCode::GENERAL, "DiskFile::Delete() failed with incorrect status")); |
| |
| Status DiskFile::Delete(const unique_lock<shared_mutex>& lock) { |
| DCHECK(lock.mutex() == &physical_file_lock_ && lock.owns_lock()); |
| Status status = Status::OK(); |
| unique_lock<SpinLock> status_l(status_lock_); |
| // No support for remote file deletion yet. |
| if (disk_type_ == DiskFileType::LOCAL_BUFFER || disk_type_ == DiskFileType::LOCAL) { |
| if (is_deleted(status_l)) return DISK_FILE_DELETE_FAILED_INCORRECT_STATUS; |
| if (file_writer_ != nullptr) { |
| // Close the file writer to release the file handle. |
| RETURN_IF_ERROR(file_writer_->Close()); |
| } |
| // Remove the local physical file if it exists. |
| RETURN_IF_ERROR(FileSystemUtil::RemovePaths({path_})); |
| SetStatusLocked(io::DiskFileStatus::DELETED, status_l); |
| } |
| return status; |
| } |
| |
| DiskFile::DiskFile(const string& path, DiskIoMgr* io_mgr) |
| : path_(path), |
| disk_type_(DiskFileType::LOCAL), |
| file_status_(DiskFileStatus::INWRITING), |
| file_writer_(new LocalFileWriter(io_mgr, path.c_str())), |
| space_reserved_(true) {} |
| |
| DiskFile::DiskFile(const string& path, DiskIoMgr* io_mgr, int64_t file_size, |
| DiskFileType disk_type, const hdfsFS* hdfs_conn) |
| : path_(path), |
| file_size_(file_size), |
| disk_type_(disk_type), |
| file_status_(DiskFileStatus::INWRITING) { |
| DCHECK(disk_type != DiskFileType::LOCAL); |
| if (disk_type == DiskFileType::LOCAL_BUFFER) { |
| file_writer_.reset(new LocalFileWriter(io_mgr, path.c_str(), file_size)); |
| hdfs_conn_ = nullptr; |
| space_reserved_.Store(false); |
| } else { |
| DCHECK(hdfs_conn != nullptr); |
| hdfs_conn_ = *hdfs_conn; |
| space_reserved_.Store(true); |
| } |
| } |
| |
| DiskFile::DiskFile(const string& path, DiskIoMgr* io_mgr, int64_t file_size, |
| DiskFileType disk_type, int64_t read_buffer_block_size, int num_read_buffer_blocks) |
| : path_(path), |
| file_size_(file_size), |
| disk_type_(disk_type), |
| file_status_(DiskFileStatus::INWRITING) { |
| DCHECK(disk_type == DiskFileType::LOCAL_BUFFER); |
| hdfs_conn_ = nullptr; |
| space_reserved_.Store(false); |
| file_writer_.reset(new LocalFileWriter(io_mgr, path_.c_str(), file_size)); |
| read_buffer_ = |
| std::make_unique<ReadBuffer>(read_buffer_block_size, num_read_buffer_blocks); |
| } |
| |
| DiskFile::ReadBuffer::ReadBuffer( |
| int64_t read_buffer_block_size, int64_t num_read_buffer_blocks) |
| : read_buffer_block_size_(read_buffer_block_size), |
| num_of_read_buffer_blocks_(num_read_buffer_blocks) { |
| page_cnts_per_block_ = std::make_unique<int64_t[]>(num_read_buffer_blocks); |
| read_buffer_block_offsets_ = std::make_unique<int64_t[]>(num_read_buffer_blocks); |
| memset(page_cnts_per_block_.get(), 0, num_read_buffer_blocks * sizeof(int64_t)); |
| memset(read_buffer_block_offsets_.get(), DISK_FILE_INVALID_FILE_OFFSET, |
| num_read_buffer_blocks * sizeof(int64_t)); |
| for (int i = 0; i < num_read_buffer_blocks; i++) { |
| read_buffer_blocks_.emplace_back(std::make_unique<MemBlock>(i)); |
| } |
| } |
| |
| void MemBlock::Delete(bool* reserved, bool* allocated) { |
| DCHECK(reserved != nullptr); |
| DCHECK(allocated != nullptr); |
| *reserved = false; |
| *allocated = false; |
| unique_lock<SpinLock> lock(mem_block_lock_); |
| switch (status_) { |
| case MemBlockStatus::WRITTEN: |
| case MemBlockStatus::ALLOC: |
| // Release the memory. |
| DCHECK(data_ != nullptr); |
| free(data_); |
| data_ = nullptr; |
| *allocated = true; |
| [[fallthrough]]; |
| case MemBlockStatus::RESERVED: |
| *reserved = true; |
| [[fallthrough]]; |
| default: |
| SetStatusLocked(lock, MemBlockStatus::DISABLED); |
| DCHECK(data_ == nullptr); |
| } |
| } |