Skip to content
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

feat(ffi): Add support for auto/user-generated KV-pairs in KeyValuePairLogEvent; Detect and invalidate duplicate keys among non-leaf nodes when constructing a KeyValuePairLogEvent. #558

Merged
Show file tree
Hide file tree
Changes from 10 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
296 changes: 227 additions & 69 deletions components/core/src/clp/ffi/KeyValuePairLogEvent.cpp

Large diffs are not rendered by default.

102 changes: 69 additions & 33 deletions components/core/src/clp/ffi/KeyValuePairLogEvent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
namespace clp::ffi {
/**
* A log event containing key-value pairs. Each event contains:
* - A collection of node-ID & value pairs, where each pair represents a leaf `SchemaTreeNode` in
* the `SchemaTree`.
* - A reference to the `SchemaTree`
* - The UTC offset of the current log event
* - A reference to the schema tree of auto-generated keys.
* - A reference to the schema tree of user-generated keys.
* - A collection of auto-generated node-ID & value pairs, where each pair represents a leaf
* `SchemaTree::Node` in the `SchemaTree`.
* - A collection of user-generated node-ID & value pairs, where each pair represents a leaf
* `SchemaTree::Node` in the `SchemaTree`.
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
* - The UTC offset of the current log event.
*/
class KeyValuePairLogEvent {
public:
Expand All @@ -29,15 +32,21 @@ class KeyValuePairLogEvent {

// Factory functions
/**
* @param schema_tree
* @param node_id_value_pairs
* @param auto_generated_schema_tree
* @param user_generated_schema_tree
* @param auto_generated_node_id_value_pairs
* @param user_generated_node_id_value_pairs
* @param utc_offset
* @return A result containing the key-value pair log event or an error code indicating the
* failure. See `validate_node_id_value_pairs` for the possible error codes.
* failure, or an error code indicating the failure:
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
* - std::errc::invalid_argument if any of the given schema tree pointers are null.
* - Forwards `validate_node_id_value_pairs`'s return values.
*/
[[nodiscard]] static auto create(
std::shared_ptr<SchemaTree const> schema_tree,
NodeIdValuePairs node_id_value_pairs,
std::shared_ptr<SchemaTree const> auto_generated_schema_tree,
std::shared_ptr<SchemaTree const> user_generated_schema_tree,
NodeIdValuePairs auto_generated_node_id_value_pairs,
NodeIdValuePairs user_generated_node_id_value_pairs,
UtcOffset utc_offset
) -> OUTCOME_V2_NAMESPACE::std_result<KeyValuePairLogEvent>;

Expand All @@ -53,51 +62,78 @@ class KeyValuePairLogEvent {
~KeyValuePairLogEvent() = default;

// Methods
[[nodiscard]] auto get_schema_tree() const -> SchemaTree const& { return *m_schema_tree; }
[[nodiscard]] auto get_auto_generated_schema_tree() const -> SchemaTree const& {
return *m_auto_generated_schema_tree;
}

[[nodiscard]] auto get_node_id_value_pairs() const -> NodeIdValuePairs const& {
return m_node_id_value_pairs;
[[nodiscard]] auto get_user_generated_schema_tree() const -> SchemaTree const& {
return *m_user_generated_schema_tree;
}

[[nodiscard]] auto get_utc_offset() const -> UtcOffset { return m_utc_offset; }
[[nodiscard]] auto get_auto_generated_node_id_value_pairs() const -> NodeIdValuePairs const& {
return m_auto_generated_node_id_value_pairs;
}

[[nodiscard]] auto get_user_generated_node_id_value_pairs() const -> NodeIdValuePairs const& {
return m_user_generated_node_id_value_pairs;
}

/**
* @return A result containing a bitmap where every bit corresponds to the ID of a node in the
* auto-generated schema tree, and the set bits correspond to the nodes in the subtree defined
* by all paths from the root node to the nodes in `m_auto_generated_node_id_value_pairs`; or an
* error code indicating a failure:
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
* - std::errc::result_out_of_range if a node ID in `m_auto_generated_node_id_value_pairs`
* doesn't exist in the schema tree.
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
*/
[[nodiscard]] auto get_auto_generated_schema_subtree_bitmap(
) const -> OUTCOME_V2_NAMESPACE::std_result<std::vector<bool>>;
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved

/**
* @return A result containing a bitmap where every bit corresponds to the ID of a node in the
* schema tree, and the set bits correspond to the nodes in the subtree defined by all paths
* from the root node to the nodes in `node_id_value_pairs`; or an error code indicating a
* failure:
* - std::errc::result_out_of_range if a node ID in `node_id_value_pairs` doesn't exist in the
* schema tree.
* user-generated schema tree, and the set bits correspond to the nodes in the subtree defined
* by all paths from the root node to the nodes in `m_user_generated_node_id_value_pairs`; or an
* error code indicating a failure:
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
* - std::errc::result_out_of_range if a node ID in `m_user_generated_node_id_value_pairs`
* doesn't exist in the schema tree.
*/
[[nodiscard]] auto get_schema_subtree_bitmap(
[[nodiscard]] auto get_user_generated_schema_subtree_bitmap(
) const -> OUTCOME_V2_NAMESPACE::std_result<std::vector<bool>>;

[[nodiscard]] auto get_utc_offset() const -> UtcOffset { return m_utc_offset; }

/**
* Serializes the log event into a `nlohmann::json` object.
* @return A result containing the serialized JSON object or an error code indicating the
* failure:
* - std::errc::protocol_error if a value in the log event couldn't be decoded or it couldn't be
* inserted into a JSON object.
* - std::errc::result_out_of_range if a node ID in the log event doesn't exist in the schema
* tree.
* Serializes the log event into `nlohmann::json` objects.
* @return A result containing a pair or an error code indicating the failure:
* - The pair:
* - Serialized auto-generated key-value pairs as a JSON object
* - Serialized user-generated key-value pairs as a JSON object
* - The possible error codes:
* - Forwards `serialize_node_id_value_pairs_to_json`'s return values on failure.
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
*/
[[nodiscard]] auto serialize_to_json(
) const -> OUTCOME_V2_NAMESPACE::std_result<nlohmann::json>;
) const -> OUTCOME_V2_NAMESPACE::std_result<std::pair<nlohmann::json, nlohmann::json>>;
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved

private:
// Constructor
KeyValuePairLogEvent(
std::shared_ptr<SchemaTree const> schema_tree,
NodeIdValuePairs node_id_value_pairs,
std::shared_ptr<SchemaTree const> auto_generated_schema_tree,
std::shared_ptr<SchemaTree const> user_generated_schema_tree,
NodeIdValuePairs auto_generated_node_id_value_pairs,
NodeIdValuePairs user_generated_node_id_value_pairs,
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
UtcOffset utc_offset
)
: m_schema_tree{std::move(schema_tree)},
m_node_id_value_pairs{std::move(node_id_value_pairs)},
: m_auto_generated_schema_tree{std::move(auto_generated_schema_tree)},
m_user_generated_schema_tree{std::move(user_generated_schema_tree)},
m_auto_generated_node_id_value_pairs{std::move(auto_generated_node_id_value_pairs)},
m_user_generated_node_id_value_pairs{std::move(user_generated_node_id_value_pairs)},
m_utc_offset{utc_offset} {}

// Variables
std::shared_ptr<SchemaTree const> m_schema_tree;
NodeIdValuePairs m_node_id_value_pairs;
std::shared_ptr<SchemaTree const> m_auto_generated_schema_tree;
std::shared_ptr<SchemaTree const> m_user_generated_schema_tree;
NodeIdValuePairs m_auto_generated_node_id_value_pairs;
NodeIdValuePairs m_user_generated_node_id_value_pairs;
UtcOffset m_utc_offset{0};
};
} // namespace clp::ffi
Expand Down
8 changes: 8 additions & 0 deletions components/core/src/clp/ffi/SchemaTree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ class SchemaTree {
// Destructor
~Node() = default;

// Defines default equal-to operator
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
[[nodiscard]] auto operator==(SchemaTree::Node const& rhs) const -> bool = default;
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved

// Methods
[[nodiscard]] auto get_id() const -> id_t { return m_id; }

Expand Down Expand Up @@ -248,6 +251,11 @@ class SchemaTree {
// Destructor
~SchemaTree() = default;

// Equal-to operator
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
[[nodiscard]] auto operator==(SchemaTree const& rhs) const -> bool {
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
return m_tree_nodes == rhs.m_tree_nodes;
}

// Methods
[[nodiscard]] auto get_size() const -> size_t { return m_tree_nodes.size(); }

Expand Down
17 changes: 11 additions & 6 deletions components/core/src/clp/ffi/ir_stream/Deserializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ class Deserializer {
Deserializer(IrUnitHandler ir_unit_handler) : m_ir_unit_handler{std::move(ir_unit_handler)} {}

// Variables
std::shared_ptr<SchemaTree> m_schema_tree{std::make_shared<SchemaTree>()};
std::shared_ptr<SchemaTree> m_auto_generated_schema_tree{std::make_shared<SchemaTree>()};
std::shared_ptr<SchemaTree> m_user_generated_schema_tree{std::make_shared<SchemaTree>()};
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
UtcOffset m_utc_offset{0};
IrUnitHandler m_ir_unit_handler;
bool m_is_complete{false};
Expand Down Expand Up @@ -183,9 +184,13 @@ auto Deserializer<IrUnitHandler>::deserialize_next_ir_unit(ReaderInterface& read
auto const ir_unit_type{optional_ir_unit_type.value()};
switch (ir_unit_type) {
case IrUnitType::LogEvent: {
auto result{
deserialize_ir_unit_kv_pair_log_event(reader, tag, m_schema_tree, m_utc_offset)
};
auto result{deserialize_ir_unit_kv_pair_log_event(
reader,
tag,
m_auto_generated_schema_tree,
m_user_generated_schema_tree,
m_utc_offset
)};
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
if (result.has_error()) {
return result.error();
}
Expand All @@ -207,7 +212,7 @@ auto Deserializer<IrUnitHandler>::deserialize_next_ir_unit(ReaderInterface& read
}

auto const node_locator{result.value()};
if (m_schema_tree->has_node(node_locator)) {
if (m_user_generated_schema_tree->has_node(node_locator)) {
return std::errc::protocol_error;
}

Expand All @@ -217,7 +222,7 @@ auto Deserializer<IrUnitHandler>::deserialize_next_ir_unit(ReaderInterface& read
return ir_error_code_to_errc(err);
}

std::ignore = m_schema_tree->insert_node(node_locator);
std::ignore = m_user_generated_schema_tree->insert_node(node_locator);
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,8 @@ auto deserialize_ir_unit_utc_offset_change(ReaderInterface& reader
auto deserialize_ir_unit_kv_pair_log_event(
ReaderInterface& reader,
encoded_tag_t tag,
std::shared_ptr<SchemaTree> schema_tree,
std::shared_ptr<SchemaTree> auto_generated_schema_tree,
std::shared_ptr<SchemaTree> user_generated_schema_tree,
UtcOffset utc_offset
) -> OUTCOME_V2_NAMESPACE::std_result<KeyValuePairLogEvent> {
auto const schema_result{deserialize_schema(reader, tag)};
Expand Down Expand Up @@ -579,7 +580,9 @@ auto deserialize_ir_unit_kv_pair_log_event(
}

return KeyValuePairLogEvent::create(
std::move(schema_tree),
std::move(auto_generated_schema_tree),
std::move(user_generated_schema_tree),
{},
std::move(node_id_value_pairs),
utc_offset
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ namespace clp::ffi::ir_stream {
* Deserializes a key-value pair log event IR unit.
* @param reader
* @param tag
* @param schema_tree Schema tree used to construct the KV-pair log event.
* @param auto_generated_schema_tree Schema tree of auto-generated keys used to construct the
* KV-pair log event.
* @param user_generated_schema_tree Schema tree of user-generated keys used to construct the
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
* KV-pair log event.
* @param utc_offset UTC offset used to construct the KV-pair log event.
* @return A result containing the deserialized log event or an error code indicating the
* failure:
Expand All @@ -72,7 +75,8 @@ namespace clp::ffi::ir_stream {
[[nodiscard]] auto deserialize_ir_unit_kv_pair_log_event(
ReaderInterface& reader,
encoded_tag_t tag,
std::shared_ptr<SchemaTree> schema_tree,
std::shared_ptr<SchemaTree> auto_generated_schema_tree,
std::shared_ptr<SchemaTree> user_generated_schema_tree,
Copy link
Member

Choose a reason for hiding this comment

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

How about auto_gen_keys_schema_tree and user_gen_keys_schema_tree? The current names sound like the schema trees are auto-generated and user-generated themselves, rather than being based on fields that are auto-generated and user-generated.

Copy link
Member Author

@LinZhihao-723 LinZhihao-723 Dec 9, 2024

Choose a reason for hiding this comment

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

Changed in these two commits: 733c896 and 7338c34

Renamed x_generated_schema_tree to x_gen_keys_schema_tree in every where
Also renamed x_generated_node_id_value_pairs to x_gen_node_id_value_pairs to be consistent

UtcOffset utc_offset
) -> OUTCOME_V2_NAMESPACE::std_result<KeyValuePairLogEvent>;
} // namespace clp::ffi::ir_stream
Expand Down
12 changes: 8 additions & 4 deletions components/core/tests/test-ffi_IrUnitHandlerInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,13 @@ auto test_ir_unit_handler_interface(clp::ffi::ir_stream::IrUnitHandlerInterface

auto test_ir_unit_handler_interface(clp::ffi::ir_stream::IrUnitHandlerInterface auto& handler
) -> void {
auto test_log_event_result{
KeyValuePairLogEvent::create(std::make_shared<SchemaTree>(), {}, cTestUtcOffset)
};
auto test_log_event_result{KeyValuePairLogEvent::create(
std::make_shared<SchemaTree>(),
std::make_shared<SchemaTree>(),
{},
{},
cTestUtcOffset
)};
REQUIRE(
(false == test_log_event_result.has_error()
&& IRErrorCode::IRErrorCode_Success
Expand Down Expand Up @@ -127,7 +131,7 @@ TEMPLATE_TEST_CASE(
REQUIRE(
(optional_log_event.has_value()
&& optional_log_event.value().get_utc_offset() == cTestUtcOffset
&& optional_log_event.value().get_node_id_value_pairs().empty())
&& optional_log_event.value().get_user_generated_node_id_value_pairs().empty())
);
auto const& optional_schema_tree_locator{handler.get_schema_tree_node_locator()};
REQUIRE(
Expand Down
Loading
Loading