Skip to content

Commit 2602d89

Browse files
committed
txgraph: avoid accessing other Cluster internals (refactor)
This adds 4 functions to Cluster to help implement Merge() and Split() without needing access to the internals of the other Cluster. This is a preparation for a follow-up that will make Clusters a virtual class whose internals are abstracted away.
1 parent 04c808a commit 2602d89

File tree

1 file changed

+50
-36
lines changed

1 file changed

+50
-36
lines changed

src/txgraph.cpp

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <util/vector.h>
1313

1414
#include <compare>
15+
#include <functional>
1516
#include <memory>
1617
#include <set>
1718
#include <span>
@@ -120,9 +121,7 @@ class Cluster
120121
public:
121122
Cluster() noexcept = delete;
122123
/** Construct an empty Cluster. */
123-
explicit Cluster(uint64_t sequence) noexcept;
124-
/** Construct a singleton Cluster. */
125-
explicit Cluster(uint64_t sequence, TxGraphImpl& graph, const FeePerWeight& feerate, GraphIndex graph_index) noexcept;
124+
explicit Cluster(uint64_t sequence) noexcept : m_sequence(sequence) {}
126125

127126
// Cannot move or copy (would invalidate Cluster* in Locator and ClusterSet). */
128127
Cluster(const Cluster&) = delete;
@@ -153,15 +152,25 @@ class Cluster
153152
return m_quality == QualityLevel::NEEDS_SPLIT ||
154153
m_quality == QualityLevel::NEEDS_SPLIT_ACCEPTABLE;
155154
}
155+
156156
/** Total memory usage currently for this Cluster, including all its dynamic memory, plus Cluster
157157
* structure itself, and ClusterSet::m_clusters entry. */
158158
size_t TotalMemoryUsage() const noexcept;
159+
/** Determine the range of DepGraphIndexes used by this Cluster. */
160+
DepGraphIndex GetDepGraphIndexRange() const noexcept { return m_depgraph.PositionRange(); }
159161
/** Get the number of transactions in this Cluster. */
160162
LinearizationIndex GetTxCount() const noexcept { return m_linearization.size(); }
161163
/** Get the total size of the transactions in this Cluster. */
162164
uint64_t GetTotalTxSize() const noexcept;
163165
/** Given a DepGraphIndex into this Cluster, find the corresponding GraphIndex. */
164166
GraphIndex GetClusterEntry(DepGraphIndex index) const noexcept { return m_mapping[index]; }
167+
/** Append a transaction with given GraphIndex at the end of this Cluster and its
168+
* linearization. Return the DepGraphIndex it was placed at. */
169+
DepGraphIndex AppendTransaction(GraphIndex graph_idx, FeePerWeight feerate) noexcept;
170+
/** Add dependencies to a given child in this cluster. */
171+
void AddDependencies(SetType parents, DepGraphIndex child) noexcept;
172+
/** Invoke visitor_fn for each transaction in the cluster, in linearization order, then wipe this Cluster. */
173+
void ExtractTransactions(const std::function<void (DepGraphIndex, GraphIndex, FeePerWeight, SetType)>& visit_fn) noexcept;
165174
/** Figure out what level this Cluster exists at in the graph. In most cases this is known by
166175
* the caller already (see all "int level" arguments below), but not always. */
167176
int GetLevel(const TxGraphImpl& graph) const noexcept;
@@ -186,7 +195,7 @@ class Cluster
186195
// Functions that implement the Cluster-specific side of internal TxGraphImpl mutations.
187196

188197
/** Apply all removals from the front of to_remove that apply to this Cluster, popping them
189-
* off. These must be at least one such entry. */
198+
* off. There must be at least one such entry. */
190199
void ApplyRemovals(TxGraphImpl& graph, int level, std::span<GraphIndex>& to_remove) noexcept;
191200
/** Split this cluster (must have a NEEDS_SPLIT* quality). Returns whether to delete this
192201
* Cluster afterwards. */
@@ -732,6 +741,31 @@ uint64_t Cluster::GetTotalTxSize() const noexcept
732741
return ret;
733742
}
734743

