diff --git a/src/ripple/app/consensus/LedgerConsensus.cpp b/src/ripple/app/consensus/LedgerConsensus.cpp index 929ae1e40..7eefccc15 100644 --- a/src/ripple/app/consensus/LedgerConsensus.cpp +++ b/src/ripple/app/consensus/LedgerConsensus.cpp @@ -559,7 +559,7 @@ public: WriteLog (lsWARNING, LedgerConsensus) << mPrevLedgerHash << " to " << netLgr; WriteLog (lsWARNING, LedgerConsensus) - << ripple::getJson (*mPreviousLedger, 0); + << ripple::getJson (*mPreviousLedger); if (ShouldLog (lsDEBUG, LedgerConsensus)) { diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 0d9eed63e..9e4deee00 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -643,7 +643,7 @@ bool Ledger::saveValidatedLedger (bool current) if (!getAccountHash ().isNonZero ()) { WriteLog (lsFATAL, Ledger) << "AH is zero: " - << getJson (*this, 0); + << getJson (*this); assert (false); } @@ -920,7 +920,7 @@ Ledger::pointer Ledger::getSQL (std::string const& sql) { WriteLog (lsERROR, Ledger) << "Failed on ledger"; Json::Value p; - addJson (*ret, p, LEDGER_JSON_FULL); + addJson (p, {*ret, LEDGER_JSON_FULL}); WriteLog (lsERROR, Ledger) << p; } @@ -1648,7 +1648,7 @@ bool Ledger::assertSane () const WriteLog (lsFATAL, Ledger) << "ledger is not sane"; - Json::Value j = getJson (*this, 0); + Json::Value j = getJson (*this); j [jss::accountTreeHash] = to_string (mAccountHash); j [jss::transTreeHash] = to_string (mTransHash); diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index cf377adfb..dc9d6ac73 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -49,10 +49,10 @@ enum LedgerStateParms lepERROR = 32, // error }; -#define LEDGER_JSON_DUMP_TXRP 0x10000000 -#define LEDGER_JSON_DUMP_STATE 0x20000000 -#define LEDGER_JSON_EXPAND 0x40000000 -#define LEDGER_JSON_FULL 0x80000000 +#define LEDGER_JSON_DUMP_TXRP 0x1 +#define LEDGER_JSON_DUMP_STATE 0x2 +#define LEDGER_JSON_EXPAND 0x4 +#define LEDGER_JSON_FULL 0x8 class SqliteStatement; diff --git a/src/ripple/app/ledger/LedgerToJson.h b/src/ripple/app/ledger/LedgerToJson.h index c6745a4c4..3fd30dd5d 100644 --- a/src/ripple/app/ledger/LedgerToJson.h +++ b/src/ripple/app/ledger/LedgerToJson.h @@ -30,35 +30,49 @@ namespace ripple { +struct LedgerFill +{ + LedgerFill (Ledger const& l, + int o = 0, + RPC::Yield const& y = {}, + RPC::YieldStrategy const& ys = {}) + : ledger (l), + options (o), + yield (y), + yieldStrategy (ys) + { + } + + Ledger const& ledger; + int options; + RPC::Yield yield; + RPC::YieldStrategy yieldStrategy; +}; + /** Given a Ledger, options, and a generic Object that has Json semantics, fill the Object with a description of the ledger. */ template -void fillJson (Ledger const&, Object&, int options, - RPC::Yield const& yield = {}); +void fillJson (Object&, LedgerFill const&); /** Add Json to an existing generic Object. */ template -void addJson (Ledger const&, Object&, int options, - RPC::Yield const& yield = {}); +void addJson (Object&, LedgerFill const&); /** Return a new Json::Value representing the ledger with given options.*/ -Json::Value getJson (Ledger const&, int options, - RPC::Yield const& yield = {}); +Json::Value getJson (LedgerFill const&); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Implementations. -auto const accountYieldCount = 0; -auto const transactionYieldCount = 0; - template -void fillJson ( - Ledger const& ledger, Object& json, int options, RPC::Yield const& yield) +void fillJson (Object& json, LedgerFill const& fill) { - bool const bFull (options & LEDGER_JSON_FULL); - bool const bExpand (options & LEDGER_JSON_EXPAND); + auto const& ledger = fill.ledger; + + bool const bFull (fill.options & LEDGER_JSON_FULL); + bool const bExpand (fill.options & LEDGER_JSON_EXPAND); // DEPRECATED json[jss::seqNum] = to_string (ledger.getLedgerSeq()); @@ -100,20 +114,17 @@ void fillJson ( } auto &transactionMap = ledger.peekTransactionMap(); - if (transactionMap && (bFull || options & LEDGER_JSON_DUMP_TXRP)) + if (transactionMap && (bFull || fill.options & LEDGER_JSON_DUMP_TXRP)) { auto&& txns = RPC::addArray (json, jss::transactions); SHAMapTreeNode::TNType type; - int count = 0; + RPC::CountedYield count ( + fill.yieldStrategy.transactionYieldCount, fill.yield); for (auto item = transactionMap->peekFirstItem (type); item; item = transactionMap->peekNextItem (item->getTag (), type)) { - if (transactionYieldCount && ++count >= transactionYieldCount) - { - yield(); - count = 0; - } + count.yield(); if (bFull || bExpand) { if (type == SHAMapTreeNode::tnTRANSACTION_NM) @@ -148,33 +159,26 @@ void fillJson ( } auto& accountStateMap = ledger.peekAccountStateMap(); - if (accountStateMap && (bFull || options & LEDGER_JSON_DUMP_STATE)) + if (accountStateMap && (bFull || fill.options & LEDGER_JSON_DUMP_STATE)) { auto&& array = RPC::addArray (json, jss::accountState); - auto count = 0; + RPC::CountedYield count ( + fill.yieldStrategy.accountYieldCount, fill.yield); if (bFull || bExpand) { ledger.visitStateItems ( - [&array, &count, &yield] (SLE::ref sle) + [&array, &count, &fill] (SLE::ref sle) { - if (accountYieldCount && ++count >= accountYieldCount) - { - yield(); - count = 0; - } + count.yield(); array.append (sle->getJson(0)); }); } else { accountStateMap->visitLeaves( - [&array, &count, &yield] (SHAMapItem::ref smi) + [&array, &count, &fill] (SHAMapItem::ref smi) { - if (accountYieldCount && ++count >= accountYieldCount) - { - yield(); - count = 0; - } + count.yield(); array.append (to_string(smi->getTag ())); }); } @@ -183,18 +187,17 @@ void fillJson ( /** Add Json to an existing generic Object. */ template -void addJson ( - Ledger const& ledger, Object& json, int options, RPC::Yield const& yield) +void addJson (Object& json, LedgerFill const& fill) { auto&& object = RPC::addObject (json, jss::ledger); - fillJson (ledger, object, options, yield); + fillJson (object, fill); } inline -Json::Value getJson (Ledger const& ledger, int options, RPC::Yield const& yield) +Json::Value getJson (LedgerFill const& fill) { Json::Value json; - fillJson (ledger, json, options, yield); + fillJson (json, fill); return json; } diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index bd11451a2..486c18b56 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -1409,7 +1409,7 @@ bool NetworkOPsImp::checkLastClosedLedger ( } m_journal.warning << "We are not running on the consensus ledger"; - m_journal.info << "Our LCL: " << getJson (*ourClosed, 0); + m_journal.info << "Our LCL: " << getJson (*ourClosed); m_journal.info << "Net LCL " << closedLedger; if ((mMode == omTRACKING) || (mMode == omFULL)) diff --git a/src/ripple/rpc/RPCHandler.h b/src/ripple/rpc/RPCHandler.h index fec3ef06d..2723d92e5 100644 --- a/src/ripple/rpc/RPCHandler.h +++ b/src/ripple/rpc/RPCHandler.h @@ -20,20 +20,22 @@ #ifndef RIPPLE_APP_RPC_HANDLER #define RIPPLE_APP_RPC_HANDLER -#include #include #include -#include #include +#include namespace ripple { namespace RPC { +struct Context; +struct YieldStrategy; + /** Execute an RPC command and store the results in a Json::Value. */ -Status doCommand (RPC::Context&, Json::Value&); +Status doCommand (RPC::Context&, Json::Value&, YieldStrategy const& s = {}); /** Execute an RPC command and store the results in an std::string. */ -void executeRPC (RPC::Context&, std::string&); +void executeRPC (RPC::Context&, std::string&, YieldStrategy const& s = {}); /** Temporary flag to enable RPCs. */ auto const streamingRPC = false; diff --git a/src/ripple/rpc/handlers/Ledger.h b/src/ripple/rpc/handlers/Ledger.h index b9d835255..7dce747bc 100644 --- a/src/ripple/rpc/handlers/Ledger.h +++ b/src/ripple/rpc/handlers/Ledger.h @@ -78,7 +78,7 @@ void LedgerHandler::writeResult (Object& value) if (ledger_) { RPC::copyFrom (value, result_); - addJson (*ledger_, value, options_, context_.yield); + addJson (value, {*ledger_, options_, context_.yield}); } else { @@ -86,13 +86,12 @@ void LedgerHandler::writeResult (Object& value) auto& yield = context_.yield; { auto&& closed = RPC::addObject (value, jss::closed); - addJson (*master.getClosedLedger(), closed, 0, yield); + addJson (closed, {*master.getClosedLedger(), 0, yield}); } { auto&& open = RPC::addObject (value, jss::open); - addJson (*master.getCurrentLedger(), open, 0, yield); + addJson (open, {*master.getCurrentLedger(), 0, yield}); } - } } diff --git a/src/ripple/rpc/handlers/LedgerHeader.cpp b/src/ripple/rpc/handlers/LedgerHeader.cpp index 8d495a985..1c29293f3 100644 --- a/src/ripple/rpc/handlers/LedgerHeader.cpp +++ b/src/ripple/rpc/handlers/LedgerHeader.cpp @@ -42,7 +42,7 @@ Json::Value doLedgerHeader (RPC::Context& context) // This information isn't verified: they should only use it if they trust // us. - addJson (*lpLedger, jvResult, 0); + addJson (jvResult, {*lpLedger, 0}); return jvResult; } diff --git a/src/ripple/rpc/handlers/LedgerRequest.cpp b/src/ripple/rpc/handlers/LedgerRequest.cpp index 16dae11f1..55882372f 100644 --- a/src/ripple/rpc/handlers/LedgerRequest.cpp +++ b/src/ripple/rpc/handlers/LedgerRequest.cpp @@ -94,7 +94,7 @@ Json::Value doLedgerRequest (RPC::Context& context) // We already have the ledger they want Json::Value jvResult; jvResult[jss::ledger_index] = ledger->getLedgerSeq(); - addJson (*ledger, jvResult, 0); + addJson (jvResult, {*ledger, 0}); return jvResult; } else diff --git a/src/ripple/rpc/impl/Context.h b/src/ripple/rpc/impl/Context.h index 8c0e991d7..9c04c3e55 100644 --- a/src/ripple/rpc/impl/Context.h +++ b/src/ripple/rpc/impl/Context.h @@ -22,6 +22,7 @@ #include #include +#include #include namespace ripple { diff --git a/src/ripple/rpc/impl/RPCHandler.cpp b/src/ripple/rpc/impl/RPCHandler.cpp index d26f43c56..8990412f9 100644 --- a/src/ripple/rpc/impl/RPCHandler.cpp +++ b/src/ripple/rpc/impl/RPCHandler.cpp @@ -22,11 +22,17 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include +#include + namespace ripple { namespace RPC { @@ -198,7 +204,8 @@ void getResult ( } // namespace -Status doCommand (RPC::Context& context, Json::Value& result) +Status doCommand ( + RPC::Context& context, Json::Value& result, YieldStrategy const&) { boost::optional handler; if (auto error = fillHandler (context, handler)) @@ -214,7 +221,8 @@ Status doCommand (RPC::Context& context, Json::Value& result) } /** Execute an RPC command and store the results in a string. */ -void executeRPC (RPC::Context& context, std::string& output) +void executeRPC ( + RPC::Context& context, std::string& output, YieldStrategy const& strategy) { boost::optional handler; if (auto error = fillHandler (context, handler)) @@ -232,8 +240,7 @@ void executeRPC (RPC::Context& context, std::string& output) { auto object = Json::Value (Json::objectValue); getResult (context, method, object, handler->name_); - - if (streamingRPC) + if (strategy.streaming == YieldStrategy::Streaming::yes) output = jsonAsString (object); else output = to_string (object); diff --git a/src/ripple/server/ServerHandler.h b/src/ripple/server/ServerHandler.h index d6d36758d..de394954d 100644 --- a/src/ripple/server/ServerHandler.h +++ b/src/ripple/server/ServerHandler.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include // @@ -66,6 +67,7 @@ public: }; overlay_t overlay; + RPC::YieldStrategy yieldStrategy; void makeContexts(); diff --git a/src/ripple/server/impl/ServerHandlerImp.cpp b/src/ripple/server/impl/ServerHandlerImp.cpp index 75141612b..ece3cdf27 100644 --- a/src/ripple/server/impl/ServerHandlerImp.cpp +++ b/src/ripple/server/impl/ServerHandlerImp.cpp @@ -192,9 +192,19 @@ ServerHandlerImp::onRequest (HTTP::Session& session) auto detach = session.detach(); - RPC::Coroutine::YieldFunction yieldFunction = - [this, detach] (Yield const& y) { processSession (detach, y); }; - runCoroutine (RPC::Coroutine (yieldFunction), m_jobQueue); + if (setup_.yieldStrategy.useCoroutines == + RPC::YieldStrategy::UseCoroutines::yes) + { + RPC::Coroutine::YieldFunction yieldFunction = + [this, detach] (Yield const& y) { processSession (detach, y); }; + runCoroutine (RPC::Coroutine (yieldFunction), m_jobQueue); + } + else + { + m_jobQueue.addJob ( + jtCLIENT, "RPC-Client", + [=] (Job&) { processSession (detach, RPC::Yield{}); }); + } } void @@ -211,23 +221,14 @@ ServerHandlerImp::onStopped (HTTP::Server&) //------------------------------------------------------------------------------ -// ServerHandlerImp will yield after emitting serverOutputChunkSize bytes. -// If this value is 0, it means "yield after each output" -// A negative value means "never yield" -// TODO(tom): negotiate a spot for this in Configs. -const int serverOutputChunkSize = -1; - // Dispatched on the job queue void ServerHandlerImp::processSession ( std::shared_ptr const& session, Yield const& yield) { auto output = makeOutput (*session); - if (serverOutputChunkSize >= 0) - { - output = RPC::chunkedYieldingOutput ( - output, yield, serverOutputChunkSize); - } + if (auto byteYieldCount = setup_.yieldStrategy.byteYieldCount) + output = RPC::chunkedYieldingOutput (output, yield, byteYieldCount); processRequest ( session->port(), @@ -313,7 +314,12 @@ ServerHandlerImp::processRequest ( return; } - // Parse params + // Extract request parameters from the request Json as `params`. + // + // If the field "params" is empty, `params` is an empty object. + // + // Otherwise, that field must be an array of length 1 (why?) + // and we take that first entry and validate that it's an object. Json::Value params = jsonRPC ["params"]; if (params.isNull () || params.empty()) @@ -357,14 +363,14 @@ ServerHandlerImp::processRequest ( RPC::Context context {params, loadType, m_networkOPs, role, nullptr, yield}; std::string response; - if (RPC::streamingRPC) + if (setup_.yieldStrategy.streaming == RPC::YieldStrategy::Streaming::yes) { - executeRPC (context, response); + executeRPC (context, response, setup_.yieldStrategy); } else { Json::Value result; - RPC::doCommand (context, result); + RPC::doCommand (context, result, setup_.yieldStrategy); // Always report "status". On an error report the request as received. if (result.isMember ("error")) @@ -797,8 +803,10 @@ setup_ServerHandler (BasicConfig const& config, std::ostream& log) { ServerHandler::Setup setup; setup.ports = detail::parse_Ports (config, log); + setup.yieldStrategy = RPC::makeYieldStrategy (config["server"]); detail::setup_Client(setup); detail::setup_Overlay(setup); + return setup; }