From 62f6d030c6665537c43405961cc6f12da5ad3180 Mon Sep 17 00:00:00 2001 From: jed Date: Thu, 31 Jan 2013 10:59:19 -0800 Subject: [PATCH 01/10] still working --- src/cpp/ripple/Application.cpp | 2 ++ src/cpp/ripple/Application.h | 3 +++ src/cpp/ripple/NetworkOPs.cpp | 1 + src/cpp/ripple/NetworkOPs.h | 2 ++ src/cpp/ripple/OrderBook.h | 7 +++++ src/cpp/ripple/OrderBookDB.cpp | 44 +++++++++++++++++++++++++++++++- src/cpp/ripple/OrderBookDB.h | 9 ++++++- src/cpp/ripple/Pathfinder.cpp | 8 +++--- src/cpp/ripple/Pathfinder.h | 3 +-- src/cpp/ripple/TransactionMeta.h | 1 + src/js/sjcl | 2 +- 11 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/cpp/ripple/Application.cpp b/src/cpp/ripple/Application.cpp index a2d608279c..17c37c3f43 100644 --- a/src/cpp/ripple/Application.cpp +++ b/src/cpp/ripple/Application.cpp @@ -147,6 +147,8 @@ void Application::setup() else startNewLedger(); + mOrderBookDB.setup(theApp->getLedgerMaster().getCurrentLedger()); // TODO: We need to update this if the ledger jumps + // // Begin validation and ip maintenance. // - Wallet maintains local information: including identity and network connection persistence information. diff --git a/src/cpp/ripple/Application.h b/src/cpp/ripple/Application.h index 7ba1003ce5..343c9d26c2 100644 --- a/src/cpp/ripple/Application.h +++ b/src/cpp/ripple/Application.h @@ -24,6 +24,7 @@ #include "ProofOfWork.h" #include "LoadManager.h" #include "TransactionQueue.h" +#include "OrderBookDB.h" class RPCDoor; class PeerDoor; @@ -66,6 +67,7 @@ class Application LoadManager mLoadMgr; LoadFeeTrack mFeeTrack; TXQueue mTxnQueue; + OrderBookDB mOrderBookDB; DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB; @@ -115,6 +117,7 @@ public: LoadFeeTrack& getFeeTrack() { return mFeeTrack; } TXQueue& getTxnQueue() { return mTxnQueue; } PeerDoor& getPeerDoor() { return *mPeerDoor; } + OrderBookDB& getOrderBookDB() { return mOrderBookDB; } bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); } diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 3fbf0768b2..92a47fa5fc 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1316,6 +1316,7 @@ void NetworkOPs::pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedT ispListener->send(jvObj); } } + theApp->getOrderBookDB().processTxn(stTxn, terResult, meta, jvObj); pubAccountTransaction(lpCurrent, stTxn, terResult, true, meta); } diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index 0979671fb7..c03edae49f 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -71,6 +71,7 @@ protected: typedef boost::unordered_map >::iterator subInfoMapIterator; typedef boost::unordered_map > subSubmitMapType; + //typedef boost::unordered_map > subOrderMap; typedef boost::unordered_map subRpcMapType; @@ -103,6 +104,7 @@ protected: subInfoMapType mSubAccount; subInfoMapType mSubRTAccount; subSubmitMapType mSubmitMap; // TODO: probably dump this + subRpcMapType mRpcSubMap; diff --git a/src/cpp/ripple/OrderBook.h b/src/cpp/ripple/OrderBook.h index b4556f01d9..c805040849 100644 --- a/src/cpp/ripple/OrderBook.h +++ b/src/cpp/ripple/OrderBook.h @@ -1,5 +1,7 @@ #include "SerializedLedger.h" +#include "NetworkOPs.h" #include + /* Encapsulates the SLE for an orderbook */ @@ -12,6 +14,8 @@ class OrderBook uint160 mIssuerIn; uint160 mIssuerOut; + boost::unordered_set mListeners; + //SerializedLedgerEntry::pointer mLedgerEntry; OrderBook(SerializedLedgerEntry::pointer ledgerEntry); // For accounts in a ledger public: @@ -30,6 +34,9 @@ public: // looks through the best offers to see how much it would cost to take the given amount STAmount& getTakePrice(STAmount& takeAmount); + + void addSubscriber(InfoSub* sub); + void removeSubscriber(InfoSub* sub); }; // vim:ts=4 diff --git a/src/cpp/ripple/OrderBookDB.cpp b/src/cpp/ripple/OrderBookDB.cpp index 192cab703b..0f6956f8c5 100644 --- a/src/cpp/ripple/OrderBookDB.cpp +++ b/src/cpp/ripple/OrderBookDB.cpp @@ -3,8 +3,13 @@ #include +OrderBookDB::OrderBookDB() +{ + +} + // TODO: this would be way faster if we could just look under the order dirs -OrderBookDB::OrderBookDB(Ledger::pointer ledger) +void OrderBookDB::setup(Ledger::pointer ledger) { // walk through the entire ledger looking for orderbook entries uint256 currentIndex=ledger->getFirstLedgerIndex(); @@ -53,4 +58,41 @@ void OrderBookDB::getBooks(const uint160& issuerID, const uint160& currencyID, s } } } +} + +OrderBook::pointer OrderBookDB::getBook(uint160 mCurrencyIn, uint160 mCurrencyOut, uint160 mIssuerIn, uint160 mIssuerOut) +{ + +} + +/* +"CreatedNode" : { +"LedgerEntryType" : "Offer", +"LedgerIndex" : "F353BF8A7DCE35EA2985596F4C8421E30EF3B9A21618566BFE0ED00B62A8A5AB", +"NewFields" : { +"Account" : "rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY", +"BookDirectory" : "FF26BE244767D0EA9EFD523941439009E4185E4CBB918F714C08E1BC9BF04000", +"Sequence" : 112, +"TakerGets" : "400000000", +"TakerPays" : { +"currency" : "BTC", +"issuer" : "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", +"value" : "1" +} +} +}*/ + +void OrderBookDB::processTxn(const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta,Json::Value& jvObj) +{ + // 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()) + { + if(node.getFieldU16(sfLedgerEntryType)==ltOFFER) + { + + } + } + + } \ No newline at end of file diff --git a/src/cpp/ripple/OrderBookDB.h b/src/cpp/ripple/OrderBookDB.h index ded3562ae4..dc3983a36e 100644 --- a/src/cpp/ripple/OrderBookDB.h +++ b/src/cpp/ripple/OrderBookDB.h @@ -11,11 +11,13 @@ class OrderBookDB std::vector mEmptyVector; std::vector mXRPOrders; std::map > mIssuerMap; + //std::vector mAllOrderBooks; std::map mKnownMap; public: - OrderBookDB(Ledger::pointer ledger); + OrderBookDB(); + void setup(Ledger::pointer ledger); // return list of all orderbooks that want XRP std::vector& getXRPInBooks(){ return mXRPOrders; } @@ -27,6 +29,11 @@ public: // returns the best rate we can find float getPrice(uint160& currencyIn,uint160& currencyOut); + + OrderBook::pointer getBook(uint160 mCurrencyIn, uint160 mCurrencyOut, uint160 mIssuerIn, uint160 mIssuerOut); + // see if this txn effects any orderbook + void processTxn(const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta,Json::Value& jvObj); + }; // vim:ts=4 diff --git a/src/cpp/ripple/Pathfinder.cpp b/src/cpp/ripple/Pathfinder.cpp index a7f03cc1cf..efa070a189 100644 --- a/src/cpp/ripple/Pathfinder.cpp +++ b/src/cpp/ripple/Pathfinder.cpp @@ -269,7 +269,7 @@ bool Pathfinder::findPaths(const unsigned int iMaxSteps, const unsigned int iMax else if (!speEnd.mCurrencyID) { // Last element is for XRP, continue with qualifying books. - BOOST_FOREACH(OrderBook::ref book, mOrderBook.getXRPInBooks()) + BOOST_FOREACH(OrderBook::ref book, theApp->getOrderBookDB().getXRPInBooks()) { // XXX Don't allow looping through same order books. @@ -357,7 +357,7 @@ bool Pathfinder::findPaths(const unsigned int iMaxSteps, const unsigned int iMax // Every book that wants the source currency. std::vector books; - mOrderBook.getBooks(spPath.mCurrentAccount, spPath.mCurrencyID, books); + theApp->getOrderBookDB().getBooks(spPath.mCurrentAccount, spPath.mCurrencyID, books); BOOST_FOREACH(OrderBook::ref book,books) { @@ -499,7 +499,7 @@ void Pathfinder::addOptions(PathOption::pointer tail) { if (!tail->mCurrencyID) { // source XRP - BOOST_FOREACH(OrderBook::ref book, mOrderBook.getXRPInBooks()) + BOOST_FOREACH(OrderBook::ref book, theApp->getOrderBookDB().getXRPInBooks()) { PathOption::pointer pathOption(new PathOption(tail)); @@ -533,7 +533,7 @@ void Pathfinder::addOptions(PathOption::pointer tail) // every offer that wants the source currency std::vector books; - mOrderBook.getBooks(tail->mCurrentAccount, tail->mCurrencyID, books); + theApp->getOrderBookDB().getBooks(tail->mCurrentAccount, tail->mCurrencyID, books); BOOST_FOREACH(OrderBook::ref book,books) { diff --git a/src/cpp/ripple/Pathfinder.h b/src/cpp/ripple/Pathfinder.h index 5682778e49..e624d51675 100644 --- a/src/cpp/ripple/Pathfinder.h +++ b/src/cpp/ripple/Pathfinder.h @@ -3,7 +3,6 @@ #include "SerializedTypes.h" #include "RippleAddress.h" -#include "OrderBookDB.h" #include "RippleCalc.h" #include @@ -42,7 +41,7 @@ class Pathfinder uint160 mSrcIssuerID; STAmount mSrcAmount; - OrderBookDB mOrderBook; + //OrderBookDB mOrderBook; Ledger::pointer mLedger; PathState::pointer mPsDefault; diff --git a/src/cpp/ripple/TransactionMeta.h b/src/cpp/ripple/TransactionMeta.h index 5386b96b87..fd07635c8c 100644 --- a/src/cpp/ripple/TransactionMeta.h +++ b/src/cpp/ripple/TransactionMeta.h @@ -56,6 +56,7 @@ public: void addRaw(Serializer&, TER, uint32 index); STObject getAsObject() const; + STArray& getNodes(){ return(mNodes); } static bool thread(STObject& node, const uint256& prevTxID, uint32 prevLgrID); }; diff --git a/src/js/sjcl b/src/js/sjcl index dbdef434e7..d04d0bdccd 160000 --- a/src/js/sjcl +++ b/src/js/sjcl @@ -1 +1 @@ -Subproject commit dbdef434e76c3f16835f3126a7ff1c717b1ce8af +Subproject commit d04d0bdccd986e434b98fe393e1e01286c10fc36 From eb27240610fc28fac2cb6c212e31f235ef0d2469 Mon Sep 17 00:00:00 2001 From: jed Date: Tue, 5 Feb 2013 13:04:38 -0800 Subject: [PATCH 02/10] first draft --- src/cpp/ripple/NetworkOPs.cpp | 14 ++++ src/cpp/ripple/NetworkOPs.h | 3 + src/cpp/ripple/OrderBook.cpp | 2 + src/cpp/ripple/OrderBook.h | 5 -- src/cpp/ripple/OrderBookDB.cpp | 129 +++++++++++++++++++++++++++++++-- src/cpp/ripple/OrderBookDB.h | 21 +++++- src/cpp/ripple/Pathfinder.cpp | 6 +- src/cpp/ripple/RPCHandler.cpp | 34 +++++++++ test/send-test.js | 6 +- 9 files changed, 200 insertions(+), 20 deletions(-) diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 92a47fa5fc..aa9bcd9204 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1447,6 +1447,20 @@ void NetworkOPs::unsubAccount(InfoSub* ispListener, const boost::unordered_setgetOrderBookDB().makeBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); + if(listeners) listeners->addSubscriber(ispListener); + return(true); +} + +bool NetworkOPs::unsubBook(InfoSub* ispListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut) +{ + BookListeners::pointer listeners=theApp->getOrderBookDB().getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); + if(listeners) listeners->removeSubscriber(ispListener); + return(true); +} + void NetworkOPs::newLCL(int proposers, int convergeTime, const uint256& ledgerHash) { assert(convergeTime); diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index c03edae49f..ae6bff9b08 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -284,6 +284,9 @@ public: bool subServer(InfoSub* ispListener, Json::Value& jvResult); bool unsubServer(InfoSub* ispListener); + bool subBook(InfoSub* ispListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut); + bool unsubBook(InfoSub* ispListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut); + bool subTransactions(InfoSub* ispListener); bool unsubTransactions(InfoSub* ispListener); diff --git a/src/cpp/ripple/OrderBook.cpp b/src/cpp/ripple/OrderBook.cpp index 2cf716257e..300ebcd31b 100644 --- a/src/cpp/ripple/OrderBook.cpp +++ b/src/cpp/ripple/OrderBook.cpp @@ -20,4 +20,6 @@ OrderBook::OrderBook(SerializedLedgerEntry::pointer ledgerEntry) mBookBase=Ledger::getBookBase(mCurrencyOut,mIssuerOut,mCurrencyIn,mIssuerIn); } + + // vim:ts=4 diff --git a/src/cpp/ripple/OrderBook.h b/src/cpp/ripple/OrderBook.h index c805040849..813709d3b5 100644 --- a/src/cpp/ripple/OrderBook.h +++ b/src/cpp/ripple/OrderBook.h @@ -14,8 +14,6 @@ class OrderBook uint160 mIssuerIn; uint160 mIssuerOut; - boost::unordered_set mListeners; - //SerializedLedgerEntry::pointer mLedgerEntry; OrderBook(SerializedLedgerEntry::pointer ledgerEntry); // For accounts in a ledger public: @@ -34,9 +32,6 @@ public: // looks through the best offers to see how much it would cost to take the given amount STAmount& getTakePrice(STAmount& takeAmount); - - void addSubscriber(InfoSub* sub); - void removeSubscriber(InfoSub* sub); }; // vim:ts=4 diff --git a/src/cpp/ripple/OrderBookDB.cpp b/src/cpp/ripple/OrderBookDB.cpp index 0f6956f8c5..74faa3b12a 100644 --- a/src/cpp/ripple/OrderBookDB.cpp +++ b/src/cpp/ripple/OrderBookDB.cpp @@ -2,6 +2,7 @@ #include "Log.h" #include +SETUP_LOG(); OrderBookDB::OrderBookDB() { @@ -11,6 +12,10 @@ OrderBookDB::OrderBookDB() // TODO: this would be way faster if we could just look under the order dirs void OrderBookDB::setup(Ledger::pointer ledger) { + mXRPOrders.clear(); + mIssuerMap.clear(); + mKnownMap.clear(); + // walk through the entire ledger looking for orderbook entries uint256 currentIndex=ledger->getFirstLedgerIndex(); while(currentIndex.isNonZero()) @@ -60,9 +65,37 @@ void OrderBookDB::getBooks(const uint160& issuerID, const uint160& currencyID, s } } -OrderBook::pointer OrderBookDB::getBook(uint160 mCurrencyIn, uint160 mCurrencyOut, uint160 mIssuerIn, uint160 mIssuerOut) +BookListeners::pointer OrderBookDB::makeBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut) { + BookListeners::pointer ret=getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut); + if(!ret) + { + ret=BookListeners::pointer(new BookListeners); + mListeners[issuerIn][issuerOut][currencyIn][currencyOut]=ret; + } + return(ret); +} +BookListeners::pointer OrderBookDB::getBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut) +{ + 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()); } /* @@ -80,19 +113,101 @@ OrderBook::pointer OrderBookDB::getBook(uint160 mCurrencyIn, uint160 mCurrencyOu "value" : "1" } } -}*/ +} +"ModifiedNode" : { +"FinalFields" : { +"Account" : "rHTxKLzRbniScyQFGMb3NodmxA848W8dKM", +"BookDirectory" : "407AF8FFDE71114B1981574FDDA9B0334572D56FC579735B4B0BD7A625405555", +"BookNode" : "0000000000000000", +"Flags" : 0, +"OwnerNode" : "0000000000000000", +"Sequence" : 32, +"TakerGets" : "149900000000", +"TakerPays" : { +"currency" : "USD", +"issuer" : "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X", +"value" : "49.96666666666667" +} +}, +"LedgerEntryType" : "Offer", +"LedgerIndex" : "C60F8CC514208FA5F7BD03CF1B64B38B7183CD52318FCBBD3726350D4FE693B0", +"PreviousFields" : { +"TakerGets" : "150000000000", +"TakerPays" : { +"currency" : "USD", +"issuer" : "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X", +"value" : "50" +} +}, +"PreviousTxnID" : "1A6AAE3F1AC5A8A7554A5ABC395D17FED5BF62CD90181AA8E4315EDFED4EDEB3", +"PreviousTxnLgrSeq" : 140734 +} + +*/ +// 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) { - // 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()) + if(terResult==tesSUCCESS) { - if(node.getFieldU16(sfLedgerEntryType)==ltOFFER) + // 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()) { + try{ + if(node.getFieldU16(sfLedgerEntryType)==ltOFFER) + { + SField* field=NULL; + if(node.getFName() == sfModifiedNode) + { + field=&sfPreviousFields; + }else if(node.getFName() == sfCreatedNode) + { + field=&sfNewFields; + } + + const STObject* previous = dynamic_cast(node.peekAtPField(*field)); + if(previous) + { + STAmount& takerGets = previous->getFieldAmount(sfTakerGets); + uint160 currencyOut=takerGets.getCurrency(); + uint160 issuerOut=takerGets.getIssuer(); + + STAmount& takerPays = previous->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); + } + } + }catch(...) + { + cLog(lsINFO) << "Fields not found in OrderBookDB::processTxn"; + } } } - +} +void BookListeners::addSubscriber(InfoSub* sub) +{ + mListeners.insert(sub); +} + +void BookListeners::removeSubscriber(InfoSub* sub) +{ + mListeners.erase(sub); +} + +void BookListeners::publish(Json::Value& jvObj) +{ + //Json::Value jvObj=node.getJson(0); + + BOOST_FOREACH(InfoSub* sub,mListeners) + { + sub->send(jvObj); + } } \ No newline at end of file diff --git a/src/cpp/ripple/OrderBookDB.h b/src/cpp/ripple/OrderBookDB.h index dc3983a36e..1461e500c9 100644 --- a/src/cpp/ripple/OrderBookDB.h +++ b/src/cpp/ripple/OrderBookDB.h @@ -1,11 +1,24 @@ #include "Ledger.h" #include "OrderBook.h" +#include + /* we can eventually make this cached and just update it as transactions come in. But for now it is probably faster to just generate it each time */ +class BookListeners +{ + boost::unordered_set mListeners; +public: + typedef boost::shared_ptr pointer; + + void addSubscriber(InfoSub* sub); + void removeSubscriber(InfoSub* sub); + void publish(Json::Value& jvObj); +}; + class OrderBookDB { std::vector mEmptyVector; @@ -13,6 +26,9 @@ class OrderBookDB std::map > mIssuerMap; //std::vector mAllOrderBooks; + // issuerIn, issuerOut, currencyIn, currencyOut + std::map > > > mListeners; + std::map mKnownMap; public: @@ -30,10 +46,11 @@ public: float getPrice(uint160& currencyIn,uint160& currencyOut); - OrderBook::pointer getBook(uint160 mCurrencyIn, uint160 mCurrencyOut, uint160 mIssuerIn, uint160 mIssuerOut); + BookListeners::pointer getBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut); + BookListeners::pointer makeBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut); + // see if this txn effects any orderbook void processTxn(const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta,Json::Value& jvObj); - }; // vim:ts=4 diff --git a/src/cpp/ripple/Pathfinder.cpp b/src/cpp/ripple/Pathfinder.cpp index efa070a189..eaba5e6688 100644 --- a/src/cpp/ripple/Pathfinder.cpp +++ b/src/cpp/ripple/Pathfinder.cpp @@ -12,8 +12,6 @@ SETUP_LOG(); /* -JED: V IIII - we just need to find a succession of the highest quality paths there until we find enough width Don't do branching within each path @@ -133,11 +131,13 @@ bool Pathfinder::bDefaultPath(const STPath& spPath) // functionality is left to the future. // Pathfinder::Pathfinder(const RippleAddress& uSrcAccountID, const RippleAddress& uDstAccountID, const uint160& uSrcCurrencyID, const uint160& uSrcIssuerID, const STAmount& saDstAmount) - : mSrcAccountID(uSrcAccountID.getAccountID()), mDstAccountID(uDstAccountID.getAccountID()), mDstAmount(saDstAmount), mSrcCurrencyID(uSrcCurrencyID), mSrcIssuerID(uSrcIssuerID), mOrderBook(theApp->getLedgerMaster().getCurrentLedger()) + : mSrcAccountID(uSrcAccountID.getAccountID()), mDstAccountID(uDstAccountID.getAccountID()), mDstAmount(saDstAmount), mSrcCurrencyID(uSrcCurrencyID), mSrcIssuerID(uSrcIssuerID) { mLedger = theApp->getLedgerMaster().getCurrentLedger(); mSrcAmount = STAmount(uSrcCurrencyID, uSrcIssuerID, 1, 0, true); // -1/uSrcIssuerID/uSrcIssuerID + theApp->getOrderBookDB().setup( theApp->getLedgerMaster().getCurrentLedger()); // TODO: have the orderbook update itself rather than rebuild it from scratch each time + // Construct the default path for later comparison. PathState::pointer psDefault = boost::make_shared(mDstAmount, mSrcAmount, mLedger); diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index e6a245aad6..7f2045779b 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -2449,6 +2449,25 @@ Json::Value RPCHandler::doSubscribe(Json::Value jvRequest) } } + if (jvRequest.isMember("books")) + { + for (Json::Value::iterator it = jvRequest["books"].begin(); it != jvRequest["books"].end(); it++) + { + uint160 currencyOut; + STAmount::issuerFromString(currencyOut,(*it)["CurrencyOut"].asString()); + uint160 issuerOut=RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID(); + uint160 currencyIn; + STAmount::issuerFromString(currencyOut,(*it)["CurrencyIn"].asString()); + uint160 issuerIn=RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID(); + + mNetOps->subBook(ispSub,currencyIn,currencyOut,issuerIn,issuerOut); + if((*it)["StateNow"].asBool()) + { + + } + } + } + return jvResult; } @@ -2546,6 +2565,21 @@ Json::Value RPCHandler::doUnsubscribe(Json::Value jvRequest) } } + if (jvRequest.isMember("books")) + { + for (Json::Value::iterator it = jvRequest["books"].begin(); it != jvRequest["books"].end(); it++) + { + uint160 currencyOut; + STAmount::issuerFromString(currencyOut,(*it)["CurrencyOut"].asString()); + uint160 issuerOut=RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID(); + uint160 currencyIn; + STAmount::issuerFromString(currencyOut,(*it)["CurrencyIn"].asString()); + uint160 issuerIn=RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID(); + + mNetOps->unsubBook(ispSub,currencyIn,currencyOut,issuerIn,issuerOut); + } + } + return jvResult; } diff --git a/test/send-test.js b/test/send-test.js index d2fe9c7f32..98bf63d0e0 100644 --- a/test/send-test.js +++ b/test/send-test.js @@ -40,8 +40,8 @@ buster.testCase("Fee Changes", { */ buster.testCase("Sending", { - 'setUp' : testutils.build_setup(), - // 'setUp' : testutils.build_setup({verbose: true , no_server: true}), + //'setUp' : testutils.build_setup(), + 'setUp' : testutils.build_setup({verbose: true , no_server: true}), 'tearDown' : testutils.build_teardown(), "send XRP to non-existent account with insufficent fee" : @@ -975,7 +975,7 @@ buster.testCase("Indirect ripple", { }); }, - "indirect ripple with path" : + "=> indirect ripple with path" : function (done) { var self = this; From 5aa810404b2df974acfc027bfe6e4db419629ee9 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 5 Feb 2013 21:33:42 -0800 Subject: [PATCH 03/10] Track uptime. Update local fee schedule based on load manager. --- src/cpp/ripple/Application.cpp | 1 + src/cpp/ripple/JobQueue.cpp | 10 +++++ src/cpp/ripple/JobQueue.h | 1 + src/cpp/ripple/LoadManager.cpp | 68 +++++++++++++++++++++++++++++++++- src/cpp/ripple/LoadManager.h | 8 ++++ src/cpp/ripple/LoadMonitor.cpp | 14 +++++++ src/cpp/ripple/LoadMonitor.h | 5 ++- src/cpp/ripple/RPCHandler.cpp | 24 ++++++++++++ 8 files changed, 128 insertions(+), 3 deletions(-) diff --git a/src/cpp/ripple/Application.cpp b/src/cpp/ripple/Application.cpp index 2f5d9f68a1..072ceb0b71 100644 --- a/src/cpp/ripple/Application.cpp +++ b/src/cpp/ripple/Application.cpp @@ -52,6 +52,7 @@ Application::Application() : mJobQueue.setThreadCount(); mSweepTimer.expires_from_now(boost::posix_time::seconds(10)); mSweepTimer.async_wait(boost::bind(&Application::sweep, this)); + mLoadMgr.init(); } extern const char *RpcDBInit[], *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[], *NetNodeDBInit[]; diff --git a/src/cpp/ripple/JobQueue.cpp b/src/cpp/ripple/JobQueue.cpp index 5d0106f381..3a795fd141 100644 --- a/src/cpp/ripple/JobQueue.cpp +++ b/src/cpp/ripple/JobQueue.cpp @@ -181,6 +181,16 @@ Json::Value JobQueue::getJson(int) return ret; } +int JobQueue::isOverloaded() +{ + int count = 0; + boost::mutex::scoped_lock sl(mJobLock); + for (int i = 0; i < NUM_JOB_TYPES; ++i) + if (mJobLoads[i].isOver()) + ++count; + return count; +} + void JobQueue::shutdown() { // shut down the job queue without completing pending jobs cLog(lsINFO) << "Job queue shutting down"; diff --git a/src/cpp/ripple/JobQueue.h b/src/cpp/ripple/JobQueue.h index 1df31aca7e..22bfefad95 100644 --- a/src/cpp/ripple/JobQueue.h +++ b/src/cpp/ripple/JobQueue.h @@ -108,6 +108,7 @@ public: LoadEvent::autoptr getLoadEventAP(JobType t) { return LoadEvent::autoptr(new LoadEvent(mJobLoads[t], true, 1)); } + int isOverloaded(); Json::Value getJson(int c = 0); }; diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index daacb52153..f8454c663d 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -1,15 +1,18 @@ #include "LoadManager.h" #include +#include +#include #include "Log.h" #include "Config.h" +#include "Application.h" SETUP_LOG(); LoadManager::LoadManager(int creditRate, int creditLimit, int debitWarn, int debitLimit) : mCreditRate(creditRate), mCreditLimit(creditLimit), mDebitWarn(debitWarn), mDebitLimit(debitLimit), - mCosts(LT_MAX) + mShutdown(false), mUptime(0), mCosts(LT_MAX) { addLoadCost(LoadCost(LT_InvalidRequest, 10, LC_CPU | LC_Network)); addLoadCost(LoadCost(LT_RequestNoReply, 1, LC_CPU | LC_Disk)); @@ -25,6 +28,30 @@ LoadManager::LoadManager(int creditRate, int creditLimit, int debitWarn, int deb addLoadCost(LoadCost(LT_CheapQuery, 1, LC_CPU)); } +void LoadManager::init() +{ + boost::thread(boost::bind(&LoadManager::threadEntry, this)).detach(); +} + +LoadManager::~LoadManager() +{ + { + boost::mutex::scoped_lock sl(mLock); + mShutdown = true; + } + + do + { + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + { + boost::mutex::scoped_lock sl(mLock); + if (!mShutdown) + return; + } + } + while (1); +} + int LoadManager::getCreditRate() const { @@ -239,6 +266,45 @@ Json::Value LoadFeeTrack::getJson(uint64 baseFee, uint32 referenceFeeUnits) return j; } +int LoadManager::getUptime() +{ + boost::mutex::scoped_lock sl(mLock); + return mUptime; +} + +void LoadManager::threadEntry() +{ + boost::posix_time::ptime t = boost::posix_time::microsec_clock::universal_time(); + while (1) + { + { + boost::mutex::scoped_lock sl(mLock); + if (mShutdown) + { + mShutdown = false; + return; + } + ++mUptime; + } + + if (theApp->getJobQueue().isOverloaded()) + theApp->getFeeTrack().raiseLocalFee(); + else + theApp->getFeeTrack().lowerLocalFee(); + + t += boost::posix_time::seconds(1); + boost::posix_time::time_duration when = t - boost::posix_time::microsec_clock::universal_time(); + + if (when.is_negative()) + { + cLog(lsWARNING) << "Backwards time jump"; + t = boost::posix_time::microsec_clock::universal_time(); + } + else + boost::this_thread::sleep(when); + } +} + BOOST_AUTO_TEST_SUITE(LoadManager_test) BOOST_AUTO_TEST_CASE(LoadFeeTrack_test) diff --git a/src/cpp/ripple/LoadManager.h b/src/cpp/ripple/LoadManager.h index 0cecd6c1e1..071d0f1436 100644 --- a/src/cpp/ripple/LoadManager.h +++ b/src/cpp/ripple/LoadManager.h @@ -86,6 +86,9 @@ protected: int mDebitWarn; // when a source drops below this, we warn int mDebitLimit; // when a source drops below this, we cut it off (should be negative) + bool mShutdown; + int mUptime; + mutable boost::mutex mLock; void canonicalize(LoadSource&, const time_t now) const; @@ -94,9 +97,13 @@ protected: void addLoadCost(const LoadCost& c) { mCosts[static_cast(c.mType)] = c; } + void threadEntry(); + public: LoadManager(int creditRate = 10, int creditLimit = 50, int debitWarn = -50, int debitLimit = -100); + ~LoadManager(); + void init(); int getCreditRate() const; int getCreditLimit() const; @@ -113,6 +120,7 @@ public: bool adjust(LoadSource&, LoadType l) const; int getCost(LoadType t) { return mCosts[static_cast(t)].mCost; } + int getUptime(); }; class LoadFeeTrack diff --git a/src/cpp/ripple/LoadMonitor.cpp b/src/cpp/ripple/LoadMonitor.cpp index b014c330ec..312de87a72 100644 --- a/src/cpp/ripple/LoadMonitor.cpp +++ b/src/cpp/ripple/LoadMonitor.cpp @@ -69,6 +69,18 @@ void LoadMonitor::addCountAndLatency(int counts, int latency) mLatencyMSPeak = lp; } +bool LoadMonitor::isOver() +{ + boost::mutex::scoped_lock sl(mLock); + + update(); + + if (mLatencyEvents == 0) + return 0; + + return isOverTarget(mLatencyMSAvg / (mLatencyEvents * 4), mLatencyMSPeak / (mLatencyEvents * 4)); +} + void LoadMonitor::getCountAndLatency(uint64& count, uint64& latencyAvg, uint64& latencyPeak, bool& isOver) { boost::mutex::scoped_lock sl(mLock); @@ -89,3 +101,5 @@ void LoadMonitor::getCountAndLatency(uint64& count, uint64& latencyAvg, uint64& } isOver = isOverTarget(latencyAvg, latencyPeak); } + +// vim:ts=4 diff --git a/src/cpp/ripple/LoadMonitor.h b/src/cpp/ripple/LoadMonitor.h index ba210b75c3..efda49b53b 100644 --- a/src/cpp/ripple/LoadMonitor.h +++ b/src/cpp/ripple/LoadMonitor.h @@ -35,8 +35,8 @@ public: void setTargetLatency(uint64 avg, uint64 pk) { - mTargetLatencyAvg = avg * 4; - mTargetLatencyPk = pk * 4; + mTargetLatencyAvg = avg; + mTargetLatencyPk = pk; } bool isOverTarget(uint64 avg, uint64 peak) @@ -46,6 +46,7 @@ public: } void getCountAndLatency(uint64& count, uint64& latencyAvg, uint64& latencyPeak, bool& isOver); + bool isOver(); }; class LoadEvent diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 8fa825b86a..7def72ca93 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -1786,6 +1786,21 @@ Json::Value RPCHandler::doLogin(Json::Value jvRequest) } #endif +static void textTime(std::string& text, int& seconds, const char *unitName, int unitVal) +{ + int i = seconds / unitVal; + if (i == 0) + return; + seconds -= unitVal * i; + if (!text.empty()) + text += ", "; + text += boost::lexical_cast(i); + text += " "; + text += unitName; + if (i > 1) + text += "s"; +} + // { // min_count: // optional, defaults to 10 // } @@ -1807,6 +1822,15 @@ Json::Value RPCHandler::doGetCounts(Json::Value jvRequest) if (dbKB > 0) ret["dbKB"] = dbKB; + std::string uptime; + int s = theApp->getLoadManager().getUptime(); + textTime(uptime, s, "year", 365*24*60*60); + textTime(uptime, s, "day", 24*60*60); + textTime(uptime, s, "hour", 24*60); + textTime(uptime, s, "minute", 60); + textTime(uptime, s, "second", 1); + ret["uptime"] = uptime; + return ret; } From fadceb072dca1581435e8fcc3f616be8e5609e85 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 5 Feb 2013 21:55:18 -0800 Subject: [PATCH 04/10] Get the time jump logic right. --- src/cpp/ripple/LoadManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index f8454c663d..485202b8fa 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -295,9 +295,9 @@ void LoadManager::threadEntry() t += boost::posix_time::seconds(1); boost::posix_time::time_duration when = t - boost::posix_time::microsec_clock::universal_time(); - if (when.is_negative()) + if ((when.is_negative()) || (when.total_seconds() > 1)) { - cLog(lsWARNING) << "Backwards time jump"; + cLog(lsWARNING) << "time jump"; t = boost::posix_time::microsec_clock::universal_time(); } else From 8c36646b8cbd1f6e44fcb011796f69a9c60fa255 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 5 Feb 2013 22:06:30 -0800 Subject: [PATCH 05/10] Make a fast, monotonic timer. --- src/cpp/ripple/LoadManager.cpp | 16 ++++++++++++++++ src/cpp/ripple/LoadManager.h | 2 ++ src/cpp/ripple/RPCHandler.cpp | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index 485202b8fa..013c7f2af6 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -10,6 +10,17 @@ SETUP_LOG(); +static volatile int* uptimePtr = NULL; + +int upTime() +{ + static time_t firstCall = time(NULL); + if (uptimePtr != NULL) + return *uptimePtr; + cLog(lsWARNING) << "slow uptime"; + return static_cast(time(NULL) - firstCall); +} + LoadManager::LoadManager(int creditRate, int creditLimit, int debitWarn, int debitLimit) : mCreditRate(creditRate), mCreditLimit(creditLimit), mDebitWarn(debitWarn), mDebitLimit(debitLimit), mShutdown(false), mUptime(0), mCosts(LT_MAX) @@ -26,15 +37,20 @@ LoadManager::LoadManager(int creditRate, int creditLimit, int debitWarn, int deb addLoadCost(LoadCost(LT_RequestData, 5, LC_Disk | LC_Network)); addLoadCost(LoadCost(LT_CheapQuery, 1, LC_CPU)); + } void LoadManager::init() { + if (uptimePtr == NULL) + uptimePtr = static_cast(&mUptime); boost::thread(boost::bind(&LoadManager::threadEntry, this)).detach(); } LoadManager::~LoadManager() { + if (uptimePtr == &mUptime) + uptimePtr = NULL; { boost::mutex::scoped_lock sl(mLock); mShutdown = true; diff --git a/src/cpp/ripple/LoadManager.h b/src/cpp/ripple/LoadManager.h index 071d0f1436..dea9c6c0b4 100644 --- a/src/cpp/ripple/LoadManager.h +++ b/src/cpp/ripple/LoadManager.h @@ -9,6 +9,8 @@ #include "types.h" +extern int upTime(); + enum LoadType { // types of load that can be placed on the server diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 7def72ca93..064b49860f 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -1823,7 +1823,7 @@ Json::Value RPCHandler::doGetCounts(Json::Value jvRequest) ret["dbKB"] = dbKB; std::string uptime; - int s = theApp->getLoadManager().getUptime(); + int s = upTime(); textTime(uptime, s, "year", 365*24*60*60); textTime(uptime, s, "day", 24*60*60); textTime(uptime, s, "hour", 24*60); From 180845498384455b1c57196f29eae0afe9a9f8db Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 5 Feb 2013 22:31:26 -0800 Subject: [PATCH 06/10] Use the new uptime code. Replace slow, non-monotonic 'time(NULL)' calls with fast, almost-always-monotonic 'upTime()' calls. --- src/cpp/ripple/KeyCache.h | 14 ++++++++------ src/cpp/ripple/LedgerAcquire.cpp | 4 ++-- src/cpp/ripple/LedgerAcquire.h | 6 +++--- src/cpp/ripple/LoadManager.cpp | 10 +++++----- src/cpp/ripple/LoadManager.h | 11 +++++++---- src/cpp/ripple/LoadMonitor.cpp | 2 +- src/cpp/ripple/LoadMonitor.h | 5 +++-- src/cpp/ripple/Suppression.cpp | 8 +++++--- src/cpp/ripple/Suppression.h | 2 +- src/cpp/ripple/TaggedCache.h | 17 +++++++++-------- 10 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/cpp/ripple/KeyCache.h b/src/cpp/ripple/KeyCache.h index 63bc2e80c6..13387fb6d2 100644 --- a/src/cpp/ripple/KeyCache.h +++ b/src/cpp/ripple/KeyCache.h @@ -6,11 +6,13 @@ #include #include +extern int upTime(); + template class KeyCache { // Maintains a cache of keys with no associated data public: typedef c_Key key_type; - typedef boost::unordered_map map_type; + typedef boost::unordered_map map_type; typedef typename map_type::iterator map_iterator; protected: @@ -65,7 +67,7 @@ public: if (it == mCache.end()) return false; if (refresh) - it->second = time(NULL); + it->second = upTime(); return true; } @@ -88,19 +90,19 @@ public: map_iterator it = mCache.find(key); if (it != mCache.end()) { - it->second = time(NULL); + it->second = upTime(); return false; } - mCache.insert(std::make_pair(key, time(NULL))); + mCache.insert(std::make_pair(key, upTime())); return true; } void sweep() { // Remove stale entries from the cache - time_t now = time(NULL); + int now = upTime(); boost::mutex::scoped_lock sl(mNCLock); - time_t target; + int target; if ((mTargetSize == 0) || (mCache.size() <= mTargetSize)) target = now - mTargetAge; else diff --git a/src/cpp/ripple/LedgerAcquire.cpp b/src/cpp/ripple/LedgerAcquire.cpp index 75a2e42436..f24c6fe463 100644 --- a/src/cpp/ripple/LedgerAcquire.cpp +++ b/src/cpp/ripple/LedgerAcquire.cpp @@ -22,7 +22,7 @@ DECLARE_INSTANCE(LedgerAcquire); PeerSet::PeerSet(const uint256& hash, int interval) : mHash(hash), mTimerInterval(interval), mTimeouts(0), mComplete(false), mFailed(false), mProgress(true), mAggressive(true), mTimer(theApp->getIOService()) { - mLastAction = time(NULL); + mLastAction = upTime(); assert((mTimerInterval > 10) && (mTimerInterval < 30000)); } @@ -890,7 +890,7 @@ void LedgerAcquireMaster::sweep() { mRecentFailures.sweep(); - time_t now = time(NULL); + int now = upTime(); boost::mutex::scoped_lock sl(mLock); std::map::iterator it = mLedgers.begin(); diff --git a/src/cpp/ripple/LedgerAcquire.h b/src/cpp/ripple/LedgerAcquire.h index 0f2c6abd26..b6d60f0f37 100644 --- a/src/cpp/ripple/LedgerAcquire.h +++ b/src/cpp/ripple/LedgerAcquire.h @@ -32,7 +32,7 @@ protected: uint256 mHash; int mTimerInterval, mTimeouts; bool mComplete, mFailed, mProgress, mAggressive; - time_t mLastAction; + int mLastAction; boost::recursive_mutex mLock; boost::asio::deadline_timer mTimer; @@ -53,8 +53,8 @@ public: bool isActive(); void progress() { mProgress = true; mAggressive = false; } bool isProgress() { return mProgress; } - void touch() { mLastAction = time(NULL); } - time_t getLastAction() { return mLastAction; } + void touch() { mLastAction = upTime(); } + int getLastAction() { return mLastAction; } void peerHas(Peer::ref); void badPeer(Peer::ref); diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index 013c7f2af6..79e7eb952e 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -17,7 +17,7 @@ int upTime() static time_t firstCall = time(NULL); if (uptimePtr != NULL) return *uptimePtr; - cLog(lsWARNING) << "slow uptime"; + cLog(lsTRACE) << "Slow uptime in use"; return static_cast(time(NULL) - firstCall); } @@ -117,7 +117,7 @@ void LoadManager::setDebitLimit(int r) mDebitLimit = r; } -void LoadManager::canonicalize(LoadSource& source, const time_t now) const +void LoadManager::canonicalize(LoadSource& source, int now) const { if (source.mLastUpdate != now) { @@ -133,9 +133,9 @@ void LoadManager::canonicalize(LoadSource& source, const time_t now) const bool LoadManager::shouldWarn(LoadSource& source) const { - time_t now = time(NULL); boost::mutex::scoped_lock sl(mLock); + int now = upTime(); canonicalize(source, now); if (source.isPrivileged() || (source.mBalance < mDebitWarn) || (source.mLastWarning == now)) return false; @@ -146,9 +146,9 @@ bool LoadManager::shouldWarn(LoadSource& source) const bool LoadManager::shouldCutoff(LoadSource& source) const { - time_t now = time(NULL); boost::mutex::scoped_lock sl(mLock); + int now = upTime(); canonicalize(source, now); return !source.isPrivileged() && (source.mBalance < mDebitLimit); } @@ -161,10 +161,10 @@ bool LoadManager::adjust(LoadSource& source, LoadType t) const bool LoadManager::adjust(LoadSource& source, int credits) const { // return: true = need to warn/cutoff - time_t now = time(NULL); boost::mutex::scoped_lock sl(mLock); // We do it this way in case we want to add exponential decay later + int now = upTime(); canonicalize(source, now); source.mBalance += credits; if (source.mBalance > mCreditLimit) diff --git a/src/cpp/ripple/LoadManager.h b/src/cpp/ripple/LoadManager.h index dea9c6c0b4..b64394298f 100644 --- a/src/cpp/ripple/LoadManager.h +++ b/src/cpp/ripple/LoadManager.h @@ -63,12 +63,12 @@ public: protected: int mBalance; int mFlags; - time_t mLastUpdate; - time_t mLastWarning; + int mLastUpdate; + int mLastWarning; public: LoadSource() : mBalance(0), mFlags(0), mLastWarning(0) - { mLastUpdate = time(NULL); } + { mLastUpdate = upTime(); } bool isPrivileged() const { return (mFlags & lsfPrivileged) != 0; } void setPrivileged() { mFlags |= lsfPrivileged; } @@ -89,11 +89,14 @@ protected: int mDebitLimit; // when a source drops below this, we cut it off (should be negative) bool mShutdown; + + int mSpace1[4]; // We want mUptime to have its own cache line int mUptime; + int mSpace2[4]; mutable boost::mutex mLock; - void canonicalize(LoadSource&, const time_t now) const; + void canonicalize(LoadSource&, int upTime) const; std::vector mCosts; diff --git a/src/cpp/ripple/LoadMonitor.cpp b/src/cpp/ripple/LoadMonitor.cpp index 312de87a72..567d08c948 100644 --- a/src/cpp/ripple/LoadMonitor.cpp +++ b/src/cpp/ripple/LoadMonitor.cpp @@ -2,7 +2,7 @@ void LoadMonitor::update() { // call with the mutex - time_t now = time(NULL); + int now = upTime(); if (now == mLastUpdate) // current return; diff --git a/src/cpp/ripple/LoadMonitor.h b/src/cpp/ripple/LoadMonitor.h index efda49b53b..18cbb228dd 100644 --- a/src/cpp/ripple/LoadMonitor.h +++ b/src/cpp/ripple/LoadMonitor.h @@ -7,6 +7,7 @@ #include #include "types.h" +extern int upTime(); // Monitors load levels and response times @@ -19,7 +20,7 @@ protected: uint64 mLatencyMSPeak; uint64 mTargetLatencyAvg; uint64 mTargetLatencyPk; - time_t mLastUpdate; + int mLastUpdate; boost::mutex mLock; void update(); @@ -27,7 +28,7 @@ protected: public: LoadMonitor() : mCounts(0), mLatencyEvents(0), mLatencyMSAvg(0), mLatencyMSPeak(0), mTargetLatencyAvg(0), mTargetLatencyPk(0) - { mLastUpdate = time(NULL); } + { mLastUpdate = upTime(); } void addCount(int counts); void addLatency(int latency); diff --git a/src/cpp/ripple/Suppression.cpp b/src/cpp/ripple/Suppression.cpp index 1bd594d40b..b168b9120f 100644 --- a/src/cpp/ripple/Suppression.cpp +++ b/src/cpp/ripple/Suppression.cpp @@ -4,6 +4,8 @@ DECLARE_INSTANCE(Suppression); +extern int upTime(); + Suppression& SuppressionTable::findCreateEntry(const uint256& index, bool& created) { boost::unordered_map::iterator fit = mSuppressionMap.find(index); @@ -15,11 +17,11 @@ Suppression& SuppressionTable::findCreateEntry(const uint256& index, bool& creat } created = true; - time_t now = time(NULL); - time_t expireTime = now - mHoldTime; + int now = upTime(); + int expireTime = now - mHoldTime; // See if any supressions need to be expired - std::map< time_t, std::list >::iterator it = mSuppressionTimes.begin(); + std::map< int, std::list >::iterator it = mSuppressionTimes.begin(); if ((it != mSuppressionTimes.end()) && (it->first <= expireTime)) { BOOST_FOREACH(const uint256& lit, it->second) diff --git a/src/cpp/ripple/Suppression.h b/src/cpp/ripple/Suppression.h index 4cd9db074f..d401a8f412 100644 --- a/src/cpp/ripple/Suppression.h +++ b/src/cpp/ripple/Suppression.h @@ -50,7 +50,7 @@ protected: boost::unordered_map mSuppressionMap; // Stores all expiration times and the hashes indexed for them - std::map< time_t, std::list > mSuppressionTimes; + std::map< int, std::list > mSuppressionTimes; int mHoldTime; diff --git a/src/cpp/ripple/TaggedCache.h b/src/cpp/ripple/TaggedCache.h index f8cb5d4992..ad6bea2d74 100644 --- a/src/cpp/ripple/TaggedCache.h +++ b/src/cpp/ripple/TaggedCache.h @@ -11,6 +11,7 @@ #include "Log.h" extern LogPartition TaggedCachePartition; +extern int upTime(); // This class implements a cache and a map. The cache keeps objects alive // in the map. The map allows multiple code paths that reference objects @@ -36,15 +37,15 @@ protected: class cache_entry { public: - time_t last_use; + int last_use; data_ptr ptr; weak_data_ptr weak_ptr; - cache_entry(time_t l, const data_ptr& d) : last_use(l), ptr(d), weak_ptr(d) { ; } + cache_entry(int l, const data_ptr& d) : last_use(l), ptr(d), weak_ptr(d) { ; } bool isCached() { return !!ptr; } bool isExpired() { return weak_ptr.expired(); } data_ptr lock() { return weak_ptr.lock(); } - void touch() { last_use = time(NULL); } + void touch() { last_use = upTime(); } }; typedef std::pair cache_pair; @@ -59,11 +60,11 @@ protected: int mCacheCount; // Number of items cached cache_type mCache; // Hold strong reference to recent objects - time_t mLastSweep; + int mLastSweep; public: TaggedCache(const char *name, int size, int age) - : mName(name), mTargetSize(size), mTargetAge(age), mCacheCount(0), mLastSweep(time(NULL)) { ; } + : mName(name), mTargetSize(size), mTargetAge(age), mCacheCount(0), mLastSweep(upTime()) { ; } int getTargetSize() const; int getTargetAge() const; @@ -128,8 +129,8 @@ template void TaggedCache::sweep { boost::recursive_mutex::scoped_lock sl(mLock); - time_t mLastSweep = time(NULL); - time_t target = mLastSweep - mTargetAge; + int mLastSweep = upTime(); + int target = mLastSweep - mTargetAge; int cacheRemovals = 0, mapRemovals = 0, cc = 0; if ((mTargetSize != 0) && (mCache.size() > mTargetSize)) @@ -243,7 +244,7 @@ bool TaggedCache::canonicalize(const key_type& key, boost::shared cache_iterator cit = mCache.find(key); if (cit == mCache.end()) { - mCache.insert(cache_pair(key, cache_entry(time(NULL), data))); + mCache.insert(cache_pair(key, cache_entry(upTime(), data))); ++mCacheCount; return false; } From 4f400420902acb0e175294a2114c5780006e1f27 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 6 Feb 2013 02:20:54 -0800 Subject: [PATCH 07/10] Remove an extraneous cast. --- src/cpp/ripple/NetworkOPs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index 4816d3622a..a8b6d01cd1 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1178,7 +1178,7 @@ Json::Value NetworkOPs::getServerInfo(bool human, bool admin) } else { - l["base_fee_xrp"] = static_cast(Json::UInt(baseFee)) / SYSTEM_CURRENCY_PARTS; + l["base_fee_xrp"] = static_cast(baseFee) / SYSTEM_CURRENCY_PARTS; l["reserve_base_xrp"] = static_cast(Json::UInt(lpClosed->getReserve(0) * baseFee / baseRef)) / SYSTEM_CURRENCY_PARTS; l["reserve_inc_xrp"] = From 4b2672e115b54bf5d34bb2429f7d8f788feee516 Mon Sep 17 00:00:00 2001 From: jed Date: Wed, 6 Feb 2013 11:26:55 -0800 Subject: [PATCH 08/10] . --- src/cpp/ripple/OrderBookDB.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/ripple/OrderBookDB.cpp b/src/cpp/ripple/OrderBookDB.cpp index f878d4c8f3..101cf3c3ad 100644 --- a/src/cpp/ripple/OrderBookDB.cpp +++ b/src/cpp/ripple/OrderBookDB.cpp @@ -185,11 +185,11 @@ void OrderBookDB::processTxn(const SerializedTransaction& stTxn, TER terResult,T const STObject* previous = dynamic_cast(node.peekAtPField(*field)); if(previous) { - STAmount& takerGets = previous->getFieldAmount(sfTakerGets); + STAmount takerGets = previous->getFieldAmount(sfTakerGets); uint160 currencyOut=takerGets.getCurrency(); uint160 issuerOut=takerGets.getIssuer(); - STAmount& takerPays = previous->getFieldAmount(sfTakerPays); + STAmount takerPays = previous->getFieldAmount(sfTakerPays); uint160 currencyIn=takerPays.getCurrency(); uint160 issuerIn=takerPays.getIssuer(); From c4cbc509d3ea03153881e8ddf62cc6e1c5283a2b Mon Sep 17 00:00:00 2001 From: jed Date: Wed, 6 Feb 2013 11:39:47 -0800 Subject: [PATCH 09/10] didn't mean to check that in --- test/send-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/send-test.js b/test/send-test.js index d9d6c91761..b21cba3a38 100644 --- a/test/send-test.js +++ b/test/send-test.js @@ -39,8 +39,8 @@ buster.testCase("Fee Changes", { */ buster.testCase("Sending", { - //'setUp' : testutils.build_setup(), - 'setUp' : testutils.build_setup({verbose: true , no_server: true}), + 'setUp' : testutils.build_setup(), + //'setUp' : testutils.build_setup({verbose: true , no_server: true}), 'tearDown' : testutils.build_teardown(), "send XRP to non-existent account with insufficent fee" : @@ -974,7 +974,7 @@ buster.testCase("Indirect ripple", { }); }, - "=> indirect ripple with path" : + "indirect ripple with path" : function (done) { var self = this; From 9cd5b82b933b11484a9f0d51a35ba17b85356ec3 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 6 Feb 2013 14:09:54 -0800 Subject: [PATCH 10/10] Remove unhelpful log entry. --- src/cpp/ripple/LoadManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index 79e7eb952e..dd78cd3731 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -17,7 +17,6 @@ int upTime() static time_t firstCall = time(NULL); if (uptimePtr != NULL) return *uptimePtr; - cLog(lsTRACE) << "Slow uptime in use"; return static_cast(time(NULL) - firstCall); }