744+
DepGraphIndex Cluster::AppendTransaction(GraphIndex graph_idx, FeePerWeight feerate) noexcept
745+
{
746+
Assume(graph_idx != GraphIndex(-1));
747+
auto ret = m_depgraph.AddTransaction(feerate);
748+
m_mapping.push_back(graph_idx);
749+
m_linearization.push_back(ret);
750+
return ret;
751+
}
752+
753+
void Cluster::AddDependencies(SetType parent, DepGraphIndex child) noexcept
754+
{
755+
m_depgraph.AddDependencies(parent, child);
756+
}
757+
758+
void Cluster::ExtractTransactions(const std::function<void (DepGraphIndex, GraphIndex, FeePerWeight, SetType)>& visit_fn) noexcept
759+
{
760+
for (auto pos : m_linearization) {
761+
visit_fn(pos, m_mapping[pos], FeePerWeight::FromFeeFrac(m_depgraph.FeeRate(pos)), m_depgraph.GetReducedParents(pos));
762+
}
763+
// Purge this Cluster, now that everything has been moved.
764+
m_depgraph = DepGraph<SetType>{};
765+
m_linearization.clear();
766+
m_mapping.clear();
767+
}
768+
735769
int Cluster::GetLevel(const TxGraphImpl& graph) const noexcept
736770
{
737771
// GetLevel() does not work for empty Clusters.
@@ -1072,12 +1106,7 @@ bool Cluster::Split(TxGraphImpl& graph, int level) noexcept
10721106
/** The cluster which transaction originally in position i is moved to. */
10731107
Cluster* new_cluster = remap[i].first;
10741108
// Copy the transaction to the new cluster's depgraph, and remember the position.
1075-
remap[i].second = new_cluster->m_depgraph.AddTransaction(m_depgraph.FeeRate(i));
1076-
// Create new mapping entry.
1077-
new_cluster->m_mapping.push_back(m_mapping[i]);
1078-
// Create a new linearization entry. As we're only appending transactions, they equal the
1079-
// DepGraphIndex.
1080-
new_cluster->m_linearization.push_back(remap[i].second);
1109+
remap[i].second = new_cluster->AppendTransaction(m_mapping[i], FeePerWeight::FromFeeFrac(m_depgraph.FeeRate(i)));
10811110
}
10821111
// Redistribute the dependencies.
10831112
for (auto i : m_linearization) {
@@ -1086,7 +1115,7 @@ bool Cluster::Split(TxGraphImpl& graph, int level) noexcept
10861115
// Copy its parents, translating positions.
10871116
SetType new_parents;
10881117
for (auto par : m_depgraph.GetReducedParents(i)) new_parents.Set(remap[par].second);
1089-
new_cluster->m_depgraph.AddDependencies(new_parents, remap[i].second);
1118+
new_cluster->AddDependencies(new_parents, remap[i].second);
10901119
}
10911120
// Update all the Locators of moved transactions, and memory usage.
10921121
for (Cluster* new_cluster : new_clusters) {
@@ -1104,39 +1133,34 @@ bool Cluster::Split(TxGraphImpl& graph, int level) noexcept
11041133
void Cluster::Merge(TxGraphImpl& graph, int level, Cluster& other) noexcept
11051134
{
11061135
/** Vector to store the positions in this Cluster for each position in other. */
1107-
std::vector<DepGraphIndex> remap(other.m_depgraph.PositionRange());
1136+
std::vector<DepGraphIndex> remap(other.GetDepGraphIndexRange());
11081137
// Iterate over all transactions in the other Cluster (the one being absorbed).
1109-
for (auto pos : other.m_linearization) {
1110-
auto idx = other.m_mapping[pos];
1138+
other.ExtractTransactions([&](DepGraphIndex pos, GraphIndex idx, FeePerWeight feerate, SetType other_parents) noexcept {
11111139
// Copy the transaction into this Cluster, and remember its position.
1112-
auto new_pos = m_depgraph.AddTransaction(other.m_depgraph.FeeRate(pos));
1140+
auto new_pos = m_depgraph.AddTransaction(feerate);
11131141
// Since this cluster must have been made hole-free before being merged into, all added
11141142
// transactions should appear at the end.
11151143
Assume(new_pos == m_mapping.size());
11161144
remap[pos] = new_pos;
11171145
m_mapping.push_back(idx);
11181146
m_linearization.push_back(new_pos);
11191147
// Copy the transaction's dependencies, translating them using remap. Note that since
1120-
// pos iterates over other.m_linearization, which is in topological order, all parents
1121-
// of pos should already be in remap.
1148+
// pos iterates in linearization order, which is topological, all parents of pos should
1149+
// already be in remap.
11221150
SetType parents;
1123-
for (auto par : other.m_depgraph.GetReducedParents(pos)) {
1151+
for (auto par : other_parents) {
11241152
parents.Set(remap[par]);
11251153
}
11261154
m_depgraph.AddDependencies(parents, remap[pos]);
11271155
// Update the transaction's Locator. There is no need to call Updated() to update chunk
11281156
// feerates, as Updated() will be invoked by Cluster::ApplyDependencies on the resulting
1129-
// merged Cluster later anyway).
1157+
// merged Cluster later anyway.
11301158
auto& entry = graph.m_entries[idx];
11311159
// Discard any potential ChunkData prior to modifying the Cluster (as that could
11321160
// invalidate its ordering).
11331161
if (level == 0) graph.ClearChunkData(entry);
11341162
entry.m_locator[level].SetPresent(this, new_pos);
1135-
}
1136-
// Purge the other Cluster, now that everything has been moved.
1137-
other.m_depgraph = DepGraph<SetType>{};
1138-
other.m_linearization.clear();
1139-
other.m_mapping.clear();
1163+
});
11401164
}
11411165

11421166
void Cluster::ApplyDependencies(TxGraphImpl& graph, int level, std::span<std::pair<GraphIndex, GraphIndex>> to_apply) noexcept
@@ -1766,17 +1790,6 @@ void TxGraphImpl::MakeAllAcceptable(int level) noexcept
17661790
}
17671791
}
17681792

