diff --git a/src/cpp/ripple/LedgerEntrySet.cpp b/src/cpp/ripple/LedgerEntrySet.cpp index 728242d77..38e9461d6 100644 --- a/src/cpp/ripple/LedgerEntrySet.cpp +++ b/src/cpp/ripple/LedgerEntrySet.cpp @@ -94,7 +94,7 @@ SLE::pointer LedgerEntrySet::entryCache(LedgerEntryType letType, const uint256& if (!sleEntry) { assert(action != taaDELETE); - sleEntry = mLedger->getSLE(index); + sleEntry = mImmutable ? mLedger->getSLEi(index) : mLedger->getSLE(index); if (sleEntry) entryCache(sleEntry); } @@ -115,7 +115,7 @@ LedgerEntryAction LedgerEntrySet::hasEntry(const uint256& index) const void LedgerEntrySet::entryCache(SLE::ref sle) { assert(mLedger); - assert(sle->isMutable()); + assert(sle->isMutable() || mImmutable); // Don't put an immutable SLE in a mutable LES std::map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) { @@ -138,7 +138,7 @@ void LedgerEntrySet::entryCache(SLE::ref sle) void LedgerEntrySet::entryCreate(SLE::ref sle) { - assert(mLedger); + assert(mLedger && !mImmutable); assert(sle->isMutable()); std::map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -175,7 +175,7 @@ void LedgerEntrySet::entryCreate(SLE::ref sle) void LedgerEntrySet::entryModify(SLE::ref sle) { - assert(sle->isMutable()); + assert(sle->isMutable() && !mImmutable); assert(mLedger); std::map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -209,7 +209,7 @@ void LedgerEntrySet::entryModify(SLE::ref sle) void LedgerEntrySet::entryDelete(SLE::ref sle) { - assert(sle->isMutable()); + assert(sle->isMutable() && !mImmutable); assert(mLedger); std::map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) diff --git a/src/cpp/ripple/LedgerEntrySet.h b/src/cpp/ripple/LedgerEntrySet.h index 47962cdb1..179f9a9c9 100644 --- a/src/cpp/ripple/LedgerEntrySet.h +++ b/src/cpp/ripple/LedgerEntrySet.h @@ -56,9 +56,11 @@ protected: TransactionMetaSet mSet; TransactionEngineParams mParams; int mSeq; + bool mImmutable; LedgerEntrySet(Ledger::ref ledger, const std::map &e, - const TransactionMetaSet& s, int m) : mLedger(ledger), mEntries(e), mSet(s), mParams(tapNONE), mSeq(m) { ; } + const TransactionMetaSet& s, int m) : + mLedger(ledger), mEntries(e), mSet(s), mParams(tapNONE), mSeq(m), mImmutable(false) { ; } SLE::pointer getForMod(const uint256& node, Ledger::ref ledger, boost::unordered_map& newMods); @@ -72,11 +74,14 @@ protected: public: - LedgerEntrySet(Ledger::ref ledger, TransactionEngineParams tep) : mLedger(ledger), mParams(tep), mSeq(0) { ; } + LedgerEntrySet(Ledger::ref ledger, TransactionEngineParams tep, bool immutable = false) : + mLedger(ledger), mParams(tep), mSeq(0), mImmutable(immutable) { ; } - LedgerEntrySet() : mParams(tapNONE), mSeq(0) { ; } + LedgerEntrySet() : mParams(tapNONE), mSeq(0), mImmutable(false) { ; } // set functions + void setImmutable() { mImmutable = true; } + bool isImmutable() const { return mImmutable; } LedgerEntrySet duplicate() const; // Make a duplicate of this set void setTo(const LedgerEntrySet&); // Set this set to have the same contents as another void swapWith(LedgerEntrySet&); // Swap the contents of two sets diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 0a500b2f5..3ec5d8a93 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1854,7 +1854,7 @@ void NetworkOPs::getBookPage(Ledger::pointer lpLedger, const uint160& uTakerPays cLog(lsTRACE) << boost::str(boost::format("getBookPage: uBookEnd=%s") % uBookEnd); cLog(lsTRACE) << boost::str(boost::format("getBookPage: uTipIndex=%s") % uTipIndex); - LedgerEntrySet lesActive(lpLedger, tapNONE); + LedgerEntrySet lesActive(lpLedger, tapNONE, true); bool bDone = false; bool bDirectAdvance = true; diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index 24a212c82..c18f8b55c 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -52,6 +52,8 @@ public: virtual ~InfoSub(); virtual void send(const Json::Value& jvObj, bool broadcast) = 0; + virtual void send(const Json::Value& jvObj, const std::string& sObj, bool broadcast) + { send(jvObj, broadcast); } uint64 getSeq() { diff --git a/src/cpp/ripple/OrderBookDB.cpp b/src/cpp/ripple/OrderBookDB.cpp index 0a7be2783..94d659d3e 100644 --- a/src/cpp/ripple/OrderBookDB.cpp +++ b/src/cpp/ripple/OrderBookDB.cpp @@ -167,13 +167,13 @@ void OrderBookDB::processTxn(Ledger::ref ledger, const ALTransaction& alTx, Json const STObject* data = dynamic_cast(node.peekAtPField(*field)); if (data) { - STAmount takerGets = data->getFieldAmount(sfTakerGets); - uint160 currencyGets = takerGets.getCurrency(); - uint160 issuerGets = takerGets.getIssuer(); + const STAmount& takerGets = data->getFieldAmount(sfTakerGets); + const uint160& currencyGets = takerGets.getCurrency(); + const uint160& issuerGets = takerGets.getIssuer(); - STAmount takerPays = data->getFieldAmount(sfTakerPays); - uint160 currencyPays = takerPays.getCurrency(); - uint160 issuerPays = takerPays.getIssuer(); + const STAmount& takerPays = data->getFieldAmount(sfTakerPays); + const uint160& currencyPays = takerPays.getCurrency(); + const uint160& issuerPays = takerPays.getIssuer(); // determine the OrderBook BookListeners::pointer book = @@ -206,6 +206,9 @@ void BookListeners::removeSubscriber(uint64 seq) void BookListeners::publish(Json::Value& jvObj) { + Json::FastWriter jfwWriter; + std::string sObj = jfwWriter.write(jvObj); + boost::recursive_mutex::scoped_lock sl(mLock); NetworkOPs::subMapType::const_iterator it = mListeners.begin(); while (it != mListeners.end()) @@ -213,7 +216,7 @@ void BookListeners::publish(Json::Value& jvObj) InfoSub::pointer p = it->second.lock(); if (p) { - p->send(jvObj, true); + p->send(jvObj, sObj, true); ++it; } else diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index d44d78071..aa185cfed 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -1202,12 +1202,15 @@ Json::Value RPCHandler::doBookOffers(Json::Value jvRequest, int& cost, ScopedLoc if (!lpLedger) return jvResult; + if (lpLedger->isImmutable()) + MasterLockHolder.unlock(); + if (!jvRequest.isMember("taker_pays") || !jvRequest.isMember("taker_gets") || !jvRequest["taker_pays"].isObject() || !jvRequest["taker_gets"].isObject()) return rpcError(rpcINVALID_PARAMS); - uint160 uTakerPaysCurrencyID; - uint160 uTakerPaysIssuerID; - Json::Value jvTakerPays = jvRequest["taker_pays"]; + uint160 uTakerPaysCurrencyID; + uint160 uTakerPaysIssuerID; + const Json::Value& jvTakerPays = jvRequest["taker_pays"]; // Parse mandatory currency. if (!jvTakerPays.isMember("currency") @@ -1230,9 +1233,9 @@ Json::Value RPCHandler::doBookOffers(Json::Value jvRequest, int& cost, ScopedLoc return rpcError(rpcSRC_ISR_MALFORMED); } - uint160 uTakerGetsCurrencyID; - uint160 uTakerGetsIssuerID; - Json::Value jvTakerGets = jvRequest["taker_gets"]; + uint160 uTakerGetsCurrencyID; + uint160 uTakerGetsIssuerID; + const Json::Value& jvTakerGets = jvRequest["taker_gets"]; // Parse mandatory currency. if (!jvTakerGets.isMember("currency") diff --git a/src/cpp/ripple/WSConnection.h b/src/cpp/ripple/WSConnection.h index f27ea00b2..baa8e3ab8 100644 --- a/src/cpp/ripple/WSConnection.h +++ b/src/cpp/ripple/WSConnection.h @@ -95,6 +95,13 @@ public: mHandler->send(ptr, jvObj, broadcast); } + void send(const Json::Value& jvObj, const std::string& sObj, bool broadcast) + { + connection_ptr ptr = mConnection.lock(); + if (ptr) + mHandler->send(ptr, sObj, broadcast); + } + // Utilities Json::Value invokeCommand(Json::Value& jvRequest) {