+ /* Resample the clock */
+ _clock = lttng::make_unique<lsu::clock_class>();
+
+ _metadata_version++;
+ _reset_metadata();
+ _generate_metadata();
+}
+
+/*
+ * Lookup enumeration by enum ID.
+ *
+ * Note that there is no need to lock the registry session as this only
+ * performs an RCU-protected look-up. The function also return an rcu-protected
+ * reference, which ensures that the caller keeps the RCU read lock until it
+ * disposes of the object.
+ */
+lsu::registry_enum::const_rcu_protected_reference
+lsu::registry_session::get_enumeration(const char *enum_name, uint64_t enum_id) const
+{
+ lsu::registry_enum *reg_enum = NULL;
+ struct lttng_ht_node_str *node;
+ struct lttng_ht_iter iter;
+ lttng::urcu::unique_read_lock rcu_lock;
+ /*
+ * Hack: only the name is used for hashing; the rest of the attributes
+ * can be fudged.
+ */
+ lsu::registry_signed_enum reg_enum_lookup(enum_name, nullptr, 0);
+
+ ASSERT_RCU_READ_LOCKED();
+
+ reg_enum_lookup.id = enum_id;
+ cds_lfht_lookup(_enums->ht,
+ ht_hash_enum((void *) ®_enum_lookup, lttng_ht_seed),
+ ht_match_enum_id, ®_enum_lookup, &iter.iter);
+ node = lttng_ht_iter_get_node_str(&iter);
+ if (!node) {
+ LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
+ "Unknown enumeration referenced by application event field: enum name = `{}`, enum id = {}",
+ enum_name, enum_id));
+ }
+
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_INVALID_OFFSETOF
+ reg_enum = lttng::utils::container_of(node, &lsu::registry_enum::node);
+ DIAGNOSTIC_POP
+
+ return lsu::registry_enum::const_rcu_protected_reference{*reg_enum, std::move(rcu_lock)};
+}
+
+lst::type::cuptr lsu::registry_session::get_packet_header() const
+{
+ lst::structure_type::fields packet_header_fields;
+
+ /* uint32_t magic */
+ packet_header_fields.emplace_back(lttng::make_unique<lst::field>("magic",
+ lttng::make_unique<lst::integer_type>(abi.uint32_t_alignment,
+ abi.byte_order, 32, lst::integer_type::signedness::UNSIGNED,
+ lst::integer_type::base::HEXADECIMAL,
+ std::initializer_list<lst::integer_type::role>({lst::integer_type::role::PACKET_MAGIC_NUMBER}))));
+
+ /* uuid */
+ packet_header_fields.emplace_back(lttng::make_unique<lst::field>("uuid",
+ lttng::make_unique<lst::static_length_blob_type>(0, 16,
+ std::initializer_list<lst::static_length_blob_type::role>({lst::static_length_blob_type::role::TRACE_CLASS_UUID}))));
+
+ /* uint32_t stream_id */
+ packet_header_fields.emplace_back(lttng::make_unique<lst::field>("stream_id",
+ lttng::make_unique<lst::integer_type>(abi.uint32_t_alignment,
+ abi.byte_order, 32, lst::integer_type::signedness::UNSIGNED,
+ lst::integer_type::base::DECIMAL,
+ std::initializer_list<lst::integer_type::role>({lst::integer_type::role::DATA_STREAM_CLASS_ID}))));
+
+ /* uint64_t stream_instance_id */
+ packet_header_fields.emplace_back(lttng::make_unique<lst::field>("stream_instance_id",
+ lttng::make_unique<lst::integer_type>(abi.uint64_t_alignment,
+ abi.byte_order, 64, lst::integer_type::signedness::UNSIGNED,
+ lst::integer_type::base::DECIMAL,
+ std::initializer_list<lst::integer_type::role>({lst::integer_type::role::DATA_STREAM_ID}))));
+
+ return lttng::make_unique<lst::structure_type>(0, std::move(packet_header_fields));
+}
+
+/*
+ * Lookup enumeration by name and comparing enumeration entries.
+ * Needs to be called from RCU read-side critical section.
+ */
+lsu::registry_enum *lsu::registry_session::_lookup_enum(
+ const lsu::registry_enum *reg_enum_lookup) const
+{
+ lsu::registry_enum *reg_enum = NULL;
+ struct lttng_ht_node_str *node;
+ struct lttng_ht_iter iter;
+
+ ASSERT_RCU_READ_LOCKED();
+
+ cds_lfht_lookup(_enums->ht, ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed),
+ ht_match_enum, reg_enum_lookup, &iter.iter);
+ node = lttng_ht_iter_get_node_str(&iter);
+ if (!node) {
+ goto end;
+ }
+
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_INVALID_OFFSETOF
+ reg_enum = lttng::utils::container_of(node, &lsu::registry_enum::node);
+ DIAGNOSTIC_POP
+
+end:
+ return reg_enum;
+}
+
+/*
+ * Create a lsu::registry_enum from the given parameters and add it to the
+ * registry hash table, or find it if already there.
+ *
+ * Should be called with session registry mutex held.
+ *
+ * We receive ownership of entries.
+ */
+void lsu::registry_session::create_or_find_enum(
+ int session_objd, const char *enum_name,
+ struct lttng_ust_ctl_enum_entry *raw_entries, size_t nr_entries,
+ uint64_t *enum_id)
+{
+ struct cds_lfht_node *nodep;
+ lsu::registry_enum *reg_enum = NULL, *old_reg_enum;
+ lttng::urcu::read_lock_guard read_lock_guard;
+ auto entries = lttng::make_unique_wrapper<lttng_ust_ctl_enum_entry, lttng::free>(raw_entries);
+
+ LTTNG_ASSERT(enum_name);
+
+ /*
+ * This should not happen but since it comes from the UST tracer, an
+ * external party, don't assert and simply validate values.
+ */
+ if (session_objd < 0) {
+ LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format(
+ "Invalid parameters used to create or look-up enumeration from registry session: session_objd = {}",
+ session_objd));
+ }
+ if (nr_entries == 0) {
+ LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format(
+ "Invalid parameters used to create or look-up enumeration from registry session: nr_entries = {}",
+ nr_entries));
+ }
+ if (lttng_strnlen(enum_name, LTTNG_UST_ABI_SYM_NAME_LEN) ==
+ LTTNG_UST_ABI_SYM_NAME_LEN) {
+ LTTNG_THROW_INVALID_ARGUMENT_ERROR(
+ "Invalid parameters used to create or look-up enumeration from registry session: enumeration name is not null terminated");