blob: 3e9b917c5819f19496bcc0bf179c220cc879175e [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 "paimon/core/mergetree/spill_writer.h"
#include "paimon/common/utils/arrow/arrow_output_stream_adapter.h"
#include "paimon/common/utils/arrow/arrow_utils.h"
#include "paimon/common/utils/arrow/mem_utils.h"
#include "paimon/common/utils/arrow/status_utils.h"
#include "paimon/common/utils/scope_guard.h"
#include "paimon/core/mergetree/spill_channel_manager.h"
namespace paimon {
SpillWriter::SpillWriter(const std::shared_ptr<FileSystem>& fs,
const std::shared_ptr<arrow::Schema>& schema,
const std::shared_ptr<FileIOChannel::Enumerator>& channel_enumerator,
const std::shared_ptr<SpillChannelManager>& spill_channel_manager,
const std::string& compression, int32_t compression_level,
bool use_threads, const std::shared_ptr<MemoryPool>& pool)
: fs_(fs),
schema_(schema),
channel_enumerator_(channel_enumerator),
spill_channel_manager_(spill_channel_manager),
compression_(compression),
compression_level_(compression_level),
use_threads_(use_threads),
arrow_pool_(GetArrowPool(pool)) {}
Result<std::unique_ptr<SpillWriter>> SpillWriter::Create(
const std::shared_ptr<FileSystem>& fs, const std::shared_ptr<arrow::Schema>& schema,
const std::shared_ptr<FileIOChannel::Enumerator>& channel_enumerator,
const std::shared_ptr<SpillChannelManager>& spill_channel_manager,
const std::string& compression, int32_t compression_level, bool use_threads,
const std::shared_ptr<MemoryPool>& pool) {
std::unique_ptr<SpillWriter> writer(new SpillWriter(fs, schema, channel_enumerator,
spill_channel_manager, compression,
compression_level, use_threads, pool));
PAIMON_RETURN_NOT_OK(writer->Open());
return writer;
}
Status SpillWriter::Open() {
channel_id_ = channel_enumerator_->Next();
auto ipc_write_options = arrow::ipc::IpcWriteOptions::Defaults();
ipc_write_options.memory_pool = arrow_pool_.get();
ipc_write_options.use_threads = use_threads_;
auto cleanup_guard = ScopeGuard([&]() {
arrow_writer_.reset();
arrow_output_stream_adapter_.reset();
if (out_stream_) {
[[maybe_unused]] auto status = out_stream_->Close();
out_stream_.reset();
}
if (!channel_id_.GetPath().empty()) {
[[maybe_unused]] auto status = fs_->Delete(channel_id_.GetPath());
}
});
PAIMON_ASSIGN_OR_RAISE(arrow::Compression::type arrow_compression,
ArrowUtils::GetCompressionType(compression_));
if (!arrow::util::Codec::SupportsCompressionLevel(arrow_compression)) {
compression_level_ = arrow::util::Codec::UseDefaultCompressionLevel();
}
PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(
ipc_write_options.codec, arrow::util::Codec::Create(arrow_compression, compression_level_));
PAIMON_ASSIGN_OR_RAISE(out_stream_, fs_->Create(channel_id_.GetPath(), /*overwrite=*/false));
arrow_output_stream_adapter_ = std::make_shared<ArrowOutputStreamAdapter>(out_stream_);
PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(
arrow_writer_,
arrow::ipc::MakeFileWriter(arrow_output_stream_adapter_, schema_, ipc_write_options));
spill_channel_manager_->AddChannel(channel_id_);
cleanup_guard.Release();
return Status::OK();
}
Status SpillWriter::WriteBatch(const std::shared_ptr<arrow::RecordBatch>& batch) {
PAIMON_RETURN_NOT_OK_FROM_ARROW(arrow_writer_->WriteRecordBatch(*batch));
return Status::OK();
}
Status SpillWriter::Close() {
if (closed_) {
return Status::OK();
}
if (arrow_writer_) {
PAIMON_RETURN_NOT_OK_FROM_ARROW(arrow_writer_->Close());
}
if (out_stream_) {
PAIMON_RETURN_NOT_OK(out_stream_->Close());
}
closed_ = true;
return Status::OK();
}
Result<int64_t> SpillWriter::GetFileSize() const {
if (channel_id_.GetPath().empty()) {
return Status::Invalid("spill writer has no channel id");
}
if (!closed_ && arrow_output_stream_adapter_ != nullptr) {
PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(int64_t file_size, arrow_output_stream_adapter_->Tell());
return file_size;
}
PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<FileStatus> file_status,
fs_->GetFileStatus(channel_id_.GetPath()));
return static_cast<int64_t>(file_status->GetLen());
}
const FileIOChannel::ID& SpillWriter::GetChannelId() const {
return channel_id_;
}
} // namespace paimon