Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
22 changes: 21 additions & 1 deletion components/core/src/clp_s/ffi/sfa/ClpArchiveReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <ystdlib/error_handling/Result.hpp>

#include <clp/BufferReader.hpp>
#include <clp_s/archive_constants.hpp>
#include <clp_s/ArchiveReader.hpp>
#include <clp_s/ffi/sfa/SfaErrorCode.hpp>
#include <clp_s/InputConfig.hpp>
Expand Down Expand Up @@ -107,19 +108,38 @@ auto ClpArchiveReader::close() noexcept -> void {
m_archive_reader.reset();
}
m_event_count = 0;
m_file_names.clear();
m_file_infos.clear();
}

auto ClpArchiveReader::move_from(ClpArchiveReader& rhs) noexcept -> void {
m_archive_reader = std::move(rhs.m_archive_reader);
m_archive_data = std::move(rhs.m_archive_data);
m_event_count = std::exchange(rhs.m_event_count, 0);
m_file_names = std::move(rhs.m_file_names);
m_file_infos = std::move(rhs.m_file_infos);
}

auto ClpArchiveReader::precompute_archive_metadata() -> void {
auto const& range_index{m_archive_reader->get_range_index()};
m_file_names.reserve(range_index.size());
m_file_infos.reserve(range_index.size());

for (auto const& range : range_index) {
m_event_count += static_cast<uint64_t>(range.end_index - range.start_index);
auto const start_idx{static_cast<uint64_t>(range.start_index)};
auto const end_idx{static_cast<uint64_t>(range.end_index)};
m_event_count += end_idx - start_idx;

auto const filename_it{
range.fields.find(std::string{clp_s::constants::range_index::cFilename})
};
if (range.fields.end() == filename_it || false == filename_it->is_string()) {
continue;
}
auto const filename{filename_it->get<std::string>()};

m_file_names.push_back(filename);
m_file_infos.emplace_back(filename, start_idx, end_idx);
}
}
} // namespace clp_s::ffi::sfa
41 changes: 41 additions & 0 deletions components/core/src/clp_s/ffi/sfa/ClpArchiveReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,33 @@ class ArchiveReader;
} // namespace clp_s

