Delete reps with weight 0 from rep_weight table and cache

This commit is contained in:
Gustav Schauwecker 2024-03-12 13:07:51 +01:00
commit 69f147991c
3 changed files with 78 additions and 24 deletions

View file

@ -668,6 +668,26 @@ TEST (ledger, representation_changes)
ASSERT_EQ (2, rep_weights.representation_get (key1.pub)); ASSERT_EQ (2, rep_weights.representation_get (key1.pub));
} }
TEST (ledger, delete_rep_weight_of_zero)
{
auto store{ nano::test::make_store () };
nano::rep_weights rep_weights{ store->rep_weight };
auto txn{ store->tx_begin_write () };
rep_weights.representation_add (txn, 1, 100);
rep_weights.representation_add_dual (txn, 2, 100, 3, 100);
ASSERT_EQ (3, rep_weights.size ());
ASSERT_EQ (3, store->rep_weight.count (txn));
// set rep weights to 0
rep_weights.representation_add (txn, 1, std::numeric_limits<nano::uint128_t>::max () - 99);
ASSERT_EQ (2, rep_weights.size ());
ASSERT_EQ (2, store->rep_weight.count (txn));
rep_weights.representation_add_dual (txn, 2, std::numeric_limits<nano::uint128_t>::max () - 99, 3, std::numeric_limits<nano::uint128_t>::max () - 99);
ASSERT_EQ (0, rep_weights.size ());
ASSERT_EQ (0, store->rep_weight.count (txn));
}
TEST (ledger, representation) TEST (ledger, representation)
{ {
auto ctx = nano::test::context::ledger_empty (); auto ctx = nano::test::context::ledger_empty ();

View file

@ -7,39 +7,39 @@ nano::rep_weights::rep_weights (nano::store::rep_weight & rep_weight_store_a) :
{ {
} }
void nano::rep_weights::representation_add (store::write_transaction const & txn_a, nano::account const & source_rep_a, nano::uint128_t const & amount_a) void nano::rep_weights::representation_add (store::write_transaction const & txn_a, nano::account const & rep_a, nano::uint128_t const & amount_a)
{ {
auto weight{ rep_weight_store.get (txn_a, source_rep_a) }; auto previous_weight{ rep_weight_store.get (txn_a, rep_a) };
weight += amount_a; auto new_weight = previous_weight + amount_a;
put_store (txn_a, rep_a, previous_weight, new_weight);
nano::lock_guard<nano::mutex> guard (mutex); nano::lock_guard<nano::mutex> guard (mutex);
rep_weight_store.put (txn_a, source_rep_a, weight); put_cache (rep_a, new_weight);
put (source_rep_a, weight);
} }
void nano::rep_weights::representation_add_dual (store::write_transaction const & txn_a, nano::account const & source_rep_1, nano::uint128_t const & amount_1, nano::account const & source_rep_2, nano::uint128_t const & amount_2) void nano::rep_weights::representation_add_dual (store::write_transaction const & txn_a, nano::account const & rep_1, nano::uint128_t const & amount_1, nano::account const & rep_2, nano::uint128_t const & amount_2)
{ {
if (source_rep_1 != source_rep_2) if (rep_1 != rep_2)
{ {
auto rep_1_weight{ rep_weight_store.get (txn_a, source_rep_1) }; auto previous_weight_1{ rep_weight_store.get (txn_a, rep_1) };
auto rep_2_weight{ rep_weight_store.get (txn_a, source_rep_2) }; auto previous_weight_2{ rep_weight_store.get (txn_a, rep_2) };
rep_1_weight += amount_1; auto new_weight_1 = previous_weight_1 + amount_1;
rep_2_weight += amount_2; auto new_weight_2 = previous_weight_2 + amount_2;
rep_weight_store.put (txn_a, source_rep_1, rep_1_weight); put_store (txn_a, rep_1, previous_weight_1, new_weight_1);
rep_weight_store.put (txn_a, source_rep_2, rep_2_weight); put_store (txn_a, rep_2, previous_weight_2, new_weight_2);
nano::lock_guard<nano::mutex> guard (mutex); nano::lock_guard<nano::mutex> guard (mutex);
put (source_rep_1, rep_1_weight); put_cache (rep_1, new_weight_1);
put (source_rep_2, rep_2_weight); put_cache (rep_2, new_weight_2);
} }
else else
{ {
representation_add (txn_a, source_rep_1, amount_1 + amount_2); representation_add (txn_a, rep_1, amount_1 + amount_2);
} }
} }
void nano::rep_weights::representation_put (nano::account const & account_a, nano::uint128_t const & representation_a) void nano::rep_weights::representation_put (nano::account const & account_a, nano::uint128_t const & representation_a)
{ {
nano::lock_guard<nano::mutex> guard (mutex); nano::lock_guard<nano::mutex> guard (mutex);
put (account_a, representation_a); put_cache (account_a, representation_a);
} }
nano::uint128_t nano::rep_weights::representation_get (nano::account const & account_a) const nano::uint128_t nano::rep_weights::representation_get (nano::account const & account_a) const
@ -62,13 +62,22 @@ void nano::rep_weights::copy_from (nano::rep_weights & other_a)
for (auto const & entry : other_a.rep_amounts) for (auto const & entry : other_a.rep_amounts)
{ {
auto prev_amount (get (entry.first)); auto prev_amount (get (entry.first));
put (entry.first, prev_amount + entry.second); put_cache (entry.first, prev_amount + entry.second);
} }
} }
void nano::rep_weights::put (nano::account const & account_a, nano::uint128_union const & representation_a) void nano::rep_weights::put_cache (nano::account const & account_a, nano::uint128_union const & representation_a)
{ {
auto it = rep_amounts.find (account_a); auto it = rep_amounts.find (account_a);
if (representation_a.is_zero ())
{
if (it != rep_amounts.end ())
{
rep_amounts.erase (it);
}
}
else
{
auto amount = representation_a.number (); auto amount = representation_a.number ();
if (it != rep_amounts.end ()) if (it != rep_amounts.end ())
{ {
@ -78,6 +87,22 @@ void nano::rep_weights::put (nano::account const & account_a, nano::uint128_unio
{ {
rep_amounts.emplace (account_a, amount); rep_amounts.emplace (account_a, amount);
} }
}
}
void nano::rep_weights::put_store (store::write_transaction const & txn_a, nano::account const & rep_a, nano::uint128_t const & previous_weight_a, nano::uint128_t const & new_weight_a)
{
if (new_weight_a.is_zero ())
{
if (!previous_weight_a.is_zero ())
{
rep_weight_store.del (txn_a, rep_a);
}
}
else
{
rep_weight_store.put (txn_a, rep_a, new_weight_a);
}
} }
nano::uint128_t nano::rep_weights::get (nano::account const & account_a) const nano::uint128_t nano::rep_weights::get (nano::account const & account_a) const
@ -93,6 +118,12 @@ nano::uint128_t nano::rep_weights::get (nano::account const & account_a) const
} }
} }
std::size_t nano::rep_weights::size () const
{
nano::lock_guard<nano::mutex> guard (mutex);
return rep_amounts.size ();
}
std::unique_ptr<nano::container_info_component> nano::collect_container_info (nano::rep_weights const & rep_weights, std::string const & name) std::unique_ptr<nano::container_info_component> nano::collect_container_info (nano::rep_weights const & rep_weights, std::string const & name)
{ {
size_t rep_amounts_count; size_t rep_amounts_count;

View file

@ -26,13 +26,16 @@ public:
/* Only use this method when loading rep weights from the database table */ /* Only use this method when loading rep weights from the database table */
void representation_put (nano::account const & account_a, nano::uint128_t const & representation_a); void representation_put (nano::account const & account_a, nano::uint128_t const & representation_a);
std::unordered_map<nano::account, nano::uint128_t> get_rep_amounts () const; std::unordered_map<nano::account, nano::uint128_t> get_rep_amounts () const;
/* Only use this method when loading rep weights from the database table */
void copy_from (rep_weights & other_a); void copy_from (rep_weights & other_a);
size_t size () const;
private: private:
mutable nano::mutex mutex; mutable nano::mutex mutex;
std::unordered_map<nano::account, nano::uint128_t> rep_amounts; std::unordered_map<nano::account, nano::uint128_t> rep_amounts;
nano::store::rep_weight & rep_weight_store; nano::store::rep_weight & rep_weight_store;
void put (nano::account const & account_a, nano::uint128_union const & representation_a); void put_cache (nano::account const & account_a, nano::uint128_union const & representation_a);
void put_store (store::write_transaction const & txn_a, nano::account const & rep_a, nano::uint128_t const & previous_weight_a, nano::uint128_t const & new_weight_a);
nano::uint128_t get (nano::account const & account_a) const; nano::uint128_t get (nano::account const & account_a) const;
friend std::unique_ptr<container_info_component> collect_container_info (rep_weights const &, std::string const &); friend std::unique_ptr<container_info_component> collect_container_info (rep_weights const &, std::string const &);