Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
Arthur Britto
2013-02-22 01:25:36 -08:00
33 changed files with 416 additions and 160 deletions

View File

@@ -24,20 +24,18 @@ void AccountItems::fillItems(const uint160& accountID, Ledger::ref ledger)
uint256 rootIndex = Ledger::getOwnerDirIndex(accountID);
uint256 currentIndex = rootIndex;
LedgerStateParms lspNode = lepNONE;
while (1)
{
SLE::pointer ownerDir = ledger->getDirNode(lspNode, currentIndex);
SLE::pointer ownerDir = ledger->getDirNode(currentIndex);
if (!ownerDir) return;
STVector256 svOwnerNodes = ownerDir->getFieldV256(sfIndexes);
BOOST_FOREACH(uint256& uNode, svOwnerNodes.peekValue())
{
SLE::pointer sleCur = ledger->getSLE(uNode);
SLE::pointer sleCur = ledger->getSLEi(uNode);
AccountItem::pointer item=mOfType->makeItem(accountID, sleCur);
AccountItem::pointer item = mOfType->makeItem(accountID, sleCur);
if(item)
{
mItems.push_back(item);

View File

@@ -41,7 +41,7 @@ DatabaseCon::~DatabaseCon()
Application::Application() :
mIOWork(mIOService), mAuxWork(mAuxService), mUNL(mIOService), mNetOps(mIOService, &mLedgerMaster),
mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300),
mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300), mSLECache("LedgerEntryCache", 4096, 120),
mSNTPClient(mAuxService), mRPCHandler(&mNetOps), mFeeTrack(),
mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL),
@@ -301,6 +301,7 @@ void Application::sweep()
mTempNodeCache.sweep();
mValidations.sweep();
getMasterLedgerAcquire().sweep();
mSLECache.sweep();
mSweepTimer.expires_from_now(boost::posix_time::seconds(theConfig.getSize(siSweepInterval)));
mSweepTimer.async_wait(boost::bind(&Application::sweep, this));
}

View File

@@ -29,6 +29,7 @@
class RPCDoor;
class PeerDoor;
typedef TaggedCache< uint256, std::vector<unsigned char> > NodeCache;
typedef TaggedCache< uint256, SLE > SLECache;
class DatabaseCon
{
@@ -60,6 +61,7 @@ class Application
ValidationCollection mValidations;
SuppressionTable mSuppressions;
HashedObjectStore mHashedObjectStore;
SLECache mSLECache;
SNTPClient mSNTPClient;
JobQueue mJobQueue;
RPCHandler mRPCHandler;
@@ -118,6 +120,7 @@ public:
TXQueue& getTxnQueue() { return mTxnQueue; }
PeerDoor& getPeerDoor() { return *mPeerDoor; }
OrderBookDB& getOrderBookDB() { return mOrderBookDB; }
SLECache& getSLECache() { return mSLECache; }
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }

View File

