mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
This change replaces all include guards in the `src/` and `include/` directories by `#pragma once`.
330 lines
8.0 KiB
C++
330 lines
8.0 KiB
C++
#pragma once
|
|
|
|
#include <test/csf/SimTime.h>
|
|
#include <test/csf/events.h>
|
|
|
|
namespace xrpl {
|
|
namespace test {
|
|
namespace csf {
|
|
|
|
/** Holds a type-erased reference to an arbitrary collector.
|
|
|
|
A collector is any class that implements
|
|
|
|
on(NodeID, SimTime, Event)
|
|
|
|
for all events emitted by a Peer.
|
|
|
|
This class is used to type-erase the actual collector used by each peer in
|
|
the simulation. The idea is to compose complicated and typed collectors
|
|
using the helpers in collectors.h, then only type erase at the higher-most
|
|
level when adding to the simulation.
|
|
|
|
The example code below demonstrates the reason for storing the collector
|
|
as a reference. The collector's lifetime will generally be longer than
|
|
the simulation; perhaps several simulations are run for a single collector
|
|
instance. The collector potentially stores lots of data as well, so the
|
|
simulation needs to point to the single instance, rather than requiring
|
|
collectors to manage copying that data efficiently in their design.
|
|
|
|
@code
|
|
// Initialize a specific collector that might write to a file.
|
|
SomeFancyCollector collector{"out.file"};
|
|
|
|
// Setup your simulation
|
|
Sim sim(trustgraph, topology, collector);
|
|
|
|
// Run the simulation
|
|
sim.run(100);
|
|
|
|
// do any reported related to the collector
|
|
collector.report();
|
|
|
|
@endcode
|
|
|
|
@note If a new event type is added, it needs to be added to the interfaces
|
|
below.
|
|
|
|
*/
|
|
class CollectorRef
|
|
{
|
|
using tp = SimTime;
|
|
|
|
// Interface for type-erased collector instance
|
|
struct ICollector
|
|
{
|
|
virtual ~ICollector() = default;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<Tx> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<TxSet> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<Validation> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<Ledger> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<Proposal> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<Tx> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<TxSet> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<Validation> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<Ledger> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<Proposal> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<Tx> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<TxSet> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<Validation> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<Ledger> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<Proposal> const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, SubmitTx const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, StartRound const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, CloseLedger const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, AcceptLedger const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, WrongPrevLedger const&) = 0;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, FullyValidateLedger const&) = 0;
|
|
};
|
|
|
|
// Bridge between type-ful collector T and type erased instance
|
|
template <class T>
|
|
class Any final : public ICollector
|
|
{
|
|
T& t_;
|
|
|
|
public:
|
|
Any(T& t) : t_{t}
|
|
{
|
|
}
|
|
|
|
// Can't copy
|
|
Any(Any const&) = delete;
|
|
Any&
|
|
operator=(Any const&) = delete;
|
|
|
|
Any(Any&&) = default;
|
|
Any&
|
|
operator=(Any&&) = default;
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<Tx> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<TxSet> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<Validation> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<Ledger> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Share<Proposal> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
void
|
|
on(PeerID node, tp when, Receive<Tx> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<TxSet> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<Validation> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<Ledger> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Receive<Proposal> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
void
|
|
on(PeerID node, tp when, Relay<Tx> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<TxSet> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<Validation> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<Ledger> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, Relay<Proposal> const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, SubmitTx const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, StartRound const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, CloseLedger const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, AcceptLedger const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, WrongPrevLedger const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
|
|
virtual void
|
|
on(PeerID node, tp when, FullyValidateLedger const& e) override
|
|
{
|
|
t_.on(node, when, e);
|
|
}
|
|
};
|
|
|
|
std::unique_ptr<ICollector> impl_;
|
|
|
|
public:
|
|
template <class T>
|
|
CollectorRef(T& t) : impl_{new Any<T>(t)}
|
|
{
|
|
}
|
|
|
|
// Non-copyable
|
|
CollectorRef(CollectorRef const& c) = delete;
|
|
CollectorRef&
|
|
operator=(CollectorRef& c) = delete;
|
|
|
|
CollectorRef(CollectorRef&&) = default;
|
|
CollectorRef&
|
|
operator=(CollectorRef&&) = default;
|
|
|
|
template <class E>
|
|
void
|
|
on(PeerID node, tp when, E const& e)
|
|
{
|
|
impl_->on(node, when, e);
|
|
}
|
|
};
|
|
|
|
/** A container of CollectorRefs
|
|
|
|
A set of CollectorRef instances that process the same events. An event is
|
|
processed by collectors in the order the collectors were added.
|
|
|
|
This class type-erases the collector instances. By contract, the
|
|
Collectors/collectors class/helper in collectors.h are not type erased and
|
|
offer an opportunity for type transformations and combinations with
|
|
improved compiler optimizations.
|
|
*/
|
|
class CollectorRefs
|
|
{
|
|
std::vector<CollectorRef> collectors_;
|
|
|
|
public:
|
|
template <class Collector>
|
|
void
|
|
add(Collector& collector)
|
|
{
|
|
collectors_.emplace_back(collector);
|
|
}
|
|
|
|
template <class E>
|
|
void
|
|
on(PeerID node, SimTime when, E const& e)
|
|
{
|
|
for (auto& c : collectors_)
|
|
{
|
|
c.on(node, when, e);
|
|
}
|
|
}
|
|
};
|
|
|
|
} // namespace csf
|
|
} // namespace test
|
|
} // namespace xrpl
|