From e24689b8a78111422f9c38888395469f6be0af2b Mon Sep 17 00:00:00 2001 From: Mark Travis Date: Tue, 19 Dec 2017 17:08:05 -0800 Subject: [PATCH] Performance counter modifications: * Create and display counters to track: 1) Pending transaction limit overruns. 2) Total peer disconnections. 3) Peers disconnections due to resource consumption. * Render 64 bit integers in Json. * Convert state_accounting counters in server_info to 64 bit integers. * Avoid a potential double-free in Json library. --- src/ripple/app/misc/NetworkOPs.cpp | 8 ++++-- src/ripple/json/impl/json_value.cpp | 21 ++++++++++++++- src/ripple/json/json_value.h | 8 +++++- src/ripple/overlay/Overlay.h | 12 +++++++++ src/ripple/overlay/impl/OverlayImpl.h | 39 +++++++++++++++++++++++++++ src/ripple/overlay/impl/PeerImp.cpp | 3 +++ src/ripple/protocol/JsonFields.h | 4 +++ 7 files changed, 91 insertions(+), 4 deletions(-) diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index b18587dde68..a37c0ca10dc 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -120,7 +120,7 @@ class NetworkOPsImp final { struct Counters { - std::uint32_t transitions = 0; + std::uint64_t transitions = 0; std::chrono::microseconds dur = std::chrono::microseconds (0); }; @@ -2367,6 +2367,10 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin) info[jss::state_accounting] = accounting_.json(); info[jss::uptime] = UptimeTimer::getInstance ().getElapsedSeconds (); + info[jss::jq_trans_overflow] = app_.overlay().getJqTransOverflow(); + info[jss::peer_disconnects] = app_.overlay().getPeerDisconnect(); + info[jss::peer_disconnects_resources] = + app_.overlay().getPeerDisconnectCharges(); return info; } @@ -3365,7 +3369,7 @@ Json::Value NetworkOPsImp::StateAccounting::json() const ret[states_[i]] = Json::objectValue; auto& state = ret[states_[i]]; state[jss::transitions] = counters[i].transitions; - state[jss::duration_us] = std::to_string (counters[i].dur.count()); + state[jss::duration_us] = counters[i].dur.count(); } return ret; diff --git a/src/ripple/json/impl/json_value.cpp b/src/ripple/json/impl/json_value.cpp index 3b4f06d8dd9..ca0dbbf5813 100644 --- a/src/ripple/json/impl/json_value.cpp +++ b/src/ripple/json/impl/json_value.cpp @@ -243,6 +243,24 @@ Value::Value ( UInt value ) value_.uint_ = value; } +Value::Value ( std::int64_t value ) + : type_ ( stringValue ) + , allocated_ ( true ) +{ + std::string str(std::to_string(value)); + value_.string_ = valueAllocator ()->duplicateStringValue ( + str.c_str (), str.size() ); +} + +Value::Value ( std::uint64_t value ) + : type_ ( stringValue ) + , allocated_ ( true ) +{ + std::string str(std::to_string(value)); + value_.string_ = valueAllocator ()->duplicateStringValue ( + str.c_str (), str.size() ); +} + Value::Value ( double value ) : type_ ( realValue ) { @@ -344,7 +362,8 @@ Value::~Value () case arrayValue: case objectValue: - delete value_.map_; + if (value_.map_) + delete value_.map_; break; default: diff --git a/src/ripple/json/json_value.h b/src/ripple/json/json_value.h index 2644223ce97..b62114ceb72 100644 --- a/src/ripple/json/json_value.h +++ b/src/ripple/json/json_value.h @@ -26,6 +26,7 @@ #include #include #include +#include /** \brief JSON (JavaScript Object Notation). */ @@ -214,6 +215,11 @@ class Value Value ( ValueType type = nullValue ); Value ( Int value ); Value ( UInt value ); + // Convert 64bit integers to string. Json integers overflow between 32 + // and 64 bits: some large integers cannot be expressed as + // a Json integer therefore. + Value ( std::int64_t value ); + Value ( std::uint64_t value ); Value ( double value ); Value ( const char* value ); Value ( const char* beginValue, const char* endValue ); @@ -385,7 +391,7 @@ class Value double real_; bool bool_; char* string_; - ObjectValues* map_; + ObjectValues* map_ {nullptr}; } value_; ValueType type_ : 8; int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. diff --git a/src/ripple/overlay/Overlay.h b/src/ripple/overlay/Overlay.h index 103240bba31..75cfdf9718b 100644 --- a/src/ripple/overlay/Overlay.h +++ b/src/ripple/overlay/Overlay.h @@ -227,6 +227,18 @@ class Overlay std::size_t selectPeers (PeerSet& set, std::size_t limit, std::function< bool(std::shared_ptr const&)> score) = 0; + + /** Increment and retrieve counter for transaction job queue overflows. */ + virtual void incJqTransOverflow() = 0; + virtual std::uint64_t getJqTransOverflow() const = 0; + + /** Increment and retrieve counters for total peer disconnects, and + * disconnects we initiate for excessive resource consumption. + */ + virtual void incPeerDisconnect() = 0; + virtual std::uint64_t getPeerDisconnect() const = 0; + virtual void incPeerDisconnectCharges() = 0; + virtual std::uint64_t getPeerDisconnectCharges() const = 0; }; struct ScoreHasLedger diff --git a/src/ripple/overlay/impl/OverlayImpl.h b/src/ripple/overlay/impl/OverlayImpl.h index 6791c20208c..f7c84c9006b 100644 --- a/src/ripple/overlay/impl/OverlayImpl.h +++ b/src/ripple/overlay/impl/OverlayImpl.h @@ -119,6 +119,9 @@ class OverlayImpl : public Overlay Resolver& m_resolver; std::atomic next_id_; int timer_count_; + std::atomic jqTransOverflow_ {0}; + std::atomic peerDisconnects_ {0}; + std::atomic peerDisconnectsCharges_ {0}; //-------------------------------------------------------------------------- @@ -301,6 +304,42 @@ class OverlayImpl : public Overlay bool isInbound, int bytes); + void + incJqTransOverflow() override + { + ++jqTransOverflow_; + } + + std::uint64_t + getJqTransOverflow() const override + { + return jqTransOverflow_; + } + + void + incPeerDisconnect() + { + ++peerDisconnects_; + } + + std::uint64_t + getPeerDisconnect() const override + { + return peerDisconnects_; + } + + void + incPeerDisconnectCharges() + { + ++peerDisconnectsCharges_; + } + + std::uint64_t + getPeerDisconnectCharges() const override + { + return peerDisconnectsCharges_; + }; + private: std::shared_ptr makeRedirectResponse (PeerFinder::Slot::ptr const& slot, diff --git a/src/ripple/overlay/impl/PeerImp.cpp b/src/ripple/overlay/impl/PeerImp.cpp index 0cdc63465b4..d4b1fd81c8a 100644 --- a/src/ripple/overlay/impl/PeerImp.cpp +++ b/src/ripple/overlay/impl/PeerImp.cpp @@ -222,6 +222,7 @@ PeerImp::charge (Resource::Charge const& fee) usage_.disconnect() && strand_.running_in_this_thread()) { // Sever the connection + overlay_.incPeerDisconnectCharges(); fail("charge: Resources"); } } @@ -414,6 +415,7 @@ PeerImp::close() error_code ec; timer_.cancel(ec); socket_.close(ec); + overlay_.incPeerDisconnect(); if(m_inbound) { JLOG(journal_.debug()) << "Closed"; @@ -1094,6 +1096,7 @@ PeerImp::onMessage (std::shared_ptr const& m) constexpr int max_transactions = 250; if (app_.getJobQueue().getJobCount(jtTRANSACTION) > max_transactions) { + overlay_.incJqTransOverflow(); JLOG(p_journal_.info()) << "Transaction queue is full"; } else if (app_.getLedgerMaster().getValidatedLedgerAge() > 4min) diff --git a/src/ripple/protocol/JsonFields.h b/src/ripple/protocol/JsonFields.h index 089d702bc59..61c9e3e0ad6 100644 --- a/src/ripple/protocol/JsonFields.h +++ b/src/ripple/protocol/JsonFields.h @@ -215,6 +215,7 @@ JSS ( issuer ); // in: RipplePathFind, Subscribe, // Unsubscribe, BookOffers // out: paths/Node, STPathSet, STAmount JSS ( jsonrpc ); // json version +JSS ( jq_trans_overflow ); // JobQueue transaction limit overflow. JSS ( key ); // out: WalletSeed JSS ( key_type ); // in/out: WalletPropose, TransactionSign JSS ( latency ); // out: PeerImp @@ -326,6 +327,9 @@ JSS ( peer ); // in: AccountLines JSS ( peer_authorized ); // out: AccountLines JSS ( peer_id ); // out: RCLCxPeerPos JSS ( peers ); // out: InboundLedger, handlers/Peers, Overlay +JSS ( peer_disconnects ); // Severed peer connection counter. +JSS ( peer_disconnects_resources ); // Severed peer connections because of + // excess resource consumption. JSS ( port ); // in: Connect JSS ( previous_ledger ); // out: LedgerPropose JSS ( proof ); // in: BookOffers