Skip to content

Commit

Permalink
Rework collect_container_info (..) functions (nanocurrency#4736)
Browse files Browse the repository at this point in the history
* Move container info classes to separate file

* Introduce better `container_info` class

* Rename legacy to `container_info_entry`

* Conversion

* Test

* Fixes
  • Loading branch information
pwojcikdev authored Oct 3, 2024
1 parent 1f1c8ab commit ab093d5
Show file tree
Hide file tree
Showing 92 changed files with 742 additions and 701 deletions.
21 changes: 21 additions & 0 deletions nano/core_test/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3794,4 +3794,25 @@ TEST (node, local_block_broadcast)
node1.network.merge_peer (node2.network.endpoint ());
ASSERT_TIMELY (5s, node1.network.find_node_id (node2.get_node_id ()));
ASSERT_TIMELY (10s, node2.block (send1->hash ()));
}

TEST (node, container_info)
{
nano::test::system system;
auto & node1 = *system.add_node ();
auto & node2 = *system.add_node ();

// Generate some random activity
std::vector<nano::account> accounts;
auto dev_genesis_key = nano::dev::genesis_key;
system.wallet (0)->insert_adhoc (dev_genesis_key.prv);
accounts.push_back (dev_genesis_key.pub);
for (int n = 0; n < 10; ++n)
{
system.generate_activity (node1, accounts);
}

// This should just execute, sanitizers will catch any problems
ASSERT_NO_THROW (node1.container_info ());
ASSERT_NO_THROW (node2.container_info ());
}
2 changes: 2 additions & 0 deletions nano/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ add_library(
config.hpp
config.cpp
configbase.hpp
container_info.hpp
container_info.cpp
diagnosticsconfig.hpp
diagnosticsconfig.cpp
env.hpp
Expand Down
41 changes: 41 additions & 0 deletions nano/lib/container_info.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <nano/lib/container_info.hpp>

nano::container_info_composite::container_info_composite (std::string name) :
name (std::move (name))
{
}

bool nano::container_info_composite::is_composite () const
{
return true;
}

void nano::container_info_composite::add_component (std::unique_ptr<container_info_component> child)
{
children.push_back (std::move (child));
}

std::vector<std::unique_ptr<nano::container_info_component>> const & nano::container_info_composite::get_children () const
{
return children;
}

std::string const & nano::container_info_composite::get_name () const
{
return name;
}

nano::container_info_leaf::container_info_leaf (container_info_entry info) :
info (std::move (info))
{
}

bool nano::container_info_leaf::is_composite () const
{
return false;
}

nano::container_info_entry const & nano::container_info_leaf::get_info () const
{
return info;
}
172 changes: 172 additions & 0 deletions nano/lib/container_info.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#pragma once

#include <list>
#include <memory>
#include <string>
#include <vector>

namespace nano
{
/* These containers are used to collect information about sequence containers.
* It makes use of the composite design pattern to collect information
* from sequence containers and sequence containers inside member variables.
*/
struct container_info_entry
{
std::string name;
size_t count;
size_t sizeof_element;
};

class container_info_component
{
public:
virtual ~container_info_component () = default;
virtual bool is_composite () const = 0;
};

class container_info_composite : public container_info_component
{
public:
container_info_composite (std::string name);
bool is_composite () const override;
void add_component (std::unique_ptr<container_info_component> child);
std::vector<std::unique_ptr<container_info_component>> const & get_children () const;
std::string const & get_name () const;

private:
std::string name;
std::vector<std::unique_ptr<container_info_component>> children;
};

class container_info_leaf : public container_info_component
{
public:
container_info_leaf (container_info_entry);
bool is_composite () const override;
container_info_entry const & get_info () const;

private:
container_info_entry info;
};
}

/*
* New version
*/
namespace nano
{
class container_info;

template <typename T>
concept sized_container = requires (T a) {
typename T::value_type;
{
a.size ()
} -> std::convertible_to<std::size_t>;
};

template <typename T>
concept container_info_collectable = requires (T a) {
{
a.collect_info ()
} -> std::convertible_to<container_info>;
};

class container_info
{
public:
// Child represented as <name, container_info>
// Using pair to avoid problems with incomplete types
using child = std::pair<std::string, container_info>;

struct entry
{
std::string name;
std::size_t size;
std::size_t sizeof_element;
};

public:
/**
* Adds a subcontainer
*/
void add (std::string const & name, container_info const & info)
{
children_m.emplace_back (name, info);
}

template <container_info_collectable T>
void add (std::string const & name, T const & container)
{
add (name, container.collect_info ());
}

/**
* Adds an entry to this container
*/
void put (std::string const & name, std::size_t size, std::size_t sizeof_element = 0)
{
entries_m.emplace_back (entry{ name, size, sizeof_element });
}

template <class T>
void put (std::string const & name, std::size_t size)
{
put (name, size, sizeof (T));
}

template <sized_container T>
void put (std::string const & name, T const & container)
{
put (name, container.size (), sizeof (typename T::value_type));
}

public:
bool children_empty () const
{
return children_m.empty ();
}

auto const & children () const
{
return children_m;
}

bool entries_empty () const
{
return entries_m.empty ();
}

auto const & entries () const
{
return entries_m;
}

public:
// Needed to convert to legacy container_info_component during transition period
std::unique_ptr<nano::container_info_component> to_legacy (std::string const & name) const
{
auto composite = std::make_unique<nano::container_info_composite> (name);

// Add entries as leaf components
for (const auto & entry : entries_m)
{
nano::container_info_entry info{ entry.name, entry.size, entry.sizeof_element };
composite->add_component (std::make_unique<nano::container_info_leaf> (info));
}

// Recursively convert children to composites and add them
for (const auto & [child_name, child] : children_m)
{
composite->add_component (child.to_legacy (child_name));
}

return composite;
}

private:
std::list<child> children_m;
std::list<entry> entries_m;
};
}
18 changes: 11 additions & 7 deletions nano/lib/observer_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,19 @@ class observer_set final
return observers.empty ();
}