1769-
Cluster::Cluster(uint64_t sequence) noexcept : m_sequence{sequence} {}
1770-
1771-
Cluster::Cluster(uint64_t sequence, TxGraphImpl& graph, const FeePerWeight& feerate, GraphIndex graph_index) noexcept :
1772-
m_sequence{sequence}
1773-
{
1774-
// Create a new transaction in the DepGraph, and remember its position in m_mapping.
1775-
auto cluster_idx = m_depgraph.AddTransaction(feerate);
1776-
m_mapping.push_back(graph_index);
1777-
m_linearization.push_back(cluster_idx);
1778-
}
1779-
17801793
TxGraph::Ref TxGraphImpl::AddTransaction(const FeePerWeight& feerate) noexcept
17811794
{
17821795
Assume(m_main_chunkindex_observers == 0 || GetTopLevel() != 0);
@@ -1793,7 +1806,8 @@ TxGraph::Ref TxGraphImpl::AddTransaction(const FeePerWeight& feerate) noexcept
17931806
GetRefIndex(ret) = idx;
17941807
// Construct a new singleton Cluster (which is necessarily optimally linearized).
17951808
bool oversized = uint64_t(feerate.size) > m_max_cluster_size;
1796-
auto cluster = std::make_unique<Cluster>(m_next_sequence_counter++, *this, feerate, idx);
1809+
auto cluster = std::make_unique<Cluster>(m_next_sequence_counter++);
1810+
cluster->AppendTransaction(idx, feerate);
17971811
auto cluster_ptr = cluster.get();
17981812
int level = GetTopLevel();
17991813
auto& clusterset = GetClusterSet(level);

0 commit comments

Comments
 (0)