diff --git a/modules/ripple_client/ripple_client.cpp b/modules/ripple_client/ripple_client.cpp index b565aedea4..42b0bb38a8 100644 --- a/modules/ripple_client/ripple_client.cpp +++ b/modules/ripple_client/ripple_client.cpp @@ -37,6 +37,7 @@ #include "src/cpp/ripple/ripple_InfoSub.h" // Order and indentation reflect the hierarchy of dependencies + #include "src/cpp/ripple/JSONCache.h" #include "src/cpp/ripple/ripple_HashedObject.h" #include "src/cpp/ripple/ripple_SHAMapItem.h" #include "src/cpp/ripple/ripple_SHAMapNode.h" diff --git a/modules/ripple_main/ripple_main.cpp b/modules/ripple_main/ripple_main.cpp index 0f72e445a1..40e19fbefb 100644 --- a/modules/ripple_main/ripple_main.cpp +++ b/modules/ripple_main/ripple_main.cpp @@ -185,6 +185,7 @@ #include "src/cpp/ripple/LedgerEntrySet.h" #include "src/cpp/ripple/TransactionEngine.h" #include "src/cpp/ripple/ripple_CanonicalTXSet.h" +#include "src/cpp/ripple/JSONCache.h" #include "src/cpp/ripple/ripple_LedgerHistory.h" #include "src/cpp/ripple/LedgerMaster.h" diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 8b415af21a..ec3efb6e50 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -17,7 +17,7 @@ NetworkOPs::NetworkOPs(boost::asio::io_service& io_service, LedgerMaster* pLedge mFeatureBlocked(false), mNetTimer(io_service), mLedgerMaster(pLedgerMaster), mCloseTimeOffset(0), mLastCloseProposers(0), mLastCloseConvergeTime(1000 * LEDGER_IDLE_INTERVAL), mLastCloseTime(0), mLastValidationTime(0), - mFetchPack("FetchPack", 2048, 20), mLastFetchPack(0), mFetchSeq(static_cast(-1)), + mJSONCache(120), mFetchPack("FetchPack", 2048, 20), mLastFetchPack(0), mFetchSeq(static_cast(-1)), mLastLoadBase(256), mLastLoadFactor(256) { } @@ -2074,6 +2074,7 @@ void NetworkOPs::makeFetchPack(Job&, boost::weak_ptr wPeer, void NetworkOPs::sweepFetchPack() { mFetchPack.sweep(); + mJSONCache.sweep(); } void NetworkOPs::addFetchPack(uint256 const& hash, boost::shared_ptr< Blob >& data) diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index 5336642590..ba31ba8abe 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -176,6 +176,16 @@ public: int getFetchSize(); void sweepFetchPack(); + float getJSONHitRate() { return mJSONCache.getHitRate(); } + int getJSONEntries() { return mJSONCache.getCount(); } + + void storeJSONCache(int operation, const uint256& ledger, const uint160& object, + const boost::shared_ptr& data) + { mJSONCache.storeEntry(operation, ledger, object, data); } + + boost::shared_ptr getJSONCache(int operation, const uint256& ledger, const uint160& object) + { return mJSONCache.getEntry(operation, ledger, object); } + // network state machine void checkState(const boost::system::error_code& result); void switchLastClosedLedger(Ledger::pointer newLedger, bool duringConsensus); // Used for the "jump" case @@ -303,6 +313,8 @@ private: subMapType mSubTransactions; // all accepted transactions subMapType mSubRTTransactions; // all proposed and accepted transactions + JSONCache mJSONCache; + TaggedCache< uint256, Blob , UptimeTimerAdapter > mFetchPack; uint32 mLastFetchPack; uint32 mFetchSeq; diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 8307a3d690..9eda3b06f1 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -1049,8 +1049,12 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest, int& cost, ScopedL if (!lpLedger) return jvResult; + bool bUnlocked = false; if (lpLedger->isImmutable()) + { MasterLockHolder.unlock(); + bUnlocked = true; + } if (!jvRequest.isMember("account")) return rpcError(rpcINVALID_PARAMS); @@ -1088,32 +1092,47 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest, int& cost, ScopedL { jvResult["account"] = raAccount.humanAccountID(); - AccountItems rippleLines(raAccount.getAccountID(), lpLedger, AccountItem::pointer(new RippleState())); + boost::shared_ptr jvsLines = + theApp->getOPs().getJSONCache(JC_OP_ACCOUNT_LINES, lpLedger->getHash(), raAccount.getAccountID()); - Json::Value& jsonLines = (jvResult["lines"] = Json::arrayValue); - BOOST_FOREACH(AccountItem::ref item, rippleLines.getItems()) + if (!jvsLines) { - RippleState* line=(RippleState*)item.get(); + jvsLines = boost::make_shared(Json::arrayValue); + Json::Value& jsonLines = *jvsLines; - if (!raPeer.isValid() || raPeer.getAccountID() == line->getAccountIDPeer()) + AccountItems rippleLines(raAccount.getAccountID(), lpLedger, AccountItem::pointer(new RippleState())); + + BOOST_FOREACH(AccountItem::ref item, rippleLines.getItems()) { - const STAmount& saBalance = line->getBalance(); - const STAmount& saLimit = line->getLimit(); - const STAmount& saLimitPeer = line->getLimitPeer(); + RippleState* line=(RippleState*)item.get(); - Json::Value& jPeer = jsonLines.append(Json::objectValue); + if (!raPeer.isValid() || raPeer.getAccountID() == line->getAccountIDPeer()) + { + const STAmount& saBalance = line->getBalance(); + const STAmount& saLimit = line->getLimit(); + const STAmount& saLimitPeer = line->getLimitPeer(); - jPeer["account"] = RippleAddress::createHumanAccountID(line->getAccountIDPeer()); - // Amount reported is positive if current account holds other account's IOUs. - // Amount reported is negative if other account holds current account's IOUs. - jPeer["balance"] = saBalance.getText(); - jPeer["currency"] = saBalance.getHumanCurrency(); - jPeer["limit"] = saLimit.getText(); - jPeer["limit_peer"] = saLimitPeer.getText(); - jPeer["quality_in"] = static_cast(line->getQualityIn()); - jPeer["quality_out"] = static_cast(line->getQualityOut()); + Json::Value& jPeer = jsonLines.append(Json::objectValue); + + jPeer["account"] = RippleAddress::createHumanAccountID(line->getAccountIDPeer()); + // Amount reported is positive if current account holds other account's IOUs. + // Amount reported is negative if other account holds current account's IOUs. + jPeer["balance"] = saBalance.getText(); + jPeer["currency"] = saBalance.getHumanCurrency(); + jPeer["limit"] = saLimit.getText(); + jPeer["limit_peer"] = saLimitPeer.getText(); + jPeer["quality_in"] = static_cast(line->getQualityIn()); + jPeer["quality_out"] = static_cast(line->getQualityOut()); + } } + + theApp->getOPs().storeJSONCache(JC_OP_ACCOUNT_LINES, lpLedger->getHash(), + raAccount.getAccountID(), jvsLines); } + if (!bUnlocked) + MasterLockHolder.unlock(); + + jvResult["lines"] = *jvsLines; } else { @@ -1149,8 +1168,12 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest, int& cost, Scoped if (!lpLedger) return jvResult; + bool bUnlocked = false; if (lpLedger->isImmutable()) + { MasterLockHolder.unlock(); + bUnlocked = true; + } if (!jvRequest.isMember("account")) return rpcError(rpcINVALID_PARAMS); @@ -1172,11 +1195,22 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest, int& cost, Scoped if (bIndex) jvResult["account_index"] = iIndex; - if (lpLedger->hasAccount(raAccount)) - lpLedger->visitAccountItems(raAccount.getAccountID(), - BIND_TYPE(&offerAdder, boost::ref(jvResult["offers"] = Json::arrayValue), P_1)); - else - jvResult = rpcError(rpcACT_NOT_FOUND); + if (!lpLedger->hasAccount(raAccount)) + return rpcError(rpcACT_NOT_FOUND); + + boost::shared_ptr jvsOffers = + theApp->getOPs().getJSONCache(JC_OP_ACCOUNT_OFFERS, lpLedger->getHash(), raAccount.getAccountID()); + + if (!jvsOffers) + { + jvsOffers = boost::make_shared(Json::arrayValue); + lpLedger->visitAccountItems(raAccount.getAccountID(), BIND_TYPE(&offerAdder, boost::ref(*jvsOffers), P_1)); + theApp->getOPs().storeJSONCache(JC_OP_ACCOUNT_OFFERS, lpLedger->getHash(), raAccount.getAccountID(), jvsOffers); + } + if (!bUnlocked) + MasterLockHolder.unlock(); + + jvResult["offers"] = *jvsOffers; return jvResult; } @@ -2343,6 +2377,8 @@ Json::Value RPCHandler::doGetCounts(Json::Value jvRequest, int& cost, ScopedLock ret["node_hit_rate"] = theApp->getHashedObjectStore().getCacheHitRate(); ret["ledger_hit_rate"] = theApp->getLedgerMaster().getCacheHitRate(); ret["AL_hit_rate"] = AcceptedLedger::getCacheHitRate(); + ret["JC_hit_rate"] = theApp->getOPs().getJSONHitRate(); + ret["JC_size"] = theApp->getOPs().getJSONEntries(); ret["fullbelow_size"] = SHAMap::getFullBelowSize();