std::unique_ptr<container_info_component> collect_container_info (std::string const & name) const
size_t size () const
{
nano::lock_guard<nano::mutex> lock{ mutex };
return observers.size ();
}

nano::container_info container_info () const
{
nano::unique_lock<nano::mutex> lock{ mutex };
auto count = observers.size ();
lock.unlock ();
auto sizeof_element = sizeof (typename decltype (observers)::value_type);
auto composite = std::make_unique<container_info_composite> (name);
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "observers", count, sizeof_element }));
return composite;

nano::container_info info;
info.put ("observers", observers);
return info;
}

private:
Expand Down
10 changes: 5 additions & 5 deletions nano/lib/processing_queue.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <nano/lib/container_info.hpp>
#include <nano/lib/locks.hpp>
#include <nano/lib/numbers.hpp>
#include <nano/lib/stats.hpp>
Expand Down Expand Up @@ -107,14 +108,13 @@ class processing_queue final
return queue.size ();
}

public: // Container info
std::unique_ptr<container_info_component> collect_container_info (std::string const & name) const
nano::container_info container_info () const
{
nano::lock_guard<nano::mutex> guard{ mutex };

auto composite = std::make_unique<container_info_composite> (name);
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "queue", queue.size (), sizeof (typename decltype (queue)::value_type) }));
return composite;
nano::container_info info;
info.put ("queue", queue);
return info;
}

private:
Expand Down
8 changes: 4 additions & 4 deletions nano/lib/thread_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ void nano::thread_pool::set_thread_names (nano::thread_role::name thread_name)
thread_names_latch.wait ();
}

std::unique_ptr<nano::container_info_component> nano::thread_pool::collect_container_info (std::string const & name) const
nano::container_info nano::thread_pool::container_info () const
{
auto composite = std::make_unique<container_info_composite> (name);
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "count", num_queued_tasks (), sizeof (std::function<void ()>) }));
return composite;
nano::container_info info;
info.put ("count", num_queued_tasks ());
return info;
}
2 changes: 1 addition & 1 deletion nano/lib/thread_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class thread_pool final
/** Returns the number of tasks which are awaiting execution by the thread pool **/
uint64_t num_queued_tasks () const;

std::unique_ptr<nano::container_info_component> collect_container_info (std::string const & name) const;
nano::container_info container_info () const;

private:
nano::mutex mutex;
Expand Down
8 changes: 4 additions & 4 deletions nano/lib/uniquer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ class uniquer final
return values.size ();
}

std::unique_ptr<container_info_component> collect_container_info (std::string const & name) const
nano::container_info container_info () const
{
nano::lock_guard<nano::mutex> guard{ mutex };

auto composite = std::make_unique<container_info_composite> (name);
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "cache", values.size (), sizeof (Value) }));
return composite;
nano::container_info info;
info.put ("cache", values);
return info;
}

static std::chrono::milliseconds constexpr cleanup_cutoff{ 500 };
Expand Down
40 changes: 0 additions & 40 deletions nano/lib/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,46 +63,6 @@ void nano::initialize_file_descriptor_limit ()
}
}

nano::container_info_composite::container_info_composite (std::string const & name) :
name (name)
{
}

bool nano::container_info_composite::is_composite () const
{
return true;
}

void nano::container_info_composite::add_component (std::unique_ptr<container_info_component> child)
{
children.push_back (std::move (child));
}

std::vector<std::unique_ptr<nano::container_info_component>> const & nano::container_info_composite::get_children () const
{
return children;
}

std::string const & nano::container_info_composite::get_name () const
{
return name;
}

nano::container_info_leaf::container_info_leaf (const container_info & info) :
info (info)
{
}

bool nano::container_info_leaf::is_composite () const
{
return false;
}

nano::container_info const & nano::container_info_leaf::get_info () const
{
return info;
}

void nano::remove_all_files_in_dir (std::filesystem::path const & dir)
{
for (auto & p : std::filesystem::directory_iterator (dir))
Expand Down
Loading

0 comments on commit ab093d5

Please sign in to comment.