Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion be/src/format/table/iceberg_delete_file_reader_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "io/hdfs_builder.h"
#include "runtime/runtime_state.h"
#include "storage/predicate/column_predicate.h"
#include "util/debug_points.h"

namespace doris {

Expand Down Expand Up @@ -301,6 +302,10 @@ Status read_iceberg_deletion_vector(const TIcebergDeleteFileDesc& delete_file,
if (!delete_file.__isset.content_offset || !delete_file.__isset.content_size_in_bytes) {
return Status::InternalError("Deletion vector is missing content offset or length");
}
DBUG_EXECUTE_IF("IcebergDeleteFileReader.read_deletion_vector.io_error",
{ return Status::IOError("injected Iceberg deletion vector read failure"); });
DBUG_EXECUTE_IF("IcebergDeleteFileReader.read_deletion_vector.should_stop",
{ return Status::EndOfFile("stop read."); });

TFileRangeDesc delete_range = build_iceberg_delete_file_range(delete_file.path);
if (options.fs_name != nullptr && !options.fs_name->empty()) {
Expand All @@ -316,7 +321,7 @@ Status read_iceberg_deletion_vector(const TIcebergDeleteFileDesc& delete_file,
std::vector<char> buf(delete_range.size);
RETURN_IF_ERROR(dv_reader.read_at(delete_range.start_offset,
{buf.data(), cast_set<size_t>(delete_range.size)}));
return decode_iceberg_deletion_vector_buffer(buf.data(), delete_range.size, rows_to_delete);
return decode_deletion_vector_buffer(buf.data(), delete_range.size, rows_to_delete);
}

Status decode_iceberg_deletion_vector_buffer(const char* buf, size_t buffer_size,
Expand Down
26 changes: 19 additions & 7 deletions be/src/format/table/iceberg_reader_mixin.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
Expand Down Expand Up @@ -108,6 +109,16 @@ class IcebergReaderMixin : public BaseReader, public TableSchemaChangeHelper {
_create_topn_row_id_column_iterator = create_func;
}

Status TEST_read_deletion_vector(const std::string& data_file_path,
const TIcebergDeleteFileDesc& delete_file_desc) {
return read_deletion_vector(data_file_path, delete_file_desc);
}

Status TEST_position_delete_base(const std::string& data_file_path,
const std::vector<TIcebergDeleteFileDesc>& delete_files) {
return _position_delete_base(data_file_path, delete_files);
}

protected:
// ---- Hook implementations ----

Expand Down Expand Up @@ -627,18 +638,19 @@ Status IcebergReaderMixin<BaseReader>::_position_delete_base(
Status create_status = Status::OK();
auto* delete_file_cache = _kv_cache->template get<DeleteFile>(
_delet_file_cache_key(delete_file.path), [&]() -> DeleteFile* {
auto* position_delete = new DeleteFile;
auto position_delete = std::make_unique<DeleteFile>();
TFileRangeDesc delete_file_range;
delete_file_range.__set_fs_name(this->get_scan_range().fs_name);
delete_file_range.path = delete_file.path;
delete_file_range.start_offset = 0;
delete_file_range.size = -1;
delete_file_range.file_size = -1;
create_status = _read_position_delete_file(&delete_file_range, position_delete);
create_status =
_read_position_delete_file(&delete_file_range, position_delete.get());
if (!create_status) {
return nullptr;
}
return position_delete;
return position_delete.release();
});
if (create_status.is<ErrorCode::END_OF_FILE>()) {
continue;
Expand All @@ -660,10 +672,10 @@ Status IcebergReaderMixin<BaseReader>::_position_delete_base(
SCOPED_TIMER(_iceberg_profile.delete_rows_sort_time);
_iceberg_delete_rows =
_kv_cache->template get<DeleteRows>(data_file_path, [&]() -> DeleteRows* {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This RAII conversion fixes the DeleteRows builder here, but _position_delete_base still has the same leak pattern in the DeleteFile cache builder just above it: auto* position_delete = new DeleteFile, then _read_position_delete_file(...), and on any non-OK status it returns nullptr. KVCache::get only takes ownership when the builder returns a non-null pointer, so a missing/corrupt position-delete file still leaks the partially built DeleteFile. Please wrap that builder in std::unique_ptr<DeleteFile> too and release only after _read_position_delete_file succeeds.

auto* data_file_position_delete = new DeleteRows;
auto data_file_position_delete = std::make_unique<DeleteRows>();
_sort_delete_rows(delete_rows_array, num_delete_rows,
*data_file_position_delete);
return data_file_position_delete;
return data_file_position_delete.release();
});
set_delete_rows();
COUNTER_UPDATE(_iceberg_profile.num_delete_rows, num_delete_rows);
Expand Down Expand Up @@ -808,7 +820,7 @@ Status IcebergReaderMixin<BaseReader>::read_deletion_vector(
_iceberg_delete_rows = _kv_cache->template get<DeleteRows>(
build_iceberg_deletion_vector_cache_key(data_file_path, delete_file_desc),
[&]() -> DeleteRows* {
auto* delete_rows = new DeleteRows;
auto delete_rows = std::make_unique<DeleteRows>();

roaring::Roaring64Map bitmap;
IcebergDeleteFileReaderOptions options;
Expand All @@ -828,7 +840,7 @@ Status IcebergReaderMixin<BaseReader>::read_deletion_vector(
delete_rows->push_back(*it);
}
COUNTER_UPDATE(_iceberg_profile.num_delete_rows, delete_rows->size());
return delete_rows;
return delete_rows.release();
});

RETURN_IF_ERROR(create_status);
Expand Down
13 changes: 7 additions & 6 deletions be/src/format/table/paimon_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <fmt/format.h>

#include <cstring>
#include <memory>
#include <vector>

#include "common/status.h"
Expand Down Expand Up @@ -134,7 +135,7 @@ Status PaimonOrcReader::_init_deletion_vector() {
using DeleteRows = std::vector<int64_t>;
_delete_rows = _kv_cache->get<DeleteRows>(
build_paimon_deletion_vector_cache_key(deletion_file), [&]() -> DeleteRows* {
auto* delete_rows = new DeleteRows;
auto delete_rows = std::make_unique<DeleteRows>();

TFileRangeDesc delete_range;
delete_range.__set_fs_name(get_scan_range().fs_name);
Expand All @@ -160,12 +161,12 @@ Status PaimonOrcReader::_init_deletion_vector() {

SCOPED_TIMER(_paimon_profile.parse_deletion_vector_time);
create_status = decode_paimon_deletion_vector_buffer(buffer.data(), bytes_read,
delete_rows);
delete_rows.get());
if (!create_status.ok()) [[unlikely]] {
return nullptr;
}
COUNTER_UPDATE(_paimon_profile.num_delete_rows, delete_rows->size());
return delete_rows;
return delete_rows.release();
});
RETURN_IF_ERROR(create_status);
if (!_delete_rows->empty()) [[likely]] {
Expand Down Expand Up @@ -233,7 +234,7 @@ Status PaimonParquetReader::_init_deletion_vector() {
using DeleteRows = std::vector<int64_t>;
_delete_rows = _kv_cache->get<DeleteRows>(
build_paimon_deletion_vector_cache_key(deletion_file), [&]() -> DeleteRows* {
auto* delete_rows = new DeleteRows;
auto delete_rows = std::make_unique<DeleteRows>();

TFileRangeDesc delete_range;
delete_range.__set_fs_name(get_scan_range().fs_name);
Expand All @@ -259,12 +260,12 @@ Status PaimonParquetReader::_init_deletion_vector() {

SCOPED_TIMER(_paimon_profile.parse_deletion_vector_time);
create_status = decode_paimon_deletion_vector_buffer(buffer.data(), bytes_read,
delete_rows);
delete_rows.get());
if (!create_status.ok()) [[unlikely]] {
return nullptr;
}
COUNTER_UPDATE(_paimon_profile.num_delete_rows, delete_rows->size());
return delete_rows;
return delete_rows.release();
});
RETURN_IF_ERROR(create_status);
if (!_delete_rows->empty()) [[likely]] {
Expand Down
4 changes: 4 additions & 0 deletions be/src/format/table/paimon_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class PaimonOrcReader final : public OrcReader, public TableSchemaChangeHelper {
}
~PaimonOrcReader() final = default;

Status TEST_init_deletion_vector() { return _init_deletion_vector(); }

protected:
Status on_before_init_reader(ReaderInitContext* ctx) override;

Expand Down Expand Up @@ -109,6 +111,8 @@ class PaimonParquetReader final : public ParquetReader, public TableSchemaChange
}
~PaimonParquetReader() final = default;

Status TEST_init_deletion_vector() { return _init_deletion_vector(); }

protected:
Status on_before_init_reader(ReaderInitContext* ctx) override;

Expand Down
16 changes: 13 additions & 3 deletions be/src/format_v2/table_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <gen_cpp/Types_types.h>

#include <algorithm>
#include <memory>
#include <ranges>
#include <set>
#include <sstream>
Expand All @@ -46,6 +47,7 @@
#include "format_v2/native/native_reader.h"
#include "format_v2/parquet/parquet_reader.h"
#include "storage/segment/condition_cache.h"
#include "util/debug_points.h"
#include "util/string_util.h"

namespace doris::format {
Expand Down Expand Up @@ -765,7 +767,7 @@ Status TableReader::_parse_delete_predicates(const SplitReadOptions& options) {
Status create_status = Status::OK();

_delete_rows = options.cache->get<DeleteRows>(desc.key, [&]() -> DeleteRows* {
auto* delete_rows = new DeleteRows;
auto delete_rows = std::make_unique<DeleteRows>();

DeletionVectorReader dv_reader(_runtime_state, _scanner_profile, *_scan_params, desc,
_io_ctx.get());
Expand All @@ -776,19 +778,27 @@ Status TableReader::_parse_delete_predicates(const SplitReadOptions& options) {

size_t bytes_read = desc.size;
std::vector<char> buffer(bytes_read);
DBUG_EXECUTE_IF("TableReader.parse_deletion_vector.io_error", {
create_status = Status::IOError("injected format v2 deletion vector read failure");
return nullptr;
});
DBUG_EXECUTE_IF("TableReader.parse_deletion_vector.should_stop", {
create_status = Status::EndOfFile("stop read.");
return nullptr;
});
create_status = dv_reader.read_at(desc.start_offset, {buffer.data(), bytes_read});
if (!create_status.ok()) [[unlikely]] {
return nullptr;
}

const char* buf = buffer.data();
SCOPED_TIMER(_profile.parse_delete_file_time);
create_status = parse_deletion_vector(buf, bytes_read, desc.format, delete_rows);
create_status = parse_deletion_vector(buf, bytes_read, desc.format, delete_rows.get());
if (!create_status.ok()) [[unlikely]] {
return nullptr;
}
COUNTER_UPDATE(_profile.num_delete_rows, delete_rows->size());
return delete_rows;
return delete_rows.release();
});
RETURN_IF_ERROR(create_status);
}
Expand Down
Loading
Loading