blob: b588c2e602bb00eb19a748b30fcf897f4d6b1b31 [file]
// 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);
}
}