Repository navigation
feat(clp-s): Add the write-side implementation for the archive range index. #847
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
eebbcd2
ea8b137
6d4cb44
c79ed57
dce6b6f
e7bb1a2
139d302
c308293
30f4750
fba7785
e868abe
166c770
b9550be
0dd24c4
90415a9
3f3064c
200fd60
2b664fd
36ac56c
7ec7737
2e34156
7cbb060
011bd01
c06163f
c7fc681
a8c3705
47d0e94
36c1fa0
ca4a371
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,6 +58,11 @@ void ArchiveWriter::open(ArchiveWriterOption const& option) { | |
| } | ||
|
|
||
| void ArchiveWriter::close() { | ||
| if (m_range_open) { | ||
| if (auto const rc = close_current_range(); ErrorCodeSuccess != rc) { | ||
| throw OperationFailed(rc, __FILENAME__, __LINE__); | ||
| } | ||
| } | ||
| auto var_dict_compressed_size = m_var_dict->close(); | ||
| auto log_dict_compressed_size = m_log_dict->close(); | ||
| auto array_dict_compressed_size = m_array_dict->close(); | ||
|
|
@@ -145,8 +150,12 @@ void ArchiveWriter::write_archive_metadata( | |
|
|
||
| ZstdCompressor compressor; | ||
| compressor.open(archive_writer, m_compression_level); | ||
| uint8_t const num_packets{3U}; | ||
| compressor.write_numeric_value(num_packets); | ||
| uint8_t num_optional_packets{0ULL}; | ||
| if (false == m_range_index_writer.empty()) { | ||
| ++num_optional_packets; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have any other optional packets?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By the spec I think the timestamp dictionary is optional, but we've always written it even when it is unused for the whole time we've had the metadata section. Should I open an issue to refactor the timestamp dictionary writing code to actually write it only when it is used? |
||
| } | ||
| uint8_t const num_constant_packets{3U}; | ||
| compressor.write_numeric_value<uint8_t>(num_constant_packets + num_optional_packets); | ||
|
|
||
|
gibber9809 marked this conversation as resolved.
Resolved
|
||
| // Write archive info | ||
| ArchiveInfoPacket archive_info{.num_segments = 1}; | ||
|
|
@@ -173,6 +182,11 @@ void ArchiveWriter::write_archive_metadata( | |
| compressor.write_numeric_value(static_cast<uint32_t>(encoded_timestamp_dict.size())); | ||
| compressor.write(encoded_timestamp_dict.data(), encoded_timestamp_dict.size()); | ||
|
|
||
| // Write range index | ||
| if (auto rc = m_range_index_writer.write(compressor); ErrorCodeSuccess != rc) { | ||
| throw OperationFailed(rc, __FILENAME__, __LINE__); | ||
| } | ||
|
|
||
|
gibber9809 marked this conversation as resolved.
Resolved
|
||
| compressor.close(); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,13 +9,15 @@ | |
| #include <vector> | ||
|
|
||
| #include <absl/container/flat_hash_map.h> | ||
| #include <boost/uuid/uuid_io.hpp> | ||
| #include <curl/curl.h> | ||
| #include <simdjson.h> | ||
| #include <spdlog/spdlog.h> | ||
|
|
||
| #include "../clp/ffi/ir_stream/decoding_methods.hpp" | ||
| #include "../clp/ffi/ir_stream/Deserializer.hpp" | ||
| #include "../clp/ffi/ir_stream/IrUnitType.hpp" | ||
| #include "../clp/ffi/ir_stream/protocol_constants.hpp" | ||
| #include "../clp/ffi/KeyValuePairLogEvent.hpp" | ||
| #include "../clp/ffi/SchemaTree.hpp" | ||
| #include "../clp/ffi/Value.hpp" | ||
|
|
@@ -480,6 +482,7 @@ void JsonParser::parse_line(ondemand::value line, int32_t parent_node_id, std::s | |
| } | ||
|
|
||
| bool JsonParser::parse() { | ||
| auto archive_creator_id = boost::uuids::to_string(m_generator()); | ||
| for (auto const& path : m_input_paths) { | ||
| auto reader{ReaderUtils::try_create_reader(path, m_network_auth)}; | ||
| if (nullptr == reader) { | ||
|
|
@@ -504,14 +507,59 @@ bool JsonParser::parse() { | |
| size_t bytes_consumed_up_to_prev_archive = 0; | ||
| size_t bytes_consumed_up_to_prev_record = 0; | ||
|
|
||
| size_t file_split_number{0ULL}; | ||
| int32_t log_event_idx_node_id{}; | ||
| auto add_log_event_idx_node = [&]() { | ||
| auto initialize_fields_for_archive = [&]() -> bool { | ||
| if (m_record_log_order) { | ||
| log_event_idx_node_id | ||
| = add_metadata_field(constants::cLogEventIdxName, NodeType::Integer); | ||
| } | ||
| if (auto const rc = m_archive_writer->add_field_to_current_range( | ||
| std::string{constants::range_index::cFilename}, | ||
| path.path | ||
| ); | ||
| ErrorCodeSuccess != rc) | ||
| { | ||
| SPDLOG_ERROR( | ||
| "Failed to add metadata field \"{}\" ({})", | ||
| constants::range_index::cFilename, | ||
| static_cast<int64_t>(rc) | ||
| ); | ||
| return false; | ||
| } | ||
| if (auto const rc = m_archive_writer->add_field_to_current_range( | ||
| std::string{constants::range_index::cFileSplitNumber}, | ||
| file_split_number | ||
| ); | ||
| ErrorCodeSuccess != rc) | ||
| { | ||
| SPDLOG_ERROR( | ||
| "Failed to add metadata field \"{}\" ({})", | ||
| constants::range_index::cFileSplitNumber, | ||
| static_cast<int64_t>(rc) | ||
| ); | ||
|
gibber9809 marked this conversation as resolved.
Resolved
|
||
| return false; | ||
| } | ||
| if (auto const rc = m_archive_writer->add_field_to_current_range( | ||
| std::string{constants::range_index::cArchiveCreatorId}, | ||
| archive_creator_id | ||
| ); | ||
| ErrorCodeSuccess != rc) | ||
| { | ||
| SPDLOG_ERROR( | ||
| "Failed to add metadata field \"{}\" ({})", | ||
| constants::range_index::cArchiveCreatorId, | ||
| static_cast<int64_t>(rc) | ||
| ); | ||
| return false; | ||
| } | ||
| return true; | ||
|
gibber9809 marked this conversation as resolved.
Resolved
|
||
| }; | ||
| add_log_event_idx_node(); | ||
| if (false == initialize_fields_for_archive()) { | ||
| m_archive_writer->close(); | ||
| return false; | ||
| } | ||
| auto update_fields_after_archive_split = [&]() { ++file_split_number; }; | ||
|
|
||
| while (json_file_iterator.get_json(json_it)) { | ||
| m_current_schema.clear(); | ||
|
|
@@ -571,7 +619,11 @@ bool JsonParser::parse() { | |
| ); | ||
| bytes_consumed_up_to_prev_archive = bytes_consumed_up_to_prev_record; | ||
| split_archive(); | ||
| add_log_event_idx_node(); | ||
| update_fields_after_archive_split(); | ||
| if (false == initialize_fields_for_archive()) { | ||
| m_archive_writer->close(); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| m_current_parsed_message.clear(); | ||
|
|
@@ -603,6 +655,12 @@ bool JsonParser::parse() { | |
| m_archive_writer->close(); | ||
| return false; | ||
| } | ||
|
|
||
| if (auto const rc = m_archive_writer->close_current_range(); ErrorCodeSuccess != rc) { | ||
| SPDLOG_ERROR("Failed to close metadata range: {}", static_cast<int64_t>(rc)); | ||
| m_archive_writer->close(); | ||
| return false; | ||
| } | ||
|
gibber9809 marked this conversation as resolved.
Resolved
|
||
| } | ||
| return true; | ||
| } | ||
|
|
@@ -887,6 +945,7 @@ void JsonParser::parse_kv_log_event(KeyValuePairLogEvent const& kv) { | |
|
|
||
| auto JsonParser::parse_from_ir() -> bool { | ||
| constexpr size_t cDecompressorReadBufferCapacity{64 * 1024}; // 64 KB | ||
| auto archive_creator_id = boost::uuids::to_string(m_generator()); | ||
| for (auto const& path : m_input_paths) { | ||
| auto reader{ReaderUtils::try_create_reader(path, m_network_auth)}; | ||
| if (nullptr == reader) { | ||
|
|
@@ -917,14 +976,83 @@ auto JsonParser::parse_from_ir() -> bool { | |
| auto& deserializer = deserializer_result.value(); | ||
| auto& ir_unit_handler{deserializer.get_ir_unit_handler()}; | ||
|
|
||
| size_t file_split_number{0ULL}; | ||
| int32_t log_event_idx_node_id{}; | ||
| auto add_log_event_idx_node = [&]() { | ||
| auto initialize_fields_for_archive = [&]() -> bool { | ||
| if (m_record_log_order) { | ||
| log_event_idx_node_id | ||
| = add_metadata_field(constants::cLogEventIdxName, NodeType::Integer); | ||
| } | ||
| if (auto const rc = m_archive_writer->add_field_to_current_range( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to deduplicate the code from line 985-1023 with code from line 517-555
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's a bit hard with the way the code is currently written. In general I think we want to deduplicate a lot of the code between the kv-ir/json
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it might be a somewhat substantial refactor to merge the kvir/json parsing flow in a way that lets us share a lot of this code at the moment. I think we could maybe do it by doing something like the Then we could handle most stuff like populating the default metadata fields + adding the Maybe I can put up a github issue to that effect? |
||
| std::string{constants::range_index::cFilename}, | ||
| path.path | ||
| ); | ||
| ErrorCodeSuccess != rc) | ||
| { | ||
| SPDLOG_ERROR( | ||
| "Failed to add metadata field \"{}\" ({})", | ||
| constants::range_index::cFilename, | ||
| static_cast<int64_t>(rc) | ||
| ); | ||
| return false; | ||
| } | ||
| if (auto const rc = m_archive_writer->add_field_to_current_range( | ||
| std::string{constants::range_index::cFileSplitNumber}, | ||
| file_split_number | ||
| ); | ||
| ErrorCodeSuccess != rc) | ||
| { | ||
| SPDLOG_ERROR( | ||
| "Failed to add metadata field \"{}\" ({})", | ||
| constants::range_index::cFileSplitNumber, | ||
| static_cast<int64_t>(rc) | ||
| ); | ||
| return false; | ||
| } | ||
| if (auto const rc = m_archive_writer->add_field_to_current_range( | ||
| std::string{constants::range_index::cArchiveCreatorId}, | ||
| archive_creator_id | ||
| ); | ||
| ErrorCodeSuccess != rc) | ||
| { | ||
| SPDLOG_ERROR( | ||
| "Failed to add metadata field \"{}\" ({})", | ||
| constants::range_index::cArchiveCreatorId, | ||
| static_cast<int64_t>(rc) | ||
| ); | ||
| return false; | ||
| } | ||
| auto const& metadata = deserializer.get_metadata(); | ||
| if (metadata.contains(clp::ffi::ir_stream::cProtocol::Metadata::UserDefinedMetadataKey)) | ||
| { | ||
| for (auto const& [metadata_key, metadata_value] : | ||
| metadata.at(clp::ffi::ir_stream::cProtocol::Metadata::UserDefinedMetadataKey) | ||
| .items()) | ||
| { | ||
| if (auto const rc = m_archive_writer->add_field_to_current_range( | ||
| metadata_key, | ||
| metadata_value | ||
| ); | ||
| ErrorCodeSuccess != rc) | ||
| { | ||
| SPDLOG_ERROR( | ||
| "Failed to add metadata field \"{}\" ({})", | ||
| metadata_key, | ||
| static_cast<int64_t>(rc) | ||
| ); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| }; | ||
| add_log_event_idx_node(); | ||
| if (false == initialize_fields_for_archive()) { | ||
| decompressor.close(); | ||
| m_archive_writer->close(); | ||
| return false; | ||
| } | ||
| auto update_fields_after_archive_split = [&]() { ++file_split_number; }; | ||
|
|
||
| while (true) { | ||
| auto const kv_log_event_result{deserializer.deserialize_next_ir_unit(decompressor)}; | ||
|
|
||
|
|
@@ -979,7 +1107,12 @@ auto JsonParser::parse_from_ir() -> bool { | |
| m_archive_writer->increment_uncompressed_size(curr_pos - last_pos); | ||
| last_pos = curr_pos; | ||
| split_archive(); | ||
| add_log_event_idx_node(); | ||
| update_fields_after_archive_split(); | ||
| if (false == initialize_fields_for_archive()) { | ||
| m_archive_writer->close(); | ||
| decompressor.close(); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| ir_unit_handler.clear(); | ||
|
|
@@ -1004,6 +1137,11 @@ auto JsonParser::parse_from_ir() -> bool { | |
| curr_pos = decompressor.get_pos(); | ||
| m_archive_writer->increment_uncompressed_size(curr_pos - last_pos); | ||
| decompressor.close(); | ||
| if (auto const rc = m_archive_writer->close_current_range(); ErrorCodeSuccess != rc) { | ||
| SPDLOG_ERROR("Failed to close metadata range: {}", static_cast<int64_t>(rc)); | ||
| m_archive_writer->close(); | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is an unknown metadata packet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any metadata packet that this version of the code isn't familiar with. Generally I'm trying to make it so that if you use this version of the code to read a later archive format with more metadata packet types the code will just skip the metadata packet and keep reading as normal.
For this PR specifically it also makes it so that I can split the read side code into a separate PR but let the archive still be readable.