mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
- Separate `Scheduler` from `BasicNetwork`. - Add an event/collector framework for monitoring invariants and calculating statistics. - Allow distinct network and trust connections between Peers. - Add a simple routing strategy to support broadcasting arbitrary messages. - Add a common directed graph (`Digraph`) class for representing network and trust topologies. - Add a `PeerGroup` class for simpler specification of the trust and network topologies. - Add a `LedgerOracle` class to ensure distinct ledger histories and simplify branch checking. - Add a `Submitter` to send transactions in at fixed or random intervals to fixed or random peers. Co-authored-by: Joseph McGee
347 lines
9.1 KiB
C++
347 lines
9.1 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of rippled: https://github.com/ripple/rippled
|
|
Copyright (c) 2012-2017 Ripple Labs Inc
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
#ifndef RIPPLE_TEST_CSF_COLLECTOREF_H_INCLUDED
|
|
#define RIPPLE_TEST_CSF_COLLECTOREF_H_INCLUDED
|
|
|
|
#include <test/csf/events.h>
|
|
#include <test/csf/SimTime.h>
|
|
|
|
namespace ripple {
|
|
namespace test {
|
|
namespace csf {
|
|
|
|
/** Holds a type-erased reference to an arbitray 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 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 ripple
|
|
|
|
#endif
|