From 24696e0ff5d17be4018bac17ab58345b091bb961 Mon Sep 17 00:00:00 2001 From: Jason Dellaluce Date: Fri, 3 May 2024 14:49:14 +0000 Subject: [PATCH] refactor(userspace/libsinsp): minor changes in state API, expose new threadinfo fields * Optimize memory allocations for static fields * Ground work for supporting subtable access and complex state types * Inlining functions wherever possible * Improve checks in static and dynamic state fields defintions * Expose new fields in thread infos Co-authored-by: Gianmatteo Palmieri Signed-off-by: Jason Dellaluce --- userspace/libsinsp/plugin_table_api.cpp | 28 +++---- userspace/libsinsp/state/dynamic_struct.h | 95 +++++++++++++---------- userspace/libsinsp/state/static_struct.h | 70 ++++++++--------- userspace/libsinsp/state/table.h | 63 +++++++++++---- userspace/libsinsp/state/type_info.h | 14 ++-- userspace/libsinsp/test/plugins.ut.cpp | 2 +- userspace/libsinsp/test/state.ut.cpp | 40 ++++++---- userspace/libsinsp/threadinfo.cpp | 71 +++++++++-------- userspace/libsinsp/threadinfo.h | 2 + 9 files changed, 222 insertions(+), 163 deletions(-) diff --git a/userspace/libsinsp/plugin_table_api.cpp b/userspace/libsinsp/plugin_table_api.cpp index a83d962635..e33662cd70 100755 --- a/userspace/libsinsp/plugin_table_api.cpp +++ b/userspace/libsinsp/plugin_table_api.cpp @@ -227,6 +227,8 @@ static inline std::string table_input_error_prefix(const sinsp_plugin* o, ss_plu return "error in state table '" + std::string(i->name) + "' defined by plugin '" + o->name() + "': "; } +static const libsinsp::state::static_struct::field_infos s_empty_static_infos; + // wraps instances of ss_plugin_table_input and makes them comply // to the libsinsp::state::table state tables definition. template @@ -275,11 +277,11 @@ struct plugin_table_wrapper: public libsinsp::state::table ds::field_info f; #define _X(_type, _dtype) \ { \ - f = ds::field_info::build<_type>(res[i].name, i, this, res[i].read_only); \ + f = ds::field_info::build<_type>(res[i].name, i, (uintptr_t) this, res[i].read_only); \ } __PLUGIN_STATETYPE_SWITCH(res[i].field_type); #undef _X - ds::field_infos::add_field(f); + ds::field_infos::add_field_info(f); } } @@ -310,7 +312,7 @@ struct plugin_table_wrapper: public libsinsp::state::table return ret; } - virtual const ds::field_info& add_field(const ds::field_info& field) override + virtual const ds::field_info& add_field_info(const ds::field_info& field) override { auto ret = m_input->fields_ext->add_table_field(m_input->table, field.name().c_str(), typeinfo_to_state_type(field.info())); if (ret == NULL) @@ -327,7 +329,7 @@ struct plugin_table_wrapper: public libsinsp::state::table // lastly, we leverage the base-class implementation to obtain // a reference from our local field definitions copy. - return ds::field_infos::add_field(field); + return ds::field_infos::add_field_info(field); } }; @@ -456,10 +458,9 @@ struct plugin_table_wrapper: public libsinsp::state::table }; plugin_table_wrapper(sinsp_plugin* o, const ss_plugin_table_input* i) - : libsinsp::state::table(i->name, ss::field_infos()), + : libsinsp::state::table(i->name, &s_empty_static_infos), m_owner(o), m_input(copy_and_check_table_input(o, i)), - m_static_fields(), m_dyn_fields(std::make_shared(o, m_input)) { auto t = libsinsp::state::typeinfo::of(); @@ -477,14 +478,13 @@ struct plugin_table_wrapper: public libsinsp::state::table sinsp_plugin* m_owner; owned_table_input_t m_input; - libsinsp::state::static_struct::field_infos m_static_fields; std::shared_ptr m_dyn_fields; - const libsinsp::state::static_struct::field_infos& static_fields() const override + const libsinsp::state::static_struct::field_infos* static_fields() const override { // note: always empty, plugin-defined table have no "static" fields, // all of them are dynamically-discovered at runtime - return m_static_fields; + return &s_empty_static_infos; } std::shared_ptr dynamic_fields() const override @@ -751,7 +751,7 @@ struct sinsp_table_wrapper __CATCH_ERR_MSG(t->m_owner_plugin->m_last_owner_err, { t->m_field_list.clear(); - for (auto& info : t->m_table->static_fields()) + for (auto& info : *t->m_table->static_fields()) { ss_plugin_table_fieldinfo i; i.name = info.second.name().c_str(); @@ -797,9 +797,9 @@ struct sinsp_table_wrapper return static_cast(&it->second); } - fixed_it = t->m_table->static_fields().find(name); + fixed_it = t->m_table->static_fields()->find(name); dyn_it = t->m_table->dynamic_fields()->fields().find(name); - if (fixed_it != t->m_table->static_fields().end() + if (fixed_it != t->m_table->static_fields()->end() && dyn_it != t->m_table->dynamic_fields()->fields().end()) { // todo(jasondellaluce): plugins are not aware of the difference @@ -820,7 +820,7 @@ struct sinsp_table_wrapper return &t->m_field_accessors[name]; \ } __CATCH_ERR_MSG(t->m_owner_plugin->m_last_owner_err, { - if (fixed_it != t->m_table->static_fields().end()) + if (fixed_it != t->m_table->static_fields()->end()) { if (data_type != typeinfo_to_state_type(fixed_it->second.info())) { @@ -872,7 +872,7 @@ struct sinsp_table_wrapper return ret; } - if (t->m_table->static_fields().find(name) != t->m_table->static_fields().end()) + if (t->m_table->static_fields()->find(name) != t->m_table->static_fields()->end()) { t->m_owner_plugin->m_last_owner_err = "can't add dynamic field already defined as static: " + std::string(name); return NULL; diff --git a/userspace/libsinsp/state/dynamic_struct.h b/userspace/libsinsp/state/dynamic_struct.h index 51120d7639..52e0eb08e5 100644 --- a/userspace/libsinsp/state/dynamic_struct.h +++ b/userspace/libsinsp/state/dynamic_struct.h @@ -43,35 +43,35 @@ class dynamic_struct { public: template - static field_info build(const std::string& name, size_t index, void* defsptr, bool readonly=false) + static inline field_info build(const std::string& name, size_t index, uintptr_t defsptr, bool readonly=false) { return field_info(name, index, libsinsp::state::typeinfo::of(), defsptr, readonly); } - field_info(const std::string& n, size_t in, const typeinfo& i, void* defsptr, bool r) + inline field_info(const std::string& n, size_t in, const typeinfo& i, uintptr_t defsptr, bool r) : m_readonly(r), m_index(in), m_name(n), m_info(i), - m_defsptr(defsptr) {} - field_info(): + m_defs_id(defsptr) {} + inline field_info(): m_readonly(true), m_index((size_t) -1), m_name(""), m_info(typeinfo::of()), - m_defsptr(NULL) {} - ~field_info() = default; - field_info(field_info&&) = default; - field_info& operator = (field_info&&) = default; - field_info(const field_info& s) = default; - field_info& operator = (const field_info& s) = default; + m_defs_id((uintptr_t) NULL) {} + inline ~field_info() = default; + inline field_info(field_info&&) = default; + inline field_info& operator = (field_info&&) = default; + inline field_info(const field_info& s) = default; + inline field_info& operator = (const field_info& s) = default; friend inline bool operator==(const field_info& a, const field_info& b) { return a.info() == b.info() && a.name() == b.name() && a.m_index == b.m_index - && a.m_defsptr == b.m_defsptr; + && a.m_defs_id == b.m_defs_id; }; friend inline bool operator!=(const field_info& a, const field_info& b) @@ -79,10 +79,18 @@ class dynamic_struct return !(a == b); }; + /** + * @brief Returns the id of the shared definitions this info belongs to. + */ + inline uintptr_t defs_id() const + { + return m_defs_id; + } + /** * @brief Returns true if the field is read only. */ - bool readonly() const + inline bool readonly() const { return m_readonly; } @@ -98,7 +106,7 @@ class dynamic_struct /** * @brief Returns the name of the field. */ - const std::string& name() const + inline const std::string& name() const { return m_name; } @@ -106,7 +114,7 @@ class dynamic_struct /** * @brief Returns the index of the field. */ - size_t index() const + inline size_t index() const { return m_index; } @@ -114,7 +122,7 @@ class dynamic_struct /** * @brief Returns the type info of the field. */ - const libsinsp::state::typeinfo& info() const + inline const libsinsp::state::typeinfo& info() const { return m_info; } @@ -125,7 +133,7 @@ class dynamic_struct * all instances of structs where it is defined. */ template - field_accessor new_accessor() const + inline field_accessor new_accessor() const { if (!valid()) { @@ -146,7 +154,7 @@ class dynamic_struct size_t m_index; std::string m_name; libsinsp::state::typeinfo m_info; - void* m_defsptr; + uintptr_t m_defs_id; friend class dynamic_struct; }; @@ -159,23 +167,23 @@ class dynamic_struct class field_accessor { public: - field_accessor() = default; - ~field_accessor() = default; - field_accessor(field_accessor&&) = default; - field_accessor& operator = (field_accessor&&) = default; - field_accessor(const field_accessor& s) = default; - field_accessor& operator = (const field_accessor& s) = default; + inline field_accessor() = default; + inline ~field_accessor() = default; + inline field_accessor(field_accessor&&) = default; + inline field_accessor& operator = (field_accessor&&) = default; + inline field_accessor(const field_accessor& s) = default; + inline field_accessor& operator = (const field_accessor& s) = default; /** * @brief Returns the info about the field to which this accessor is tied. */ - const field_info& info() const + inline const field_info& info() const { return m_info; } private: - field_accessor(const field_info& info): m_info(info) { }; + inline explicit field_accessor(const field_info& info): m_info(info) { }; field_info m_info; @@ -192,12 +200,18 @@ class dynamic_struct class field_infos { public: - field_infos() = default; + inline field_infos(): m_defs_id((uintptr_t) this) { }; + inline explicit field_infos(uintptr_t defs_id): m_defs_id(defs_id) { }; virtual ~field_infos() = default; - field_infos(field_infos&&) = default; - field_infos& operator = (field_infos&&) = default; - field_infos(const field_infos& s) = delete; - field_infos& operator = (const field_infos& s) = delete; + inline field_infos(field_infos&&) = default; + inline field_infos& operator = (field_infos&&) = default; + inline field_infos(const field_infos& s) = delete; + inline field_infos& operator = (const field_infos& s) = delete; + + inline uintptr_t id() const + { + return m_defs_id; + } /** * @brief Adds metadata for a new field to the list. An exception is @@ -210,8 +224,8 @@ class dynamic_struct template inline const field_info& add_field(const std::string& name) { - auto field = field_info::build(name, m_definitions.size(), this); - return add_field(field); + auto field = field_info::build(name, m_definitions.size(), id()); + return add_field_info(field); } virtual const std::unordered_map& fields() @@ -220,7 +234,7 @@ class dynamic_struct } protected: - virtual const field_info& add_field(const field_info& field) + virtual const field_info& add_field_info(const field_info& field) { const auto &it = m_definitions.find(field.name()); if (it != m_definitions.end()) @@ -239,17 +253,18 @@ class dynamic_struct return def; } + uintptr_t m_defs_id; std::unordered_map m_definitions; std::vector m_definitions_ordered; friend class dynamic_struct; }; - dynamic_struct(const std::shared_ptr& dynamic_fields) + inline explicit dynamic_struct(const std::shared_ptr& dynamic_fields) : m_fields_len(0), m_fields(), m_dynamic_fields(dynamic_fields) { } - dynamic_struct(dynamic_struct&&) = default; - dynamic_struct& operator = (dynamic_struct&&) = default; - dynamic_struct(const dynamic_struct& s) = default; - dynamic_struct& operator = (const dynamic_struct& s) = default; + inline dynamic_struct(dynamic_struct&&) = default; + inline dynamic_struct& operator = (dynamic_struct&&) = default; + inline dynamic_struct(const dynamic_struct& s) = default; + inline dynamic_struct& operator = (const dynamic_struct& s) = default; virtual ~dynamic_struct() { if (m_dynamic_fields) @@ -301,7 +316,7 @@ class dynamic_struct */ virtual void set_dynamic_fields(const std::shared_ptr& defs) { - if (m_dynamic_fields) + if (m_dynamic_fields && m_dynamic_fields.use_count() > 1) { throw sinsp_exception("dynamic struct defintions set twice"); } @@ -358,7 +373,7 @@ class dynamic_struct { throw sinsp_exception("can't set invalid field in dynamic struct"); } - if (m_dynamic_fields.get() != i.m_defsptr) + if (m_dynamic_fields->id() != i.m_defs_id) { throw sinsp_exception("using dynamic field accessor on struct it was not created from"); } diff --git a/userspace/libsinsp/state/static_struct.h b/userspace/libsinsp/state/static_struct.h index f25f3bb8cf..0b62563b19 100644 --- a/userspace/libsinsp/state/static_struct.h +++ b/userspace/libsinsp/state/static_struct.h @@ -43,16 +43,16 @@ class static_struct class field_info { public: - field_info(): + inline field_info(): m_readonly(true), m_offset((size_t) -1), m_name(""), m_info(typeinfo::of()) {} - ~field_info() = default; - field_info(field_info&&) = default; - field_info& operator = (field_info&&) = default; - field_info(const field_info& s) = default; - field_info& operator = (const field_info& s) = default; + inline ~field_info() = default; + inline field_info(field_info&&) = default; + inline field_info& operator = (field_info&&) = default; + inline field_info(const field_info& s) = default; + inline field_info& operator = (const field_info& s) = default; friend inline bool operator==(const field_info& a, const field_info& b) { @@ -78,7 +78,7 @@ class static_struct /** * @brief Returns true if the field is read only. */ - bool readonly() const + inline bool readonly() const { return m_readonly; } @@ -86,7 +86,7 @@ class static_struct /** * @brief Returns the name of the field. */ - const std::string& name() const + inline const std::string& name() const { return m_name; } @@ -94,7 +94,7 @@ class static_struct /** * @brief Returns the type info of the field. */ - const libsinsp::state::typeinfo& info() const + inline const libsinsp::state::typeinfo& info() const { return m_info; } @@ -105,7 +105,7 @@ class static_struct * all instances of structs where it is defined. */ template - field_accessor new_accessor() const + inline field_accessor new_accessor() const { if (!valid()) { @@ -122,14 +122,14 @@ class static_struct } private: - field_info(const std::string& n, size_t o, const typeinfo& i, bool r) + inline field_info(const std::string& n, size_t o, const typeinfo& i, bool r) : m_readonly(r), m_offset(o), m_name(n), m_info(i) { } template - static field_info _build(const std::string& name, size_t offset, bool readonly=false) + static inline field_info _build(const std::string& name, size_t offset, bool readonly=false) { return field_info(name, offset, libsinsp::state::typeinfo::of(), readonly); } @@ -150,17 +150,17 @@ class static_struct class field_accessor { public: - field_accessor() = default; - ~field_accessor() = default; - field_accessor(field_accessor&&) = default; - field_accessor& operator = (field_accessor&&) = default; - field_accessor(const field_accessor& s) = default; - field_accessor& operator = (const field_accessor& s) = default; + inline field_accessor() = default; + inline ~field_accessor() = default; + inline field_accessor(field_accessor&&) = default; + inline field_accessor& operator = (field_accessor&&) = default; + inline field_accessor(const field_accessor& s) = default; + inline field_accessor& operator = (const field_accessor& s) = default; /** * @brief Returns the info about the field to which this accessor is tied. */ - const field_info& info() const + inline const field_info& info() const { return m_info; } @@ -180,12 +180,12 @@ class static_struct */ using field_infos = std::unordered_map; - static_struct() = default; - virtual ~static_struct() = default; - static_struct(static_struct&&) = default; - static_struct& operator = (static_struct&&) = default; - static_struct(const static_struct& s) = default; - static_struct& operator = (const static_struct& s) = default; + inline static_struct() = default; + inline virtual ~static_struct() = default; + inline static_struct(static_struct&&) = default; + inline static_struct& operator = (static_struct&&) = default; + inline static_struct(const static_struct& s) = default; + inline static_struct& operator = (const static_struct& s) = default; /** * @brief Accesses a field with the given accessor and reads its value. @@ -230,15 +230,14 @@ class static_struct /** * @brief Returns information about all the static fields accessible in a struct. */ - inline const field_infos& static_fields() const + virtual field_infos static_fields() const { - return m_static_fields; + return {}; } protected: /** - * @brief To be used in the constructor of child classes. - * Defines the information about a field defined in the class or struct. + * @brief Defines the information about a field defined in the class or struct. * An exception is thrown if two fields are defined with the same name. * * @tparam T Type of the field. @@ -249,22 +248,19 @@ class static_struct * @param name Display name of the field. */ template - const field_info& define_static_field(const void* thisptr, const T& v, const std::string& name, bool readonly=false) + inline const field_info& define_static_field(field_infos& fields, const void* thisptr, const T& v, const std::string& name, bool readonly=false) const { - const auto &it = m_static_fields.find(name); - if (it != m_static_fields.end()) + const auto &it = fields.find(name); + if (it != fields.end()) { throw sinsp_exception("multiple definitions of static field in struct: " + name); } // todo(jasondellaluce): add extra safety boundary checks here size_t offset = (size_t) (((uintptr_t) &v) - (uintptr_t) thisptr); - m_static_fields.insert({ name, field_info::_build(name, offset, readonly) }); - return m_static_fields.at(name); + fields.insert({ name, field_info::_build(name, offset, readonly) }); + return fields.at(name); } - -private: - field_infos m_static_fields; }; diff --git a/userspace/libsinsp/state/table.h b/userspace/libsinsp/state/table.h index f60c6efa94..d548e69e7c 100644 --- a/userspace/libsinsp/state/table.h +++ b/userspace/libsinsp/state/table.h @@ -46,18 +46,30 @@ struct table_entry: public static_struct, dynamic_struct class base_table { public: - base_table(const std::string& name, const typeinfo& key_info, - const static_struct::field_infos& static_fields) - : m_name(name), + inline base_table( + const std::string& name, + const typeinfo& key_info, + const static_struct::field_infos* static_fields) + : m_this_ptr(this), + m_name(name), m_key_info(key_info), m_static_fields(static_fields), m_dynamic_fields(std::make_shared()) { } virtual ~base_table() = default; - base_table(base_table&&) = default; - base_table& operator = (base_table&&) = default; - base_table(const base_table& s) = delete; - base_table& operator = (const base_table& s) = delete; + inline base_table(base_table&&) = default; + inline base_table& operator = (base_table&&) = default; + inline base_table(const base_table& s) = delete; + inline base_table& operator = (const base_table& s) = delete; + + /** + * @brief Returns a pointer to the area of memory in which this table + * object is allocated. Here for convenience as required in other code parts. + */ + inline const base_table* const& table_ptr() const + { + return m_this_ptr; + } /** * @brief Returns the name of the table. @@ -80,7 +92,7 @@ class base_table * for the value data type of this table. This fields will be accessible * for all the entries of this table. */ - virtual const static_struct::field_infos& static_fields() const + virtual const static_struct::field_infos* static_fields() const { return m_static_fields; } @@ -98,6 +110,19 @@ class base_table return m_dynamic_fields; } + virtual void set_dynamic_fields(std::shared_ptr dynf) + { + if (!dynf) + { + throw sinsp_exception("null definitions passed to set_dynamic_fields"); + } + if (m_dynamic_fields && m_dynamic_fields.use_count() > 1) + { + throw sinsp_exception("can't replace already in-use dynamic fields table definitions"); + } + m_dynamic_fields = dynf; + } + /** * @brief Returns the number of entries present in the table. */ @@ -130,9 +155,10 @@ class base_table virtual bool foreach_entry(std::function pred) = 0; private: + const base_table* m_this_ptr; std::string m_name; typeinfo m_key_info; - static_struct::field_infos m_static_fields; + const static_struct::field_infos* m_static_fields; std::shared_ptr m_dynamic_fields; }; @@ -146,14 +172,14 @@ class table: public base_table "table key types must have a default constructor"); public: - table(const std::string& name, const static_struct::field_infos& static_fields) + inline table(const std::string& name, const static_struct::field_infos* static_fields) : base_table(name, typeinfo::of(), static_fields) {} - table(const std::string& name): table(name, static_struct::field_infos()) {} + inline table(const std::string& name): table(name, _static_fields()) {} virtual ~table() = default; - table(table&&) = default; - table& operator = (table&&) = default; - table(const table& s) = delete; - table& operator = (const table& s) = delete; + inline table(table&&) = default; + inline table& operator = (table&&) = default; + inline table(const table& s) = delete; + inline table& operator = (const table& s) = delete; /** * @brief Returns a pointer to an entry present in the table at the given @@ -187,6 +213,13 @@ class table: public base_table * @return false If an entry was not present at the given key. */ virtual bool erase_entry(const KeyType& key) = 0; + +private: + static inline const static_struct::field_infos* _static_fields() + { + static const static_struct::field_infos s_fields{}; + return &s_fields; + } }; }; // state diff --git a/userspace/libsinsp/state/type_info.h b/userspace/libsinsp/state/type_info.h index 03dbed6a29..7a8efaa99b 100644 --- a/userspace/libsinsp/state/type_info.h +++ b/userspace/libsinsp/state/type_info.h @@ -49,15 +49,15 @@ class typeinfo */ template static inline typeinfo of() { - throw sinsp_exception("state::typeinfo::of invoked for unsupported type"); + throw sinsp_exception("state::typeinfo::of invoked for unsupported type: " + std::string(typeid(T).name())); } - typeinfo() = delete; - ~typeinfo() = default; - typeinfo(typeinfo&&) = default; - typeinfo& operator = (typeinfo&&) = default; - typeinfo(const typeinfo& s) = default; - typeinfo& operator = (const typeinfo& s) = default; + inline typeinfo() = delete; + inline ~typeinfo() = default; + inline typeinfo(typeinfo&&) = default; + inline typeinfo& operator = (typeinfo&&) = default; + inline typeinfo(const typeinfo& s) = default; + inline typeinfo& operator = (const typeinfo& s) = default; friend inline bool operator==(const typeinfo& a, const typeinfo& b) { diff --git a/userspace/libsinsp/test/plugins.ut.cpp b/userspace/libsinsp/test/plugins.ut.cpp index 6b86b03e05..deb874d70a 100644 --- a/userspace/libsinsp/test/plugins.ut.cpp +++ b/userspace/libsinsp/test/plugins.ut.cpp @@ -562,7 +562,7 @@ TEST_F(sinsp_with_test_input, plugin_tables) ASSERT_EQ(table->name(), "plugin_sample"); ASSERT_EQ(table->entries_count(), 0); ASSERT_EQ(table->key_info(), libsinsp::state::typeinfo::of()); - ASSERT_EQ(table->static_fields().size(), 0); + ASSERT_EQ(table->static_fields()->size(), 0); ASSERT_EQ(table->dynamic_fields()->fields().size(), 1); // get an already existing field form the plugin table diff --git a/userspace/libsinsp/test/state.ut.cpp b/userspace/libsinsp/test/state.ut.cpp index 2caebfdc45..eea45cfca5 100644 --- a/userspace/libsinsp/test/state.ut.cpp +++ b/userspace/libsinsp/test/state.ut.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 /* -Copyright (C) 2023 The Falco Authors. +Copyright (C) 2024 The Falco Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -34,22 +34,26 @@ TEST(static_struct, defs_and_access) { struct err_multidef_struct: public libsinsp::state::static_struct { - err_multidef_struct(): m_num(0) + libsinsp::state::static_struct::field_infos static_fields() const override { - define_static_field(this, m_num, "num"); - define_static_field(this, m_num, "num"); + libsinsp::state::static_struct::field_infos ret; + define_static_field(ret, this, m_num, "num"); + define_static_field(ret, this, m_num, "num"); + return ret; } - uint32_t m_num; + uint32_t m_num{0}; }; class sample_struct: public libsinsp::state::static_struct { public: - sample_struct(): m_num(0), m_str() + libsinsp::state::static_struct::field_infos static_fields() const override { - define_static_field(this, m_num, "num"); - define_static_field(this, m_str, "str", true); + libsinsp::state::static_struct::field_infos ret; + define_static_field(ret, this, m_num, "num"); + define_static_field(ret, this, m_str, "str", true); + return ret; } uint32_t get_num() const { return m_num; } @@ -58,23 +62,25 @@ TEST(static_struct, defs_and_access) void set_str(const std::string& v) { m_str = v; } private: - uint32_t m_num; + uint32_t m_num{0}; std::string m_str; }; struct sample_struct2: public libsinsp::state::static_struct { public: - sample_struct2(): m_num(0) + libsinsp::state::static_struct::field_infos static_fields() const override { - define_static_field(this, m_num, "num"); + libsinsp::state::static_struct::field_infos ret; + define_static_field(ret, this, m_num, "num"); + return ret; } - uint32_t m_num; + uint32_t m_num{0}; }; - // test construction errors - ASSERT_ANY_THROW(err_multidef_struct()); + // test errors + ASSERT_ANY_THROW(err_multidef_struct().static_fields()); sample_struct s; const auto& fields = s.static_fields(); @@ -302,7 +308,7 @@ TEST(thread_manager, table_access) { // note: used for regression checks, keep this updated as we make // new fields available - static const int s_threadinfo_static_fields_count = 20; + static const int s_threadinfo_static_fields_count = 24; sinsp inspector; auto table = static_cast*>(inspector.m_thread_manager.get()); @@ -310,7 +316,7 @@ TEST(thread_manager, table_access) // empty table state and info ASSERT_EQ(table->name(), "threads"); ASSERT_EQ(table->key_info(), libsinsp::state::typeinfo::of()); - ASSERT_EQ(table->static_fields(), sinsp_threadinfo().static_fields()); + ASSERT_EQ(*table->static_fields(), sinsp_threadinfo().static_fields()); ASSERT_NE(table->dynamic_fields(), nullptr); ASSERT_EQ(table->dynamic_fields()->fields().size(), 0); ASSERT_EQ(table->entries_count(), 0); @@ -324,7 +330,7 @@ TEST(thread_manager, table_access) auto comm_acc = newt->static_fields().at("comm").new_accessor(); ASSERT_NE(newtinfo, nullptr); ASSERT_EQ(newt->dynamic_fields(), table->dynamic_fields()); - ASSERT_EQ(newt->static_fields(), table->static_fields()); + ASSERT_EQ(newt->static_fields(), *table->static_fields()); ASSERT_EQ(newt->static_fields().size(), s_threadinfo_static_fields_count); newtinfo->m_tid = 999; newtinfo->m_comm = "test"; diff --git a/userspace/libsinsp/threadinfo.cpp b/userspace/libsinsp/threadinfo.cpp index 9a4852cc25..190e0cb9aa 100644 --- a/userspace/libsinsp/threadinfo.cpp +++ b/userspace/libsinsp/threadinfo.cpp @@ -50,54 +50,59 @@ sinsp_threadinfo::sinsp_threadinfo(sinsp* inspector, std::shared_ptr dyn_fields = nullptr); virtual ~sinsp_threadinfo(); + libsinsp::state::static_struct::field_infos static_fields() const override; + /*! \brief Return the name of the process containing this thread, e.g. "top". */