@@ -483,7 +483,7 @@ int Config::getSize(SizedItemName item)
{
SizedItem sizeTable[] = {
{ siSweepInterval, { 10, 30, 60, 90, 90 } },
{ siLedgerFetch, { 2, 4, 5, 6, 6 } },
{ siLedgerFetch, { 2, 2, 3, 4, 5 } },
{ siValidationsSize, { 256, 256, 512, 1024, 1024 } },
{ siValidationsAge, { 500, 500, 500, 500, 500 } },
{ siNodeCacheSize, { 8192, 32768, 131072, 1048576, 0 } },

View File

@@ -98,7 +98,7 @@ bool ConnectionPool::savePeer(const std::string& strIp, int iPort, char code)
Peer::pointer ConnectionPool::getPeerById(const uint64& id)
{
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
const boost::unordered_map<uint64, Peer::pointer>::iterator& it = mPeerIdMap.find(id);
if (it == mPeerIdMap.end())
return Peer::pointer();
@@ -107,7 +107,7 @@ Peer::pointer ConnectionPool::getPeerById(const uint64& id)
bool ConnectionPool::hasPeer(const uint64& id)
{
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
return mPeerIdMap.find(id) != mPeerIdMap.end();
}
@@ -122,7 +122,7 @@ bool ConnectionPool::peerAvailable(std::string& strIp, int& iPort)
// Convert mIpMap (list of open connections) to a vector of "<ip> <port>".
{
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
vstrIpPort.reserve(mIpMap.size());
@@ -235,7 +235,7 @@ void ConnectionPool::policyHandler(const boost::system::error_code& ecResult)
int ConnectionPool::relayMessage(Peer* fromPeer, const PackedMessage::pointer& msg)
{
int sentTo = 0;
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
BOOST_FOREACH(const vtConMap& pair, mConnectedMap)
{
@@ -254,7 +254,7 @@ int ConnectionPool::relayMessage(Peer* fromPeer, const PackedMessage::pointer& m
void ConnectionPool::relayMessageBut(const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
{ // Relay message to all but the specified peers
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
BOOST_FOREACH(const vtConMap& pair, mConnectedMap)
{
@@ -267,7 +267,7 @@ void ConnectionPool::relayMessageBut(const std::set<uint64>& fromPeers, const Pa
void ConnectionPool::relayMessageTo(const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
{ // Relay message to the specified peers
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
BOOST_FOREACH(const uint64& peerID, fromPeers)
{
@@ -305,34 +305,22 @@ Peer::pointer ConnectionPool::peerConnect(const std::string& strIp, int iPort)
ipPort pipPeer = make_pair(strIp, iPort);
Peer::pointer ppResult;
boost::unordered_map<ipPort, Peer::pointer>::iterator it;
{
boost::mutex::scoped_lock sl(mPeerLock);
if ((it = mIpMap.find(pipPeer)) == mIpMap.end())
boost::recursive_mutex::scoped_lock sl(mPeerLock);
if (mIpMap.find(pipPeer) == mIpMap.end())
{
Peer::pointer ppNew(Peer::create(theApp->getIOService(), theApp->getPeerDoor().getSSLContext(),
++mLastPeer, false));
ppResult = Peer::create(theApp->getIOService(), theApp->getPeerDoor().getSSLContext(),
++mLastPeer, false);
// Did not find it. Not already connecting or connected.
ppNew->connect(strIp, iPort);
mIpMap[pipPeer] = ppNew;
ppResult = ppNew;
mIpMap[pipPeer] = ppResult;
// ++miConnectStarting;
}
else
{
// Found it. Already connected.
nothing();
}
}
if (ppResult)
{
ppResult->connect(strIp, iPort);
//cLog(lsINFO) << "Pool: Connecting: " << ADDRESS_SHARED(ppResult) << ": " << strIp << " " << iPort;
}
else
@@ -359,7 +347,7 @@ Json::Value ConnectionPool::getPeersJson()
int ConnectionPool::getPeerCount()
{
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
return mConnectedMap.size();
}
@@ -368,7 +356,7 @@ std::vector<Peer::pointer> ConnectionPool::getPeerVector()
{
std::vector<Peer::pointer> ret;
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
ret.reserve(mConnectedMap.size());
@@ -383,7 +371,7 @@ std::vector<Peer::pointer> ConnectionPool::getPeerVector()
uint64 ConnectionPool::assignPeerId()
{
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
return ++mLastPeer;
}
@@ -402,7 +390,7 @@ bool ConnectionPool::peerConnected(Peer::ref peer, const RippleAddress& naPeer,
}
else
{
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
const boost::unordered_map<RippleAddress, Peer::pointer>::iterator& itCm = mConnectedMap.find(naPeer);
if (itCm == mConnectedMap.end())
@@ -453,7 +441,7 @@ bool ConnectionPool::peerConnected(Peer::ref peer, const RippleAddress& naPeer,
// We maintain a map of public key to peer for connected and verified peers. Maintain it.
void ConnectionPool::peerDisconnected(Peer::ref peer, const RippleAddress& naPeer)
{
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
if (naPeer.isValid())
{
@@ -556,7 +544,7 @@ void ConnectionPool::peerClosed(Peer::ref peer, const std::string& strIp, int iP
// Determine if closed peer was redundant.
bool bRedundant = true;
{
boost::mutex::scoped_lock sl(mPeerLock);
boost::recursive_mutex::scoped_lock sl(mPeerLock);
const boost::unordered_map<ipPort, Peer::pointer>::iterator& itIp = mIpMap.find(ipPeer);
if (itIp == mIpMap.end())

View File

@@ -16,8 +16,8 @@
class ConnectionPool
{
private:
boost::mutex mPeerLock;
uint64 mLastPeer;
boost::recursive_mutex mPeerLock;
uint64 mLastPeer;
typedef std::pair<RippleAddress, Peer::pointer> naPeer;
typedef std::pair<ipPort, Peer::pointer> pipPeer;

View File

@@ -23,7 +23,7 @@ JobQueue::JobQueue() : mLastJob(0), mThreadCount(0), mShuttingDown(false)
mJobLoads[jtTRANSACTION_l].setTargetLatency(100, 500);
mJobLoads[jtPROPOSAL_t].setTargetLatency(100, 500);
mJobLoads[jtCLIENT].setTargetLatency(250, 1000);
mJobLoads[jtCLIENT].setTargetLatency(2000, 5000);
mJobLoads[jtPEER].setTargetLatency(200, 1250);
mJobLoads[jtDISK].setTargetLatency(500, 1000);
mJobLoads[jtRPC].setTargetLatency(250, 750);

View File

@@ -200,8 +200,8 @@ AccountState::pointer Ledger::getAccountState(const RippleAddress& accountID)
// std::cerr << "Ledger:getAccountState(" << accountID.humanAccountID() << ")" << std::endl;
#endif
SHAMapItem::pointer item = mAccountStateMap->peekItem(Ledger::getAccountRootIndex(accountID));
if (!item)
SLE::pointer sle = getSLEi(Ledger::getAccountRootIndex(accountID));
if (!sle)
{
cLog(lsDEBUG) << boost::str(boost::format("Ledger:getAccountState: not found: %s: %s")
% accountID.humanAccountID()
@@ -210,8 +210,6 @@ AccountState::pointer Ledger::getAccountState(const RippleAddress& accountID)
return AccountState::pointer();
}
SerializedLedgerEntry::pointer sle =
boost::make_shared<SerializedLedgerEntry>(item->peekSerializer(), item->getTag());
if (sle->getType() != ltACCOUNT_ROOT)
return AccountState::pointer();
@@ -395,7 +393,7 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
static boost::format transExists("SELECT Status FROM Transactions WHERE TransID = '%s';");
static boost::format
updateTx("UPDATE Transactions SET LedgerSeq = %d, Status = '%c', TxnMeta = %s WHERE TransID = '%s';");
static boost::format addLedger("INSERT INTO Ledgers "
static boost::format addLedger("INSERT OR REPLACE INTO Ledgers "
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags,"
"AccountSetHash,TransSetHash) VALUES ('%s','%u','%s','%s','%u','%u','%d','%u','%s','%s');");
@@ -819,6 +817,7 @@ Json::Value Ledger::getJson(int options)
{
Json::Value txns(Json::arrayValue);
SHAMapTreeNode::TNType type;
ScopedLock l(mTransactionMap->Lock());
for (SHAMapItem::pointer item = mTransactionMap->peekFirstItem(type); !!item;
item = mTransactionMap->peekNextItem(item->getTag(), type))
{
@@ -858,6 +857,7 @@ Json::Value Ledger::getJson(int options)
if (mAccountStateMap && (bFull || ((options & LEDGER_JSON_DUMP_STATE) != 0)))
{
Json::Value state(Json::arrayValue);
ScopedLock l(mAccountStateMap->Lock());
for (SHAMapItem::pointer item = mAccountStateMap->peekFirstItem(); !!item;
item = mAccountStateMap->peekNextItem(item->getTag()))
{
@@ -954,6 +954,26 @@ SLE::pointer Ledger::getSLE(const uint256& uHash)
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
}
SLE::pointer Ledger::getSLEi(const uint256& uId)
{
uint256 hash;
ScopedLock sl(mAccountStateMap->Lock());
SHAMapItem::pointer node = mAccountStateMap->peekItem(uId, hash);
if (!node)
return SLE::pointer();
SLE::pointer ret = theApp->getSLECache().fetch(hash);
if (!ret)
{
ret = boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
ret->setImmutable();
theApp->getSLECache().canonicalize(hash, ret);
}
return ret;
}
uint256 Ledger::getFirstLedgerIndex()
{
SHAMapItem::pointer node = mAccountStateMap->peekFirstItem();
@@ -994,6 +1014,14 @@ uint256 Ledger::getPrevLedgerIndex(const uint256& uHash, const uint256& uBegin)
return node->getTag();
}
SLE::pointer Ledger::getASNodeI(const uint256& nodeID, LedgerEntryType let)
{
SLE::pointer node = getSLEi(nodeID);
if (node && (node->getType() != let))
node.reset();
return node;
}
SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID,
LedgerEntryType let )
{
@@ -1030,43 +1058,39 @@ SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID,
SLE::pointer Ledger::getAccountRoot(const uint160& accountID)
{
LedgerStateParms qry = lepNONE;
return getASNode(qry, getAccountRootIndex(accountID), ltACCOUNT_ROOT);
return getASNodeI(getAccountRootIndex(accountID), ltACCOUNT_ROOT);
}
SLE::pointer Ledger::getAccountRoot(const RippleAddress& naAccountID)
{
LedgerStateParms qry = lepNONE;
return getASNode(qry, getAccountRootIndex(naAccountID.getAccountID()), ltACCOUNT_ROOT);
return getASNodeI(getAccountRootIndex(naAccountID.getAccountID()), ltACCOUNT_ROOT);
}
//
// Directory
//
SLE::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex)
SLE::pointer Ledger::getDirNode(const uint256& uNodeIndex)
{
return getASNode(parms, uNodeIndex, ltDIR_NODE);
return getASNodeI(uNodeIndex, ltDIR_NODE);
}
//
// Generator Map
//
SLE::pointer Ledger::getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID)
SLE::pointer Ledger::getGenerator(const uint160& uGeneratorID)
{
return getASNode(parms, getGeneratorIndex(uGeneratorID), ltGENERATOR_MAP);
return getASNodeI(getGeneratorIndex(uGeneratorID), ltGENERATOR_MAP);
}
//
// Nickname
//
SLE::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& uNickname)
SLE::pointer Ledger::getNickname(const uint256& uNickname)
{
return getASNode(parms, uNickname, ltNICKNAME);
return getASNodeI(uNickname, ltNICKNAME);
}
//
@@ -1074,18 +1098,18 @@ SLE::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& uNickna
//
SLE::pointer Ledger::getOffer(LedgerStateParms& parms, const uint256& uIndex)
SLE::pointer Ledger::getOffer(const uint256& uIndex)
{
return getASNode(parms, uIndex, ltOFFER);
return getASNodeI(uIndex, ltOFFER);
}
//
// Ripple State
//
SLE::pointer Ledger::getRippleState(LedgerStateParms& parms, const uint256& uNode)
SLE::pointer Ledger::getRippleState(const uint256& uNode)
{
return getASNode(parms, uNode, ltRIPPLE_STATE);
return getASNodeI(uNode, ltRIPPLE_STATE);
}
// For an entry put in the 64 bit index or quality.
@@ -1179,7 +1203,7 @@ uint256 Ledger::getLedgerHash(uint32 ledgerIndex)
int diff = mLedgerSeq - ledgerIndex;
if (diff <= 256)
{
SLE::pointer hashIndex = getSLE(getLedgerHashIndex());
SLE::pointer hashIndex = getSLEi(getLedgerHashIndex());
if (hashIndex)
{
assert(hashIndex->getFieldU32(sfLastLedgerSequence) == (mLedgerSeq - 1));
@@ -1199,7 +1223,7 @@ uint256 Ledger::getLedgerHash(uint32 ledgerIndex)
}
// in skiplist
SLE::pointer hashIndex = getSLE(getLedgerHashIndex(ledgerIndex));
SLE::pointer hashIndex = getSLEi(getLedgerHashIndex(ledgerIndex));
if (hashIndex)
{
int lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence);
@@ -1219,7 +1243,7 @@ uint256 Ledger::getLedgerHash(uint32 ledgerIndex)
std::vector< std::pair<uint32, uint256> > Ledger::getLedgerHashes()
{
std::vector< std::pair<uint32, uint256> > ret;
SLE::pointer hashIndex = getSLE(getLedgerHashIndex());
SLE::pointer hashIndex = getSLEi(getLedgerHashIndex());
if (hashIndex)
{
STVector256 vec = hashIndex->getFieldV256(sfHashes);

View File

@@ -97,6 +97,9 @@ private:
protected:
SLE::pointer getASNode(LedgerStateParms& parms, const uint256& nodeID, LedgerEntryType let);
// returned SLE is immutable
SLE::pointer getASNodeI(const uint256& nodeID, LedgerEntryType let);
static void incPendingSaves();
static void decPendingSaves();
void saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer);
@@ -201,7 +204,8 @@ public:
void pendSave(bool fromConsensus);
// next/prev function
SLE::pointer getSLE(const uint256& uHash);
SLE::pointer getSLE(const uint256& uHash); // SLE is mutable
SLE::pointer getSLEi(const uint256& uHash); // SLE is immutable
uint256 getFirstLedgerIndex();
uint256 getLastLedgerIndex();
uint256 getNextLedgerIndex(const uint256& uHash); // first node >hash
@@ -230,7 +234,7 @@ public:
// Generator Map functions
//
SLE::pointer getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID);
SLE::pointer getGenerator(const uint160& uGeneratorID);
static uint256 getGeneratorIndex(const uint160& uGeneratorID);
@@ -245,9 +249,8 @@ public:
NicknameState::pointer getNicknameState(const std::string& strNickname)
{ return getNicknameState(getNicknameHash(strNickname)); }
SLE::pointer getNickname(LedgerStateParms& parms, const uint256& uNickname);
SLE::pointer getNickname(LedgerStateParms& parms, const std::string& strNickname)
{ return getNickname(parms, getNicknameHash(strNickname)); }
SLE::pointer getNickname(const uint256& uNickname);
SLE::pointer getNickname(const std::string& strNickname) { return getNickname(getNicknameHash(strNickname)); }
static uint256 getNicknameIndex(const uint256& uNickname);
@@ -263,16 +266,10 @@ public:
// Offer functions
//
SLE::pointer getOffer(LedgerStateParms& parms, const uint256& uIndex);
SLE::pointer getOffer(const uint256& uIndex);
SLE::pointer getOffer(const uint256& uIndex)
{
LedgerStateParms qry = lepNONE;
return getOffer(qry, uIndex);
}
SLE::pointer getOffer(LedgerStateParms& parms, const uint160& uAccountID, uint32 uSequence)
{ return getOffer(parms, getOfferIndex(uAccountID, uSequence)); }
SLE::pointer getOffer(const uint160& uAccountID, uint32 uSequence)
{ return getOffer(getOfferIndex(uAccountID, uSequence)); }
// The index of an offer.
static uint256 getOfferIndex(const uint160& uAccountID, uint32 uSequence);
@@ -293,7 +290,7 @@ public:
static void ownerDirDescriber(SLE::ref, const uint160& owner);
// Return a node: root or normal
SLE::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex);
SLE::pointer getDirNode(const uint256& uNodeIndex);
//
// Quality
@@ -316,13 +313,7 @@ public:
static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency)
{ return getRippleStateIndex(RippleAddress::createAccountID(uiA), RippleAddress::createAccountID(uiB), uCurrency); }
SLE::pointer getRippleState(LedgerStateParms& parms, const uint256& uNode);
SLE::pointer getRippleState(const uint256& uNode)
{
LedgerStateParms qry = lepNONE;
return getRippleState(qry, uNode);
}
SLE::pointer getRippleState(const uint256& uNode);
SLE::pointer getRippleState(const RippleAddress& naA, const RippleAddress& naB, const uint160& uCurrency)
{ return getRippleState(getRippleStateIndex(naA, naB, uCurrency)); }

View File

@@ -71,6 +71,8 @@ void PeerSet::TimerEntry(boost::weak_ptr<PeerSet> wptr, const boost::system::err
{
if (result == boost::asio::error::operation_aborted)
return;
ScopedLock sl(theApp->getMasterLock());
boost::shared_ptr<PeerSet> ptr = wptr.lock();
if (ptr)
ptr->invokeOnTimer();
@@ -920,15 +922,21 @@ void LedgerAcquireMaster::sweep()
}
}
int LedgerAcquireMaster::getFetchCount()
int LedgerAcquireMaster::getFetchCount(int& timeoutCount)
{
timeoutCount = 0;
int ret = 0;
{
typedef std::pair<uint256, LedgerAcquire::pointer> u256_acq_pair;
boost::mutex::scoped_lock sl(mLock);
BOOST_FOREACH(const u256_acq_pair& it, mLedgers)
{
if (it.second->isActive())
{
++ret;
timeoutCount += it.second->getTimeouts();
}
}
}
return ret;
}

View File

@@ -149,7 +149,7 @@ public:
void dropLedger(const uint256& ledgerHash);
SMAddNode gotLedgerData(ripple::TMLedgerData& packet, Peer::ref);
int getFetchCount();
int getFetchCount(int& timeoutCount);
void logFailure(const uint256& h) { mRecentFailures.add(h); }
bool isFailure(const uint256& h) { return mRecentFailures.isPresent(h, false); }

View File

@@ -107,6 +107,7 @@ LedgerEntryAction LedgerEntrySet::hasEntry(const uint256& index) const
void LedgerEntrySet::entryCache(SLE::ref sle)
{
assert(sle->isMutable());
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
if (it == mEntries.end())
{
@@ -128,6 +129,7 @@ void LedgerEntrySet::entryCache(SLE::ref sle)
void LedgerEntrySet::entryCreate(SLE::ref sle)
{
assert(sle->isMutable());
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
if (it == mEntries.end())
{
@@ -161,6 +163,7 @@ void LedgerEntrySet::entryCreate(SLE::ref sle)
void LedgerEntrySet::entryModify(SLE::ref sle)
{
assert(sle->isMutable());
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
if (it == mEntries.end())
{
@@ -193,6 +196,7 @@ void LedgerEntrySet::entryModify(SLE::ref sle)
void LedgerEntrySet::entryDelete(SLE::ref sle)
{
assert(sle->isMutable());
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
if (it == mEntries.end())
{
@@ -399,7 +403,7 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result, uint32 index)
if (type == &sfGeneric)
continue;
SLE::pointer origNode = mLedger->getSLE(it.first);
SLE::pointer origNode = mLedger->getSLEi(it.first);
SLE::pointer curNode = it.second.mEntry;
if ((type == &sfModifiedNode) && (*curNode == *origNode))

View File

@@ -180,7 +180,10 @@ bool LedgerMaster::acquireMissingLedger(Ledger::ref origLedger, const uint256& l
}
if (theApp->getMasterLedgerAcquire().isFailure(ledgerHash))
{
cLog(lsTRACE) << "Already failed to acquire " << ledgerSeq;
return false;
}
mMissingLedger = theApp->getMasterLedgerAcquire().findCreate(ledgerHash);
if (mMissingLedger->isComplete())
@@ -203,20 +206,28 @@ bool LedgerMaster::acquireMissingLedger(Ledger::ref origLedger, const uint256& l
theApp->getIOService().post(boost::bind(&LedgerMaster::missingAcquireComplete, this, mMissingLedger));
}
int fetch = theConfig.getSize(siLedgerFetch);
if (theApp->getMasterLedgerAcquire().getFetchCount() < fetch)
{
int count = 0;
typedef std::pair<uint32, uint256> u_pair;
int fetchMax = theConfig.getSize(siLedgerFetch);
int timeoutCount;
int fetchCount = theApp->getMasterLedgerAcquire().getFetchCount(timeoutCount);
std::vector<u_pair> vec = origLedger->getLedgerHashes();
BOOST_REVERSE_FOREACH(const u_pair& it, vec)
if (fetchCount < fetchMax)
{
if (timeoutCount > 2)
{
if ((count < fetch) && (it.first < ledgerSeq) &&
!mCompleteLedgers.hasValue(it.first) && !theApp->getMasterLedgerAcquire().find(it.second))
cLog(lsDEBUG) << "Not acquiring due to timeouts";
}
else
{
typedef std::pair<uint32, uint256> u_pair;
std::vector<u_pair> vec = origLedger->getLedgerHashes();
BOOST_REVERSE_FOREACH(const u_pair& it, vec)
{
++count;
theApp->getMasterLedgerAcquire().findCreate(it.second);
if ((fetchCount < fetchMax) && (it.first < ledgerSeq) &&
!mCompleteLedgers.hasValue(it.first) && !theApp->getMasterLedgerAcquire().find(it.second))
{
++fetchCount;
theApp->getMasterLedgerAcquire().findCreate(it.second);
}
}
}
}
@@ -249,7 +260,7 @@ bool LedgerMaster::shouldAcquire(uint32 currentLedger, uint32 ledgerHistory, uin
if (candidateLedger >= currentLedger)
ret = true;
else ret = (currentLedger - candidateLedger) <= ledgerHistory;
cLog(lsTRACE) << "Missing ledger " << candidateLedger << (ret ? " will" : " will NOT") << " be acquired";
cLog(lsTRACE) << "Missing ledger " << candidateLedger << (ret ? " should" : " should NOT") << " be acquired";
return ret;
}
@@ -362,7 +373,10 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
if (!mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1))
{
if (!shouldAcquire(mCurrentLedger->getLedgerSeq(), theConfig.LEDGER_HISTORY, ledger->getLedgerSeq() - 1))
{
cLog(lsTRACE) << "Don't need any ledgers";
return;
}
cLog(lsDEBUG) << "We need the ledger before the ledger we just accepted: " << ledger->getLedgerSeq() - 1;
acquireMissingLedger(ledger, ledger->getParentHash(), ledger->getLedgerSeq() - 1);
}
@@ -387,6 +401,8 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
cLog(lsWARNING) << "We have a gap we can't fix: " << prevMissing + 1;
}
}
else
cLog(lsTRACE) << "Shouldn't acquire";
}
}

View File

@@ -266,7 +266,7 @@ bool LoadFeeTrack::lowerLocalFee()
boost::mutex::scoped_lock sl(mLock);
uint32 origFee = mLocalTxnLoadFee;
mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/16th
mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/4
if (mLocalTxnLoadFee < lftNormalFee)
mLocalTxnLoadFee = lftNormalFee;

View File

@@ -134,7 +134,7 @@ protected:
static const int lftNormalFee = 256; // 256 is the minimum/normal load factor
static const int lftFeeIncFraction = 16; // increase fee by 1/16
static const int lftFeeDecFraction = 16; // decrease fee by 1/16
static const int lftFeeDecFraction = 4; // decrease fee by 1/4
static const int lftFeeMax = lftNormalFee * 1000000;
uint32 mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee

View File

@@ -455,12 +455,9 @@ AccountState::pointer NetworkOPs::getAccountState(Ledger::ref lrLedger, const Ri
SLE::pointer NetworkOPs::getGenerator(Ledger::ref lrLedger, const uint160& uGeneratorID)
{
LedgerStateParms qry = lepNONE;
if (!lrLedger)
return SLE::pointer();
else
return lrLedger->getGenerator(qry, uGeneratorID);
return lrLedger->getGenerator(uGeneratorID);
}
//
@@ -475,8 +472,7 @@ STVector256 NetworkOPs::getDirNodeInfo(
uint64& uNodeNext)
{
STVector256 svIndexes;
LedgerStateParms lspNode = lepNONE;
SLE::pointer sleNode = lrLedger->getDirNode(lspNode, uNodeIndex);
SLE::pointer sleNode = lrLedger->getDirNode(uNodeIndex);
if (sleNode)
{
@@ -524,8 +520,7 @@ Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const RippleAddre
uint256 uRootIndex = lpLedger->getOwnerDirIndex(naAccount.getAccountID());
LedgerStateParms lspNode = lepNONE;
SLE::pointer sleNode = lpLedger->getDirNode(lspNode, uRootIndex);
SLE::pointer sleNode = lpLedger->getDirNode(uRootIndex);
if (sleNode)
{
@@ -538,7 +533,7 @@ Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const RippleAddre
BOOST_FOREACH(const uint256& uDirEntry, vuiIndexes)
{
SLE::pointer sleCur = lpLedger->getSLE(uDirEntry);
SLE::pointer sleCur = lpLedger->getSLEi(uDirEntry);
switch (sleCur->getType())
{
@@ -569,9 +564,7 @@ Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const RippleAddre
uNodeDir = sleNode->getFieldU64(sfIndexNext);
if (uNodeDir)
{
lspNode = lepNONE;
sleNode = lpLedger->getDirNode(lspNode, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
sleNode = lpLedger->getDirNode(Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
assert(sleNode);
}
} while (uNodeDir);
@@ -1070,7 +1063,7 @@ std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
std::string sql =
str(boost::format("SELECT LedgerSeq,Status,RawTxn,TxnMeta FROM Transactions where TransID in (SELECT TransID from AccountTransactions "
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' LIMIT 1000) ORDER BY LedgerSeq;")
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' LIMIT 200) ORDER BY LedgerSeq DESC;")
% account.humanAccountID() % maxLedger % minLedger);
{
@@ -1092,7 +1085,7 @@ std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
}else rawMeta.resize(metaSize);
TransactionMetaSet::pointer meta= boost::make_shared<TransactionMetaSet>(txn->getID(), txn->getLedger(), rawMeta.getData());
ret.push_back(std::pair<Transaction::ref, TransactionMetaSet::ref>(txn,meta));
ret.push_back(std::pair<Transaction::pointer, TransactionMetaSet::pointer>(txn,meta));
}
}
@@ -1212,7 +1205,16 @@ Json::Value NetworkOPs::getServerInfo(bool human, bool admin)
static_cast<double>(Json::UInt(lpClosed->getReserve(0) * baseFee / baseRef)) / SYSTEM_CURRENCY_PARTS;
l["reserve_inc_xrp"] =
static_cast<double>(Json::UInt(lpClosed->getReserveInc() * baseFee / baseRef)) / SYSTEM_CURRENCY_PARTS;
l["age"] = Json::UInt(getCloseTimeNC() - lpClosed->getCloseTimeNC());
uint32 closeTime = getCloseTimeNC();
uint32 lCloseTime = lpClosed->getCloseTimeNC();
if (lCloseTime <= closeTime)
{
uint32 age = closeTime - lCloseTime;
if (age < 1000000)
l["age"] = Json::UInt(age);
}
}
info["closed_ledger"] = l;
}

View File

@@ -165,6 +165,7 @@ public:
void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; }
SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); }
SLE::pointer getSLEi(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLEi(uHash); }
//
// Transaction operations

View File

@@ -39,7 +39,7 @@ void OrderBookDB::setup(Ledger::ref ledger)
while (currentIndex.isNonZero())
{
SLE::pointer entry=ledger->getSLE(currentIndex);
SLE::pointer entry=ledger->getSLEi(currentIndex);
OrderBook::pointer book = OrderBook::newOrderBook(entry);
if (book)

View File

@@ -24,11 +24,14 @@ DECLARE_INSTANCE(Peer);
// Node has this long to verify its identity from connection accepted or connection attempt.
#define NODE_VERIFY_SECONDS 15
// Idle nodes are probed this often
#define NODE_IDLE_SECONDS 120
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx, uint64 peerID, bool inbound) :
mInbound(inbound),
mHelloed(false),
mDetaching(false),
mActive(true),
mActive(2),
mCluster(false),
mPeerId(peerID),
mSocketSsl(io_service, ctx),
@@ -123,6 +126,33 @@ void Peer::detach(const char *rsn)
}
}
void Peer::handlePingTimer(const boost::system::error_code& ecResult)
{
if (ecResult || mDetaching)
return;
if (mActive == 1)
{ // ping out
detach("pto");
return;
}
if (mActive == 0)
{ // idle->pingsent
mActive = 1;
ripple::TMPing packet;
packet.set_type(ripple::TMPing::ptPING);
sendPacket(boost::make_shared<PackedMessage>(packet, ripple::mtPING));
}
else // active->idle
mActive = 0;
mActivityTimer.expires_from_now(boost::posix_time::seconds(NODE_IDLE_SECONDS));
mActivityTimer.async_wait(boost::bind(&Peer::handlePingTimer, shared_from_this(),
boost::asio::placeholders::error));
}
void Peer::handleVerifyTimer(const boost::system::error_code& ecResult)
{
if (ecResult == boost::asio::error::operation_aborted)
@@ -631,8 +661,10 @@ void Peer::recvHello(ripple::TMHello& packet)
{
bool bDetach = true;
// Cancel verification timeout. - FIXME Start ping/pong timer
(void) mActivityTimer.cancel();
mActivityTimer.expires_from_now(boost::posix_time::seconds(NODE_IDLE_SECONDS));
mActivityTimer.async_wait(boost::bind(&Peer::handlePingTimer, shared_from_this(),
boost::asio::placeholders::error));
uint32 ourTime = theApp->getOPs().getNetworkTimeNC();
uint32 minTime = ourTime - 20;
@@ -1197,7 +1229,7 @@ void Peer::recvPing(ripple::TMPing& packet)
}
else if (packet.type() == ripple::TMPing::ptPONG)
{
mActive = true;
mActive = 2;
}
}

View File

@@ -37,7 +37,7 @@ private:
bool mClientConnect; // In process of connecting as client.
bool mHelloed; // True, if hello accepted.
bool mDetaching; // True, if detaching.
bool mActive;
int mActive; // 0=idle, 1=pingsent, 2=active
bool mCluster; // Node in our cluster
RippleAddress mNodePublic; // Node public key of peer.
std::string mNodeName;
@@ -58,6 +58,7 @@ private:
void handleStart(const boost::system::error_code& ecResult);
void handleVerifyTimer(const boost::system::error_code& ecResult);
void handlePingTimer(const boost::system::error_code& ecResult);
protected:

View File

@@ -217,7 +217,7 @@ Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit)
if (!txJSON.isMember("Flags")) txJSON["Flags"] = 0;
Ledger::pointer lpCurrent = mNetOps->getCurrentLedger();
SLE::pointer sleAccountRoot = mNetOps->getSLE(lpCurrent, Ledger::getAccountRootIndex(raSrcAddressID.getAccountID()));
SLE::pointer sleAccountRoot = mNetOps->getSLEi(lpCurrent, Ledger::getAccountRootIndex(raSrcAddressID.getAccountID()));
if (!sleAccountRoot)
{
@@ -899,7 +899,7 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest)
if (!lpLedger)
return jvResult;
ScopedUnlock su(theApp->getMasterLock(), lpLedger->isFixed());
ScopedUnlock su(theApp->getMasterLock());
if (!jvRequest.isMember("account"))
return rpcError(rpcINVALID_PARAMS);
@@ -980,7 +980,7 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest)
if (!lpLedger)
return jvResult;
ScopedUnlock su(theApp->getMasterLock(), lpLedger->isClosed() || lpLedger->isImmutable());
ScopedUnlock su(theApp->getMasterLock());
if (!jvRequest.isMember("account"))
return rpcError(rpcINVALID_PARAMS);
@@ -1526,6 +1526,7 @@ Json::Value RPCHandler::doLedger(Json::Value jvRequest)
Json::Value ret(Json::objectValue);
ScopedUnlock(theApp->getMasterLock());
ledger->addJson(ret, full ? LEDGER_JSON_FULL : 0);
return ret;
@@ -2147,7 +2148,7 @@ Json::Value RPCHandler::lookupLedger(Json::Value jvRequest, Ledger::pointer& lpL
if (-3 == iLedgerIndex)
{ // Last fully-validated ledger
lpLedger = mNetOps->getValidatedLedger();
iLedgerIndex = lpLedger->getLedgerSeq();
iLedgerIndex = lpLedger->getLedgerSeq();
}
if (iLedgerIndex <= 0)
@@ -2364,7 +2365,7 @@ Json::Value RPCHandler::doLedgerEntry(Json::Value jvRequest)
if (!!uNodeIndex)
{
SLE::pointer sleNode = mNetOps->getSLE(lpLedger, uNodeIndex);
SLE::pointer sleNode = mNetOps->getSLEi(lpLedger, uNodeIndex);
if (!sleNode)
{
@@ -2833,7 +2834,8 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole)
return rpcError(rpcNO_PERMISSION);
}
// XXX Need the master lock for getOperatingMode
boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock());
if (commandsA[i].iOptions & optNetwork
&& mNetOps->getOperatingMode() != NetworkOPs::omTRACKING
&& mNetOps->getOperatingMode() != NetworkOPs::omFULL)
@@ -2842,7 +2844,6 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole)
}
// XXX Should verify we have a current ledger.
boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock());
if ((commandsA[i].iOptions & optCurrent) && false)
{
return rpcError(rpcNO_CURRENT);

View File

@@ -7,6 +7,8 @@
#include <boost/format.hpp>
#include <boost/functional/hash.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/unordered_map.hpp>
#include <openssl/rand.h>
@@ -293,6 +295,9 @@ uint160 RippleAddress::getAccountID() const
}
}
static boost::mutex rncLock;
static boost::unordered_map< std::vector<unsigned char>, std::string > rncMap;
std::string RippleAddress::humanAccountID() const
{
switch (nVersion) {
@@ -300,7 +305,13 @@ std::string RippleAddress::humanAccountID() const
throw std::runtime_error("unset source - humanAccountID");
case VER_ACCOUNT_ID:
return ToString();
{
boost::mutex::scoped_lock sl(rncLock);
boost::unordered_map< std::vector<unsigned char>, std::string >::iterator it = rncMap.find(vchData);
if (it != rncMap.end())
return it->second;
return rncMap[vchData] = ToString();
}
case VER_ACCOUNT_PUBLIC:
{

View File

@@ -485,6 +485,17 @@ SHAMapItem::pointer SHAMap::peekItem(const uint256& id, SHAMapTreeNode::TNType&
return leaf->peekItem();
}
SHAMapItem::pointer SHAMap::peekItem(const uint256& id, uint256& hash)
{
boost::recursive_mutex::scoped_lock sl(mLock);
SHAMapTreeNode* leaf = walkToPointer(id);
if (!leaf)
return no_item;
hash = leaf->getNodeHash();
return leaf->peekItem();
}
bool SHAMap::hasItem(const uint256& id)
{ // does the tree have an item with this ID
boost::recursive_mutex::scoped_lock sl(mLock);

View File

@@ -406,6 +406,7 @@ public:
// save a copy if you only need a temporary
SHAMapItem::pointer peekItem(const uint256& id);
SHAMapItem::pointer peekItem(const uint256& id, uint256& hash);
SHAMapItem::pointer peekItem(const uint256& id, SHAMapTreeNode::TNType& type);
// traverse functions

View File

@@ -9,7 +9,7 @@ DECLARE_INSTANCE(SerializedLedgerEntry)
SETUP_LOG();
SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint256& index)
: STObject(sfLedgerEntry), mIndex(index)
: STObject(sfLedgerEntry), mIndex(index), mMutable(true)
{
set(sit);
uint16 type = getFieldU16(sfLedgerEntryType);
@@ -22,7 +22,7 @@ SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint
}
SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256& index)
: STObject(sfLedgerEntry), mIndex(index)
: STObject(sfLedgerEntry), mIndex(index), mMutable(true)
{
SerializerIterator sit(const_cast<Serializer&>(s)); // we know 's' isn't going away
set(sit);
@@ -41,7 +41,7 @@ SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256&
}
SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type, const uint256& index) :
STObject(sfLedgerEntry), mIndex(index), mType(type)
STObject(sfLedgerEntry), mIndex(index), mType(type), mMutable(true)
{
mFormat = LedgerEntryFormat::getLgrFormat(type);
if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type");
@@ -49,6 +49,13 @@ SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type, const uint256
setFieldU16(sfLedgerEntryType, static_cast<uint16>(mFormat->t_type));
}
SerializedLedgerEntry::pointer SerializedLedgerEntry::getMutable() const
{
SerializedLedgerEntry::pointer ret = boost::make_shared<SerializedLedgerEntry>(boost::ref(*this));
ret->mMutable = true;
return ret;
}
std::string SerializedLedgerEntry::getFullText() const
{
std::string ret = "\"";

View File

@@ -18,6 +18,7 @@ protected:
uint256 mIndex;
LedgerEntryType mType;
const LedgerEntryFormat* mFormat;
bool mMutable;
SerializedLedgerEntry* duplicate() const { return new SerializedLedgerEntry(*this); }
@@ -34,6 +35,10 @@ public:
const uint256& getIndex() const { return mIndex; }
void setIndex(const uint256& i) { mIndex = i; }
void setImmutable() { mMutable = false; }
bool isMutable() { return mMutable; }
SerializedLedgerEntry::pointer getMutable() const;
LedgerEntryType getType() const { return mType; }
uint16 getVersion() const { return getFieldU16(sfLedgerEntryType); }
const LedgerEntryFormat* getFormat() { return mFormat; }

View File

@@ -147,16 +147,18 @@ void STObject::set(const std::vector<SOElement::ref>& type)
bool STObject::setType(const std::vector<SOElement::ref> &type)
{
boost::ptr_vector<SerializedType> newData;
boost::ptr_vector<SerializedType> newData(type.size());
bool valid = true;
mType.clear();
mType.reserve(type.size());
BOOST_FOREACH(SOElement::ref elem, type)
{
bool match = false;
for (boost::ptr_vector<SerializedType>::iterator it = mData.begin(); it != mData.end(); ++it)
if (it->getFName() == elem->e_field)
{
{ // matching entry, move to new vector
match = true;
newData.push_back(mData.release(it).release());
if ((elem->flags == SOE_DEFAULT) && it->isDefault())
@@ -169,7 +171,7 @@ bool STObject::setType(const std::vector<SOElement::ref> &type)
}
if (!match)
{
{ // no match found
if (elem->flags == SOE_REQUIRED)
{
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid missing "
@@ -181,18 +183,17 @@ bool STObject::setType(const std::vector<SOElement::ref> &type)
mType.push_back(elem);
}
if (mData.size() != 0)
{
BOOST_FOREACH(const SerializedType& t, mData)
BOOST_FOREACH(const SerializedType& t, mData)
{ // Anything left over must be discardable
if (!t.getFName().isDiscardable())
{
if (!t.getFName().isDiscardable())
{
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid leftover "
<< t.getFName().getName();
valid = false;
}
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid leftover "
<< t.getFName().getName();
valid = false;
}
}
mData.swap(newData);
return valid;
}

View File

@@ -282,22 +282,23 @@ STAccount* STAccount::construct(SerializerIterator& u, SField::ref name)
STVector256* STVector256::construct(SerializerIterator& u, SField::ref name)
{
std::vector<unsigned char> data = u.getVL();
std::vector<uint256> value;
std::auto_ptr<STVector256> vec(new STVector256(name));
int count = data.size() / (256 / 8);
value.reserve(count);
vec->mValue.reserve(count);
unsigned int uStart = 0;
for (unsigned int i = 0; i != count; i++)
{
unsigned int uEnd = uStart+(256/8);
value.push_back(uint256(std::vector<unsigned char>(data.begin()+uStart, data.begin()+(uStart+32))));
// This next line could be optimized to construct a default uint256 in the vector and then copy into it
vec->mValue.push_back(uint256(std::vector<unsigned char>(data.begin()+uStart, data.begin()+uEnd)));
uStart = uEnd;
}
return new STVector256(name, value);
return vec.release();
}
void STVector256::add(Serializer& s) const

View File

@@ -5,6 +5,7 @@
#include "../json/value.h"
#include <boost/weak_ptr.hpp>
#include <boost/asio.hpp>
#include "WSDoor.h"
#include "Application.h"
@@ -17,7 +18,7 @@
DEFINE_INSTANCE(WebSocketConnection);
#ifndef WEBSOCKET_PING_FREQUENCY
#define WEBSOCKET_PING_FREQUENCY 120
#define WEBSOCKET_PING_FREQUENCY (5*60)
#endif
template <typename endpoint_type>
@@ -53,7 +54,7 @@ public:
WSConnection(WSServerHandler<endpoint_type>* wshpHandler, const connection_ptr& cpConnection)
: mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()),
mPingTimer(theApp->getAuxService()), mPinged(false)
mPingTimer(cpConnection->get_io_service()), mPinged(false)
{
mRemoteIP = cpConnection->get_socket().lowest_layer().remote_endpoint().address().to_string();
cLog(lsDEBUG) << "Websocket connection from " << mRemoteIP;
@@ -62,6 +63,7 @@ public:
void preDestroy()
{ // sever connection
mPingTimer.cancel();
mConnection.reset();
}
@@ -143,10 +145,10 @@ public:
bool onPingTimer()
{
if (mPinged)
return true;
return true; // causes connection to close
mPinged = true;
setPingTimer();
return false;
return false; // causes ping to be sent
}
void onPong()
@@ -154,8 +156,11 @@ public:
mPinged = false;
}
static void pingTimer(weak_connection_ptr c, WSServerHandler<endpoint_type>* h)
static void pingTimer(weak_connection_ptr c, WSServerHandler<endpoint_type>* h, const boost::system::error_code& e)
{
if (e)
return;
connection_ptr ptr = c.lock();
if (ptr)
h->pingTimer(ptr);
@@ -164,10 +169,10 @@ public:
void setPingTimer()
{
mPingTimer.expires_from_now(boost::posix_time::seconds(WEBSOCKET_PING_FREQUENCY));
mPingTimer.async_wait(boost::bind(&WSConnection<endpoint_type>::pingTimer, mConnection, mHandler));
mPingTimer.async_wait(boost::bind(
&WSConnection<endpoint_type>::pingTimer, mConnection, mHandler, boost::asio::placeholders::error));
}
};
// vim:ts=4

View File

@@ -176,7 +176,7 @@ protected:
memset(&vchData[0], 0, vchData.size());
}
void SetData(int nVersionIn, std::vector<unsigned char> vchDataIn)
void SetData(int nVersionIn, const std::vector<unsigned char>& vchDataIn)
{
nVersion = nVersionIn;
vchData = vchDataIn;
@@ -186,7 +186,7 @@ protected:
{
nVersion = nVersionIn;
vchData.resize(nSize);
if (!vchData.empty())
if (nSize)
memcpy(&vchData[0], pdata, nSize);
}

104
src/js/orderbook.js Normal file
View File

@@ -0,0 +1,104 @@
// Routines for working with an orderbook.
//
// Events:
// var network = require("./network.js");
var EventEmitter = require('events').EventEmitter;
var Amount = require('./amount').Amount;
var UInt160 = require('./uint160').UInt160;
var Currency = require('./currency').Currency;
var extend = require('extend');
var OrderBook = function (remote,
currency_out, issuer_out,
currency_in, issuer_in) {
var self = this;
this._remote = remote;
this._currency_out = currency_out;
this._issuer_out = issuer_out;
this._currency_in = currency_in;
this._issuer_in = issuer_in;
this._subs = 0;
// Ledger entry object
// Important: This must never be overwritten, only extend()-ed
this._entry = {};
this.on('newListener', function (type, listener) {
if (OrderBook.subscribe_events.indexOf(type) !== -1) {
if (!self._subs && 'open' === self._remote._online_state) {
self._remote.request_subscribe()
.books([self.to_json()])
.request();
}
self._subs += 1;
}
});
this.on('removeListener', function (type, listener) {
if (OrderBook.subscribe_events.indexOf(type) !== -1) {
self._subs -= 1;
if (!self._subs && 'open' === self._remote._online_state) {
self._remote.request_unsubscribe()
.books([self.to_json()])
.request();
}
}
});
this._remote.on('connect', function () {
if (self._subs) {
self._remote.request_subscribe()
.books([self.to_json()])
.request();
}
});
return this;
};
OrderBook.prototype = new EventEmitter;
/**
* List of events that require a remote subscription to the orderbook.
*/
OrderBook.subscribe_events = ['transaction'];
OrderBook.prototype.to_json = function ()
{
var json = {
"CurrencyOut": this._currency_out,
"CurrencyIn": this._currency_in
};
if (json["CurrencyOut"] !== "XRP") json["IssuerOut"] = this._issuer_out;
if (json["CurrencyIn"] !== "XRP") json["IssuerIn"] = this._issuer_in;
return json;
};
/**
* Whether the OrderBook is valid.
*
* Note: This only checks whether the parameters (currencies and issuer) are
* syntactically valid. It does not check anything against the ledger.
*/
OrderBook.prototype.is_valid = function ()
{
return (
Currency.is_valid(this._currency_in) &&
(this._currency_in !== "XRP" && UInt160.is_valid(this._issuer_in)) &&
Currency.is_valid(this._currency_out) &&
(this._currency_out !== "XRP" && UInt160.is_valid(this._issuer_out)) &&
!(this._currency_in === "XRP" && this._currency_out === "XRP")
);
};
exports.OrderBook = OrderBook;
// vim:sw=2:sts=2:ts=8:et

View File

@@ -22,6 +22,7 @@ var UInt160 = require('./amount').UInt160;
var Transaction = require('./transaction').Transaction;
var Account = require('./account').Account;
var Meta = require('./meta').Meta;
var OrderBook = require('./orderbook').OrderBook;
var utils = require('./utils');
var config = require('./config');
@@ -181,6 +182,31 @@ Request.prototype.rt_accounts = function (accounts) {
return this.accounts(accounts, true);
};
Request.prototype.books = function (books) {
var procBooks = [];
for (var i = 0, l = books.length; i < l; i++) {
var book = books[i];
var json = {
"CurrencyOut": Currency.json_rewrite(book["CurrencyOut"]),
"CurrencyIn": Currency.json_rewrite(book["CurrencyIn"])
};
if (json["CurrencyOut"] !== "XRP") {
json["IssuerOut"] = UInt160.json_rewrite(book["IssuerOut"]);
}
if (json["CurrencyIn"] !== "XRP") {
json["IssuerIn"] = UInt160.json_rewrite(book["IssuerIn"]);
}
procBooks.push(json);
}
this.message.books = procBooks;
return this;
};
//
// Remote - access to a remote Ripple server via websocket.
//
@@ -1036,6 +1062,15 @@ Remote.prototype.account = function (accountId) {
return this._accounts[account.to_json()] = account;
};
Remote.prototype.book = function (currency_out, issuer_out,
currency_in, issuer_in) {
var book = new OrderBook(this,
currency_out, issuer_out,
currency_in, issuer_in);
return book;
}
// Return the next account sequence if possible.
// <-- undefined or Sequence
Remote.prototype.account_seq = function (account, advance) {

View File

@@ -218,6 +218,11 @@ buster.testCase("Amount", {
"Divide EUR by XRP, neg, <1" : function () {
buster.assert.equals("-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("2000")).to_text_full());
}
},
"Amount comparisons" : {
"10 USD != 100 USD" : function () {
buster.refute(Amount.from_json("10/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL").equals(Amount.from_json("100/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL")));
}
}
});