diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index a0965e0356..593d9cb7cc 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1618,18 +1618,24 @@ void NetworkOPs::unsubAccount(uint64 uSeq, const boost::unordered_setgetOrderBookDB().makeBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); - if(listeners) listeners->addSubscriber(isrListener); - return(true); + BookListeners::pointer listeners = + theApp->getOrderBookDB().makeBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); + if (listeners) + listeners->addSubscriber(isrListener); + return true; } -bool NetworkOPs::unsubBook(uint64 uSeq, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut) +bool NetworkOPs::unsubBook(uint64 uSeq, + const uint160& currencyIn, const uint160& currencyOut, const uint160& issuerIn, const uint160& issuerOut) { - BookListeners::pointer listeners=theApp->getOrderBookDB().getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); - if(listeners) listeners->removeSubscriber(uSeq); - return(true); + BookListeners::pointer listeners = + theApp->getOrderBookDB().getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); + if (listeners) + listeners->removeSubscriber(uSeq); + return true; } void NetworkOPs::newLCL(int proposers, int convergeTime, const uint256& ledgerHash) diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index 8270d2efd5..1dd10c501b 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -316,8 +316,10 @@ public: bool subServer(InfoSub::ref ispListener, Json::Value& jvResult); bool unsubServer(uint64 uListener); - bool subBook(InfoSub::ref ispListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut); - bool unsubBook(uint64 uListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut); + bool subBook(InfoSub::ref ispListener, const uint160& currencyIn, const uint160& currencyOut, + const uint160& issuerIn, const uint160& issuerOut); + bool unsubBook(uint64 uListener, const uint160& currencyIn, const uint160& currencyOut, + const uint160& issuerIn, const uint160& issuerOut); bool subTransactions(InfoSub::ref ispListener); bool unsubTransactions(uint64 uListener); diff --git a/src/cpp/ripple/OrderBookDB.cpp b/src/cpp/ripple/OrderBookDB.cpp index da2050b90e..e58757decb 100644 --- a/src/cpp/ripple/OrderBookDB.cpp +++ b/src/cpp/ripple/OrderBookDB.cpp @@ -98,39 +98,44 @@ void OrderBookDB::getBooks(const uint160& issuerID, const uint160& currencyID, s } } -BookListeners::pointer OrderBookDB::makeBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut) +BookListeners::pointer OrderBookDB::makeBookListeners(const uint160& currencyIn, const uint160& currencyOut, + const uint160& issuerIn, const uint160& issuerOut) { boost::recursive_mutex::scoped_lock sl(mLock); - BookListeners::pointer ret=getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); - if(!ret) + BookListeners::pointer ret = getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); + if (!ret) { - ret=BookListeners::pointer(new BookListeners); - mListeners[issuerIn][issuerOut][currencyIn][currencyOut]=ret; + ret = boost::make_shared(); + mListeners[issuerIn][issuerOut][currencyIn][currencyOut] = ret; } - return(ret); + return ret; } -BookListeners::pointer OrderBookDB::getBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut) +BookListeners::pointer OrderBookDB::getBookListeners(const uint160& currencyIn, const uint160& currencyOut, + const uint160& issuerIn, const uint160& issuerOut) { + BookListeners::pointer ret; boost::recursive_mutex::scoped_lock sl(mLock); - std::map > > >::iterator it0=mListeners.find(issuerIn); - if(it0 != mListeners.end()) - { - std::map > >::iterator it1=(*it0).second.find(issuerOut); - if(it1 != (*it0).second.end()) - { - std::map >::iterator it2=(*it1).second.find(currencyIn); - if(it2 != (*it1).second.end()) - { - std::map::iterator it3=(*it2).second.find(currencyOut); - if(it3 != (*it2).second.end()) - { - return( (*it3).second ); - } - } - } - } - return(BookListeners::pointer()); + + std::map > > >::iterator + it0 = mListeners.find(issuerIn); + if(it0 == mListeners.end()) + return ret; + + std::map > >::iterator + it1 = (*it0).second.find(issuerOut); + if(it1 == (*it0).second.end()) + return ret; + + std::map >::iterator it2 = (*it1).second.find(currencyIn); + if(it2 == (*it1).second.end()) + return ret; + + std::map::iterator it3 = (*it2).second.find(currencyOut); + if(it3 == (*it2).second.end()) + return ret; + + return (*it3).second; } /* @@ -182,49 +187,58 @@ BookListeners::pointer OrderBookDB::getBookListeners(uint160 currencyIn, uint160 */ // Based on the meta, send the meta to the streams that are listening // We need to determine which streams a given meta effects -void OrderBookDB::processTxn(const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta,Json::Value& jvObj) +void OrderBookDB::processTxn(const SerializedTransaction& stTxn, TER terResult, + TransactionMetaSet::pointer& meta, Json::Value& jvObj) { boost::recursive_mutex::scoped_lock sl(mLock); - if(terResult==tesSUCCESS) + if (terResult == tesSUCCESS) { // check if this is an offer or an offer cancel or a payment that consumes an offer //check to see what the meta looks like - BOOST_FOREACH(STObject& node,meta->getNodes()) + BOOST_FOREACH(STObject& node, meta->getNodes()) { - try{ - if(node.getFieldU16(sfLedgerEntryType)==ltOFFER) + try + { + if (node.getFieldU16(sfLedgerEntryType) == ltOFFER) { SField* field=NULL; - if(node.getFName() == sfModifiedNode) + if (node.getFName() == sfModifiedNode) { - field=&sfPreviousFields; - }else if(node.getFName() == sfCreatedNode) - { - field=&sfNewFields; + field = &sfPreviousFields; + } + else if (node.getFName() == sfCreatedNode) + { + field = &sfNewFields; + } + else if (node.getFName() == sfDeletedNode) + { + field = &sfFinalFields; } - // FIXME: What if an order is deleted? if (field) { - const STObject* previous = dynamic_cast(node.peekAtPField(*field)); - if(previous) + const STObject* data = dynamic_cast(node.peekAtPField(*field)); + if (data) { - STAmount takerGets = previous->getFieldAmount(sfTakerGets); - uint160 currencyOut=takerGets.getCurrency(); - uint160 issuerOut=takerGets.getIssuer(); + STAmount takerGets = data->getFieldAmount(sfTakerGets); + uint160 currencyOut = takerGets.getCurrency(); + uint160 issuerOut = takerGets.getIssuer(); - STAmount takerPays = previous->getFieldAmount(sfTakerPays); - uint160 currencyIn=takerPays.getCurrency(); - uint160 issuerIn=takerPays.getIssuer(); + STAmount takerPays = data->getFieldAmount(sfTakerPays); + uint160 currencyIn = takerPays.getCurrency(); + uint160 issuerIn = takerPays.getIssuer(); // determine the OrderBook - BookListeners::pointer book=getBookListeners(currencyIn,currencyOut,issuerIn,issuerOut); - if(book) book->publish(jvObj); + BookListeners::pointer book = + getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); + if (book) + book->publish(jvObj); } } } - }catch(...) + } + catch (...) { cLog(lsINFO) << "Fields not found in OrderBookDB::processTxn"; } @@ -234,18 +248,19 @@ void OrderBookDB::processTxn(const SerializedTransaction& stTxn, TER terResult,T void BookListeners::addSubscriber(InfoSub::ref sub) { + boost::recursive_mutex::scoped_lock sl(mLock); mListeners[sub->getSeq()] = sub; } void BookListeners::removeSubscriber(uint64 seq) { + boost::recursive_mutex::scoped_lock sl(mLock); mListeners.erase(seq); } void BookListeners::publish(Json::Value& jvObj) { - //Json::Value jvObj=node.getJson(0); - + boost::recursive_mutex::scoped_lock sl(mLock); NetworkOPs::subMapType::const_iterator it = mListeners.begin(); while (it != mListeners.end()) { diff --git a/src/cpp/ripple/OrderBookDB.h b/src/cpp/ripple/OrderBookDB.h index 6133f41e09..768ca05a55 100644 --- a/src/cpp/ripple/OrderBookDB.h +++ b/src/cpp/ripple/OrderBookDB.h @@ -17,6 +17,8 @@ class BookListeners { boost::unordered_map mListeners; + boost::recursive_mutex mLock; + public: typedef boost::shared_ptr pointer; @@ -58,8 +60,10 @@ public: float getPrice(uint160& currencyIn,uint160& currencyOut); - BookListeners::pointer getBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut); - BookListeners::pointer makeBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut); + BookListeners::pointer getBookListeners(const uint160& currencyIn, const uint160& currencyOut, + const uint160& issuerIn, const uint160& issuerOut); + BookListeners::pointer makeBookListeners(const uint160& currencyIn, const uint160& currencyOut, + const uint160& issuerIn, const uint160& issuerOut); // see if this txn effects any orderbook void processTxn(const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta,Json::Value& jvObj); diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index f63fa88f1f..97b3f1b341 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -2609,12 +2609,12 @@ Json::Value RPCHandler::doSubscribe(Json::Value jvRequest) { uint160 currencyOut; STAmount::issuerFromString(currencyOut,(*it)["CurrencyOut"].asString()); - uint160 issuerOut=RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID(); + uint160 issuerOut = RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID(); uint160 currencyIn; STAmount::issuerFromString(currencyOut,(*it)["CurrencyIn"].asString()); - uint160 issuerIn=RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID(); + uint160 issuerIn = RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID(); - mNetOps->subBook(ispSub,currencyIn,currencyOut,issuerIn,issuerOut); + mNetOps->subBook(ispSub, currencyIn, currencyOut, issuerIn, issuerOut); if((*it)["StateNow"].asBool()) { @@ -2723,10 +2723,10 @@ Json::Value RPCHandler::doUnsubscribe(Json::Value jvRequest) { uint160 currencyOut; STAmount::issuerFromString(currencyOut,(*it)["CurrencyOut"].asString()); - uint160 issuerOut=RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID(); + uint160 issuerOut = RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID(); uint160 currencyIn; STAmount::issuerFromString(currencyOut,(*it)["CurrencyIn"].asString()); - uint160 issuerIn=RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID(); + uint160 issuerIn = RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID(); mNetOps->unsubBook(ispSub->getSeq(), currencyIn, currencyOut, issuerIn, issuerOut); }