namespace clp_s::ffi::sfa {
/**
* Metadata describing a single source file's event-index range within a single-file archive.
*/
class FileInfo {
public:
// Constructor
FileInfo(std::string_view file_name, uint64_t start_index, uint64_t end_index)
: m_file_name{file_name},
m_start_index{start_index},
m_end_index{end_index} {}

// Methods
[[nodiscard]] auto get_file_name() const -> std::string const& { return m_file_name; }

[[nodiscard]] auto get_start_index() const -> uint64_t { return m_start_index; }

[[nodiscard]] auto get_end_index() const -> uint64_t { return m_end_index; }

[[nodiscard]] auto get_event_count() const -> uint64_t { return m_end_index - m_start_index; }

private:
// Members
std::string m_file_name;
uint64_t m_start_index{0};
uint64_t m_end_index{0};
};

/**
* A thin wrapper around `clp_s::ArchiveReader` for single file archive FFI entrypoints.
*/
Expand Down Expand Up @@ -58,6 +85,18 @@ class ClpArchiveReader {
*/
[[nodiscard]] auto get_event_count() const -> uint64_t { return m_event_count; }

/**
* @return Source file names in range-index order.
*/
[[nodiscard]] auto get_file_names() const -> std::vector<std::string> { return m_file_names; }

/**
* @return Source file infos in range-index order.
*/
[[nodiscard]] auto get_file_infos() const -> std::vector<FileInfo> const& {
return m_file_infos;
}

private:
// Constructors
explicit ClpArchiveReader(
Expand Down Expand Up @@ -87,6 +126,8 @@ class ClpArchiveReader {
std::unique_ptr<clp_s::ArchiveReader> m_archive_reader;
std::shared_ptr<std::vector<char>> m_archive_data;
uint64_t m_event_count{0};
std::vector<std::string> m_file_names;
std::vector<FileInfo> m_file_infos;
};
} // namespace clp_s::ffi::sfa

Expand Down
98 changes: 60 additions & 38 deletions components/core/tests/test-clp_s-ffi_sfa_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@
#include <vector>

#include <catch2/catch_test_macros.hpp>
#include <ystdlib/error_handling/Result.hpp>

#include "../src/clp/ReadOnlyMemoryMappedFile.hpp"
#include "../src/clp_s/ffi/sfa/ClpArchiveReader.hpp"
#include "clp_s_test_utils.hpp"
#include "TestOutputCleaner.hpp"

namespace {
using clp::ReadOnlyMemoryMappedFile;
using clp_s::ffi::sfa::ClpArchiveReader;
using ystdlib::error_handling::Result;
using ystdlib::error_handling::success;

constexpr std::string_view cSfaReaderLogsDirectory{"test_log_files"};
constexpr std::string_view cSfaReaderArchiveOutputDirectory{"test-clp_s-ffi_sfa-reader-archive"};
constexpr std::string_view cInputNoFloats{"test_no_floats_sorted.jsonl"};
Expand All @@ -38,7 +44,6 @@ auto generate_single_file_archive(std::filesystem::path const& log_path) -> std:
std::filesystem::create_directories(root_output_dir);

auto const output_dir{root_output_dir / log_path.stem().string()};
std::filesystem::remove_all(output_dir);

auto const archive_stats = compress_archive(
log_path.string(),
Expand All @@ -64,61 +69,78 @@ auto get_num_lines(std::filesystem::path const& path) -> uint64_t {
return num_lines;
}

auto assert_archive_event_count_matches_log(
std::filesystem::path const& archive_path,
uint64_t expected_event_count
) -> void {
REQUIRE(std::filesystem::exists(archive_path));

auto reader_result{clp_s::ffi::sfa::ClpArchiveReader::create(archive_path.string())};
REQUIRE(false == reader_result.has_error());
auto& reader = reader_result.value();

auto assert_reader_matches_expected(ClpArchiveReader const& reader, uint64_t expected_event_count)
-> void {
auto const event_count{reader.get_event_count()};
REQUIRE(event_count == expected_event_count);

auto const file_names{reader.get_file_names()};
auto const& file_infos{reader.get_file_infos()};
REQUIRE(1 == file_names.size());
REQUIRE(1 == file_infos.size());

auto const& file_name{file_names.front()};
auto const& file_info{file_infos.front()};
REQUIRE(false == file_name.empty());
REQUIRE(file_info.get_file_name() == file_name);
REQUIRE(0 == file_info.get_start_index());
REQUIRE(expected_event_count == file_info.get_end_index());
REQUIRE(expected_event_count == file_info.get_event_count());
}

auto assert_archive_event_count_matches_log_in_memory(
auto test_archive_created_from_path(
std::filesystem::path const& archive_path,
uint64_t expected_event_count
) -> void {
REQUIRE(std::filesystem::exists(archive_path));
) -> Result<void> {
auto reader{YSTDLIB_ERROR_HANDLING_TRYX(ClpArchiveReader::create(archive_path.string()))};
assert_reader_matches_expected(reader, expected_event_count);
return success();
}

auto mmap_result{clp::ReadOnlyMemoryMappedFile::create(archive_path.string())};
REQUIRE(false == mmap_result.has_error());
auto& mapped_archive = mmap_result.value();
auto test_archive_created_from_bytes(
std::filesystem::path const& archive_path,
uint64_t expected_event_count
) -> Result<void> {
auto mapped_archive{
YSTDLIB_ERROR_HANDLING_TRYX(ReadOnlyMemoryMappedFile::create(archive_path.string()))
};
auto const view{mapped_archive.get_view()};
REQUIRE(false == view.empty());

auto reader_result{
clp_s::ffi::sfa::ClpArchiveReader::create(std::vector<char>{view.begin(), view.end()})
};
REQUIRE(false == reader_result.has_error());
auto& reader = reader_result.value();

auto const event_count{reader.get_event_count()};
REQUIRE(event_count == expected_event_count);
auto reader{YSTDLIB_ERROR_HANDLING_TRYX(
ClpArchiveReader::create(std::vector<char>{view.begin(), view.end()})
)};
assert_reader_matches_expected(reader, expected_event_count);
return success();
}
} // namespace

TEST_CASE("clp_s_ffi_sfa_reader_matches_test_no_floats_sorted", "[clp-s][ffi][sfa]") {
TestOutputCleaner const test_cleanup{{get_archive_output_root_dir().string()}};
auto const log_path{get_log_local_path(cInputNoFloats)};
auto run_single_log_file_case(std::string_view log_name) -> Result<void> {
auto const log_path{get_log_local_path(log_name)};
REQUIRE(std::filesystem::exists(log_path));

auto const archive_path{generate_single_file_archive(log_path)};
REQUIRE(std::filesystem::exists(archive_path));

auto const expected_event_count{get_num_lines(log_path)};

assert_archive_event_count_matches_log(archive_path, expected_event_count);
assert_archive_event_count_matches_log_in_memory(archive_path, expected_event_count);
YSTDLIB_ERROR_HANDLING_TRYV(test_archive_created_from_path(archive_path, expected_event_count));
YSTDLIB_ERROR_HANDLING_TRYV(
test_archive_created_from_bytes(archive_path, expected_event_count)
);
return success();
}
} // namespace

TEST_CASE("clp_s_ffi_sfa_reader_matches_test_search_float_timestamp", "[clp-s][ffi][sfa]") {
TEST_CASE("clp_s_ffi_sfa_reader", "[clp-s][ffi][sfa]") {
TestOutputCleaner const test_cleanup{{get_archive_output_root_dir().string()}};
auto const log_path{get_log_local_path(cInputFloatTimestamp)};
REQUIRE(std::filesystem::exists(log_path));
auto const archive_path{generate_single_file_archive(log_path)};
auto const expected_event_count{get_num_lines(log_path)};

assert_archive_event_count_matches_log(archive_path, expected_event_count);
assert_archive_event_count_matches_log_in_memory(archive_path, expected_event_count);
SECTION("test_no_floats_sorted") {
auto const test_result{run_single_log_file_case(cInputNoFloats)};
REQUIRE(false == test_result.has_error());
}

SECTION("test_search_float_timestamp") {
auto const test_result{run_single_log_file_case(cInputFloatTimestamp)};
REQUIRE(false == test_result.has_error());
}
}
Loading