From 5dda088335f797d067489a47bbce57b6a219b884 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 18 Oct 2013 15:47:32 -0700 Subject: [PATCH] Peerfinder work --- Builds/VisualStudio2012/RippleD.vcxproj | 3 +- .../VisualStudio2012/RippleD.vcxproj.filters | 15 ++-- .../{types => algorithm}/api/CycledSet.h | 3 + src/ripple/peerfinder/api/Endpoint.h | 2 +- src/ripple/peerfinder/impl/Cache.h | 4 +- src/ripple/peerfinder/impl/Endpoint.cpp | 2 +- src/ripple/peerfinder/impl/Logic.h | 24 ++++--- src/ripple/peerfinder/impl/LogicType.h | 34 +++++---- src/ripple/peerfinder/impl/Manager.cpp | 2 +- .../peerfinder/impl/SimpleMonotonicClock.h | 40 ----------- src/ripple/peerfinder/impl/Slots.cpp | 47 ++++++++++--- src/ripple/peerfinder/impl/Slots.h | 31 ++++++--- src/ripple/peerfinder/impl/Tests.cpp | 69 +++++++++++++++++++ src/ripple/peerfinder/ripple_peerfinder.cpp | 6 +- src/ripple/types/ripple_types.h | 1 - src/ripple/validators/ripple_validators.cpp | 1 + src/ripple_app/peers/Peer.cpp | 4 +- src/ripple_app/peers/Peers.cpp | 2 +- src/ripple_data/protocol/ripple.proto | 2 +- 19 files changed, 184 insertions(+), 108 deletions(-) rename src/ripple/{types => algorithm}/api/CycledSet.h (97%) delete mode 100644 src/ripple/peerfinder/impl/SimpleMonotonicClock.h diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index c2311041c8..da7afca75a 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -1654,6 +1654,7 @@ + @@ -1686,6 +1687,7 @@ + @@ -1739,7 +1741,6 @@ - diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index e6671febf8..fd977493e2 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -1104,9 +1104,6 @@ [1] Ripple\types\impl - - [2] Old Ripple\ripple_app\main - [1] Ripple\resource @@ -2232,9 +2229,6 @@ [1] Ripple\peerfinder\impl - - [1] Ripple\types\api - [1] Ripple\peerfinder\impl @@ -2250,9 +2244,6 @@ [1] Ripple\types\api - - [2] Old Ripple\ripple_app\main - [1] Ripple\resource @@ -2307,6 +2298,12 @@ [1] Ripple\resource\impl + + [1] Ripple\algorithm + + + [1] Ripple\peerfinder\impl + diff --git a/src/ripple/types/api/CycledSet.h b/src/ripple/algorithm/api/CycledSet.h similarity index 97% rename from src/ripple/types/api/CycledSet.h rename to src/ripple/algorithm/api/CycledSet.h index cfee794155..a894661713 100644 --- a/src/ripple/types/api/CycledSet.h +++ b/src/ripple/algorithm/api/CycledSet.h @@ -20,6 +20,9 @@ #ifndef RIPPLE_TYPES_CYCLEDSET_H_INCLUDED #define RIPPLE_TYPES_CYCLEDSET_H_INCLUDED +#include "beast/modules/beast_core/system/BeforeBoost.h" +#include + namespace ripple { /** Cycled set of unique keys. diff --git a/src/ripple/peerfinder/api/Endpoint.h b/src/ripple/peerfinder/api/Endpoint.h index ed7d6ef86c..28a62d93ee 100644 --- a/src/ripple/peerfinder/api/Endpoint.h +++ b/src/ripple/peerfinder/api/Endpoint.h @@ -32,7 +32,7 @@ struct Endpoint int hops; uint32 incomingSlotsAvailable; uint32 incomingSlotsMax; - uint32 uptimeMinutes; + uint32 uptimeSeconds; std::string featureList; }; diff --git a/src/ripple/peerfinder/impl/Cache.h b/src/ripple/peerfinder/impl/Cache.h index e5f6564085..8d1459907d 100644 --- a/src/ripple/peerfinder/impl/Cache.h +++ b/src/ripple/peerfinder/impl/Cache.h @@ -90,11 +90,11 @@ public: entry.message.hops = std::min (entry.message.hops, message.hops); // Copy the other fields based on uptime - if (entry.message.uptimeMinutes < message.uptimeMinutes) + if (entry.message.uptimeSeconds < message.uptimeSeconds) { entry.message.incomingSlotsAvailable = message.incomingSlotsAvailable; entry.message.incomingSlotsMax = message.incomingSlotsMax; - entry.message.uptimeMinutes = message.uptimeMinutes; + entry.message.uptimeSeconds = message.uptimeSeconds; entry.message.featureList = message.featureList; } diff --git a/src/ripple/peerfinder/impl/Endpoint.cpp b/src/ripple/peerfinder/impl/Endpoint.cpp index 25ad77c627..d9956abf96 100644 --- a/src/ripple/peerfinder/impl/Endpoint.cpp +++ b/src/ripple/peerfinder/impl/Endpoint.cpp @@ -26,7 +26,7 @@ Endpoint::Endpoint () : hops (0) , incomingSlotsAvailable (0) , incomingSlotsMax (0) - , uptimeMinutes (0) + , uptimeSeconds (0) { } diff --git a/src/ripple/peerfinder/impl/Logic.h b/src/ripple/peerfinder/impl/Logic.h index 9a505b0aa7..a4dc574c9a 100644 --- a/src/ripple/peerfinder/impl/Logic.h +++ b/src/ripple/peerfinder/impl/Logic.h @@ -77,10 +77,12 @@ public: //-------------------------------------------------------------------------- + DiscreteClock m_clock; Callback& m_callback; Store& m_store; Checker& m_checker; Journal m_journal; + Config m_config; // The number of fixed peers that are currently connected @@ -106,20 +108,28 @@ public: //-------------------------------------------------------------------------- Logic ( + DiscreteClock clock, Callback& callback, Store& store, Checker& checker, Journal journal) - : m_callback (callback) + : m_clock (clock) + , m_callback (callback) , m_store (store) , m_checker (checker) , m_journal (journal) , m_fixedPeersConnected (0) + , m_slots (clock) , m_cache (journal) , m_legacyCache (store, journal) { } + DiscreteTime get_now() + { + return m_clock(); + } + /** Stop the logic. This will cancel the current fetch and set the stopping flag to `true` to prevent further fetches. @@ -156,7 +166,7 @@ public: ep.hops = 0; ep.incomingSlotsAvailable = m_slots.inboundSlots; ep.incomingSlotsMax = m_slots.inboundSlotsMaximum; - ep.uptimeMinutes = m_slots.uptimeMinutes(); + ep.uptimeSeconds = m_slots.uptimeSeconds(); return ep; } @@ -208,14 +218,6 @@ public: m_callback.connectPeerEndpoints (list); } - // Returns the number of seconds that have elapsed since some baseline - // event. - // - virtual DiscreteTime get_now() - { - return 0; - } - //-------------------------------------------------------------------------- // // Logic @@ -259,7 +261,7 @@ public: // void cycleCache() { - m_cache.cycle(get_now()); + m_cache.cycle (get_now()); for (Peers::iterator iter (m_peers.begin()); iter != m_peers.end(); ++iter) diff --git a/src/ripple/peerfinder/impl/LogicType.h b/src/ripple/peerfinder/impl/LogicType.h index de90b23a17..c99f249763 100644 --- a/src/ripple/peerfinder/impl/LogicType.h +++ b/src/ripple/peerfinder/impl/LogicType.h @@ -23,28 +23,32 @@ namespace ripple { namespace PeerFinder { -/** Provides the Clock required by Logic's get_now(). - This allows the unit tests to provide its own manual clock. -*/ -template -class LogicType : public Logic +template +class LogicType + : private BaseFromMember + , public Logic { public: - explicit LogicType (Callback& callback, - Store& store, - Checker& checker, - Journal journal) - : Logic (callback, store, checker, journal) + typedef typename DiscreteClockSourceType::DiscreteClockType DiscreteClockType; + + LogicType ( + Callback& callback, + Store& store, + Checker& checker, + Journal journal) + : Logic ( + BaseFromMember ::member(), + callback, + store, + checker, + journal) { } - DiscreteTime get_now () + DiscreteClockSourceType& get_clock() { - return m_clock(); + return BaseFromMember ::member(); } - -private: - Clock m_clock; }; } diff --git a/src/ripple/peerfinder/impl/Manager.cpp b/src/ripple/peerfinder/impl/Manager.cpp index 86a1f31209..1141455639 100644 --- a/src/ripple/peerfinder/impl/Manager.cpp +++ b/src/ripple/peerfinder/impl/Manager.cpp @@ -340,7 +340,7 @@ public: map ["out_desired"] = m_logic.m_slots.outDesired; map ["in_avail"] = m_logic.m_slots.inboundSlots; map ["in_max"] = m_logic.m_slots.inboundSlotsMaximum; - map ["minutes"] = m_logic.m_slots.uptimeMinutes(); + map ["uptime"] = m_logic.m_slots.uptimeSeconds(); map ["round"] = m_logic.m_slots.roundUpwards(); map ["cache"] = uint32(m_logic.m_cache.size()); map ["legacy"] = uint32(m_logic.m_legacyCache.size()); diff --git a/src/ripple/peerfinder/impl/SimpleMonotonicClock.h b/src/ripple/peerfinder/impl/SimpleMonotonicClock.h deleted file mode 100644 index c178ac1b55..0000000000 --- a/src/ripple/peerfinder/impl/SimpleMonotonicClock.h +++ /dev/null @@ -1,40 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 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_PEERFINDER_SIMPLEMONOTONICCLOCK_H_INCLUDED -#define RIPPLE_PEERFINDER_SIMPLEMONOTONICCLOCK_H_INCLUDED - -namespace ripple { -namespace PeerFinder { - -/** Monotonically increasing time value. */ -struct SimpleMonotonicClock -{ - typedef int value_type; - - value_type operator() () const - { - return value_type (RelativeTime::fromStartup().inSeconds()); - } -}; - -} -} - -#endif diff --git a/src/ripple/peerfinder/impl/Slots.cpp b/src/ripple/peerfinder/impl/Slots.cpp index 8f111bc764..6f9eb6827f 100644 --- a/src/ripple/peerfinder/impl/Slots.cpp +++ b/src/ripple/peerfinder/impl/Slots.cpp @@ -20,15 +20,17 @@ namespace ripple { namespace PeerFinder { -Slots::Slots () - : startTime (0) +Slots::Slots (DiscreteClock clock, bool roundUpwards) + : m_clock (clock) + , m_startTime (0) , peerCount (0) , inboundCount (0) , outboundCount (0) + , fixedCount (0) , outDesired (0) , inboundSlots (0) , inboundSlotsMaximum (0) - , m_roundUpwards (Random::getSystemRandom().nextBool()) + , m_roundUpwards (roundUpwards) { } @@ -58,7 +60,7 @@ void Slots::update (Config const& config) void Slots::addPeer (Config const& config, bool inbound) { if (peerCount == 0) - startTime = RelativeTime::fromStartup(); + m_startTime = m_clock(); ++peerCount; if (inbound) @@ -71,24 +73,51 @@ void Slots::addPeer (Config const& config, bool inbound) void Slots::dropPeer (Config const& config, bool inbound) { + bool const wasConnected (connected ()); + --peerCount; if (inbound) --inboundCount; else --outboundCount; - if (peerCount == 0) - startTime = RelativeTime(0); + if (wasConnected && ! connected()) + m_startTime = 0; update (config); } -uint32 Slots::uptimeMinutes () const +bool Slots::roundUpwards () const { - if (startTime.isNotZero()) - return (RelativeTime::fromStartup()-startTime).inMinutes(); + return m_roundUpwards; +} + +bool Slots::connected () const +{ + return (peerCount-fixedCount) >= Config::minOutCount; +} + +uint32 Slots::uptimeSeconds () const +{ + if (m_startTime != 0) + return m_clock() - m_startTime; return 0; } +void Slots::updateConnected () +{ + bool const wasConnected (m_startTime != 0); + bool const isConnected (connected()); + + if (wasConnected && !isConnected) + { + m_startTime = 0; + } + else if (! wasConnected && isConnected) + { + m_startTime = m_clock(); + } +} + } } diff --git a/src/ripple/peerfinder/impl/Slots.h b/src/ripple/peerfinder/impl/Slots.h index f3b1ee14e7..8fc156da2e 100644 --- a/src/ripple/peerfinder/impl/Slots.h +++ b/src/ripple/peerfinder/impl/Slots.h @@ -26,15 +26,14 @@ namespace PeerFinder { class Slots { public: - Slots (); + explicit Slots ( + DiscreteClock clock, + bool roundUpwards = Random::getSystemRandom().nextBool()); void update (Config const& config); void addPeer (Config const& config, bool inbound); void dropPeer (Config const& config, bool inbound); - // Most recent time when we went from 0 to 1 peers - RelativeTime startTime; - // Current total of connected peers that have HELLOed int peerCount; @@ -44,6 +43,10 @@ public: // The portion of peers which are outgoing connections int outboundCount; + // The portion of peers which are the fixed peers. + // Fixed peers don't count towards connection limits. + int fixedCount; + // The number of outgoing peer connections we want (calculated) int outDesired; @@ -53,17 +56,25 @@ public: // The maximum number of incoming slots (calculated) int inboundSlotsMaximum; - // Returns the uptime in minutes + // Returns `true` if we round fractional slot availability upwards + bool roundUpwards () const; + + // Returns `true` if we meet the criteria of + // "connected to the network based on the current values of slots. + // + bool connected () const; + + // Returns the uptime in seconds // Uptime is measured from the last we transitioned from not // being connected to the network, to being connected. // - uint32 uptimeMinutes () const; - - // Returns `true` if we round fractional slot availability upwards - bool roundUpwards () const - { return m_roundUpwards; } + uint32 uptimeSeconds () const; private: + void updateConnected(); + + DiscreteTime m_startTime; + DiscreteClock m_clock; bool m_roundUpwards; }; diff --git a/src/ripple/peerfinder/impl/Tests.cpp b/src/ripple/peerfinder/impl/Tests.cpp index 836d02bbce..664232a620 100644 --- a/src/ripple/peerfinder/impl/Tests.cpp +++ b/src/ripple/peerfinder/impl/Tests.cpp @@ -23,9 +23,78 @@ namespace PeerFinder { class PeerFinderTests : public UnitTest { public: + // Complete Logic used for tests + // + class TestLogic + : public LogicType + , public Callback + , public Store + , public Checker + { + public: + Journal m_journal; + + explicit TestLogic (Journal journal) + : LogicType (*this, *this, *this, journal) + , m_journal (journal) + { + } + + // + // Callback + // + + void sendPeerEndpoints (PeerID const& id, + std::vector const& endpoints) + { + } + + void connectPeerEndpoints (std::vector const& list) + { + } + + void chargePeerLoadPenalty (PeerID const& id) + { + } + + // + // Store + // + + void loadLegacyEndpoints (std::vector & list) + { + } + + void updateLegacyEndpoints (std::vector const& list) + { + } + + // + // Checker + // + + void cancel () + { + } + + void async_test (IPAddress const& address, + AbstractHandler handler) + { + Checker::Result result; + result.address = address; + result.canAccept = false; + handler (result); + } + }; + + //-------------------------------------------------------------------------- + void runTest () { beginTestCase ("logic"); + + TestLogic logic (journal()); + pass (); } diff --git a/src/ripple/peerfinder/ripple_peerfinder.cpp b/src/ripple/peerfinder/ripple_peerfinder.cpp index 51b18d5e19..299a388635 100644 --- a/src/ripple/peerfinder/ripple_peerfinder.cpp +++ b/src/ripple/peerfinder/ripple_peerfinder.cpp @@ -21,7 +21,8 @@ #include "ripple_peerfinder.h" -#include "../../ripple/types/ripple_types.h" +#include "../../ripple/algorithm/api/CycledSet.h" +#include "../../ripple/algorithm/api/DiscreteClock.h" #include @@ -42,7 +43,6 @@ namespace ripple { using namespace beast; } -#include "impl/SimpleMonotonicClock.h" #include "impl/PrivateTypes.h" # include "impl/Tuning.h" # include "impl/Checker.h" @@ -57,8 +57,8 @@ using namespace beast; # include "impl/LegacyEndpointCache.h" # include "impl/PeerInfo.h" #include "impl/StoreSqdb.h" +# include "impl/LogicType.h" #include "impl/Logic.h" -#include "impl/LogicType.h" #include "impl/Checker.cpp" #include "impl/Config.cpp" diff --git a/src/ripple/types/ripple_types.h b/src/ripple/types/ripple_types.h index d5b20f506c..ee03dc640a 100644 --- a/src/ripple/types/ripple_types.h +++ b/src/ripple/types/ripple_types.h @@ -45,7 +45,6 @@ using namespace beast; } #include "api/AgedHistory.h" -#include "api/CycledSet.h" # include "api/Blob.h" # include "api/Base58.h" # include "api/ByteOrder.h" diff --git a/src/ripple/validators/ripple_validators.cpp b/src/ripple/validators/ripple_validators.cpp index d9f49799f9..1bbfccad74 100644 --- a/src/ripple/validators/ripple_validators.cpp +++ b/src/ripple/validators/ripple_validators.cpp @@ -35,6 +35,7 @@ #include "beast/modules/beast_asio/beast_asio.h" #include "beast/modules/beast_sqdb/beast_sqdb.h" +#include "../algorithm/api/CycledSet.h" #include "../testoverlay/ripple_testoverlay.h" // for unit test namespace ripple { diff --git a/src/ripple_app/peers/Peer.cpp b/src/ripple_app/peers/Peer.cpp index 8e5de9466f..69af600689 100644 --- a/src/ripple_app/peers/Peer.cpp +++ b/src/ripple_app/peers/Peer.cpp @@ -1752,8 +1752,8 @@ void PeerImp::recvEndpoints (protocol::TMEndpoints& packet) // maxSlots endpoint.incomingSlotsMax = tm.maxslots(); - // uptimeMinutes - endpoint.uptimeMinutes = tm.uptimeminutes(); + // uptimeSeconds + endpoint.uptimeSeconds = tm.uptimeseconds(); endpoints.push_back (endpoint); } diff --git a/src/ripple_app/peers/Peers.cpp b/src/ripple_app/peers/Peers.cpp index 27ecfa098f..a4f4020eab 100644 --- a/src/ripple_app/peers/Peers.cpp +++ b/src/ripple_app/peers/Peers.cpp @@ -169,7 +169,7 @@ public: tme.set_hops (ep.hops); tme.set_slots (ep.incomingSlotsAvailable); tme.set_maxslots (ep.incomingSlotsMax); - tme.set_uptimeminutes (ep.uptimeMinutes); + tme.set_uptimeseconds (ep.uptimeSeconds); tme.set_features (ep.featureList); } diff --git a/src/ripple_data/protocol/ripple.proto b/src/ripple_data/protocol/ripple.proto index 1443d78766..92e86669a6 100644 --- a/src/ripple_data/protocol/ripple.proto +++ b/src/ripple_data/protocol/ripple.proto @@ -239,7 +239,7 @@ message TMEndpoint required uint32 hops = 2; required uint32 slots = 3; // the number of available incoming slots required uint32 maxSlots = 4; // the maximum number of incoming slots - required uint32 uptimeMinutes = 5; // uptime in minutes + required uint32 uptimeSeconds = 5; // uptime in seconds required string features = 6; }