mirror of
https://github.com/Xahau/xahaud.git
synced 2026-06-02 16:26:37 +00:00
Merge branch 'master' into autoclient
Conflicts: src/cpp/ripple/AutoSocket.h
This commit is contained in:
@@ -142,7 +142,7 @@ STAmount::STAmount(SField::ref n, const Json::Value& v)
|
||||
std::vector<std::string> elements;
|
||||
boost::split(elements, val, boost::is_any_of("\t\n\r ,/"));
|
||||
|
||||
if ((elements.size() < 0) || (elements.size() > 3))
|
||||
if (elements.size() > 3)
|
||||
throw std::runtime_error("invalid amount string");
|
||||
|
||||
value = elements[0];
|
||||
@@ -1214,6 +1214,40 @@ std::string STAmount::getFullText() const
|
||||
}
|
||||
}
|
||||
|
||||
STAmount STAmount::getRound() const
|
||||
{
|
||||
if (mIsNative)
|
||||
return *this;
|
||||
|
||||
uint64 valueDigits = mValue % 1000000000ull;
|
||||
if (valueDigits == 1)
|
||||
return STAmount(mCurrency, mIssuer, mValue - 1, mOffset, mIsNegative);
|
||||
else if (valueDigits == 999999999ull)
|
||||
return STAmount(mCurrency, mIssuer, mValue + 1, mOffset, mIsNegative);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void STAmount::roundSelf()
|
||||
{
|
||||
if (mIsNative)
|
||||
return;
|
||||
|
||||
uint64 valueDigits = mValue % 1000000000ull;
|
||||
if (valueDigits == 1)
|
||||
{
|
||||
mValue -= 1;
|
||||
if (mValue < cMinValue)
|
||||
canonicalize();
|
||||
}
|
||||
else if (valueDigits == 999999999ull)
|
||||
{
|
||||
mValue += 1;
|
||||
if (mValue > cMaxValue)
|
||||
canonicalize();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::string STAmount::getExtendedText() const
|
||||
{
|
||||
@@ -1460,7 +1494,7 @@ BOOST_AUTO_TEST_CASE( CustomCurrency_test )
|
||||
BOOST_TEST_MESSAGE("Amount CC Complete");
|
||||
}
|
||||
|
||||
static void roundTest(int n, int d, int m)
|
||||
static bool roundTest(int n, int d, int m)
|
||||
{ // check STAmount rounding
|
||||
STAmount num(CURRENCY_ONE, ACCOUNT_ONE, n);
|
||||
STAmount den(CURRENCY_ONE, ACCOUNT_ONE, d);
|
||||
@@ -1469,18 +1503,19 @@ static void roundTest(int n, int d, int m)
|
||||
STAmount res = STAmount::multiply(quot, mul, CURRENCY_ONE, ACCOUNT_ONE);
|
||||
if (res.isNative())
|
||||
BOOST_FAIL("Product is native");
|
||||
|
||||
cLog(lsDEBUG) << n << " / " << d << " = " << quot.getText();
|
||||
res.roundSelf();
|
||||
|
||||
STAmount cmp(CURRENCY_ONE, ACCOUNT_ONE, (n * m) / d);
|
||||
if (cmp.isNative())
|
||||
BOOST_FAIL("Comparison amount is native");
|
||||
|
||||
if (res == cmp)
|
||||
return;
|
||||
return true;
|
||||
cmp.throwComparable(res);
|
||||
cLog(lsINFO) << "(" << num.getText() << "/" << den.getText() << ") X " << mul.getText() << " = "
|
||||
cLog(lsWARNING) << "(" << num.getText() << "/" << den.getText() << ") X " << mul.getText() << " = "
|
||||
<< res.getText() << " not " << cmp.getText();
|
||||
BOOST_FAIL("Round fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
static void mulTest(int a, int b)
|
||||
|
||||
@@ -50,7 +50,7 @@ Application::Application() :
|
||||
getRand(mNonce256.begin(), mNonce256.size());
|
||||
getRand(reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
|
||||
mJobQueue.setThreadCount();
|
||||
mSweepTimer.expires_from_now(boost::posix_time::seconds(20));
|
||||
mSweepTimer.expires_from_now(boost::posix_time::seconds(10));
|
||||
mSweepTimer.async_wait(boost::bind(&Application::sweep, this));
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,15 @@ public:
|
||||
boost::asio::async_write(PlainSocket(), buffers, handler);
|
||||
}
|
||||
|
||||
template <typename Allocator, typename Handler>
|
||||
void async_write(boost::asio::basic_streambuf<Allocator>& buffers, Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_write(*mSocket, buffers, handler);
|
||||
else
|
||||
boost::asio::async_write(PlainSocket(), buffers, handler);
|
||||
}
|
||||
|
||||
template <typename Buf, typename Condition, typename Handler>
|
||||
void async_read(const Buf& buffers, Condition cond, Handler handler)
|
||||
{
|
||||
|
||||
@@ -55,15 +55,16 @@ const char *LedgerDBInit[] = {
|
||||
);",
|
||||
"CREATE INDEX SeqLedger ON Ledgers(LedgerSeq);",
|
||||
|
||||
"CREATE TABLE LedgerValidations ( \
|
||||
"CREATE TABLE Validations ( \
|
||||
LedgerHash CHARACTER(64), \
|
||||
NodePubKey CHARACTER(56), \
|
||||
Flags BIGINT UNSIGNED, \
|
||||
SignTime BIGINT UNSIGNED, \
|
||||
Signature BLOB \
|
||||
RawData BLOB \
|
||||
);",
|
||||
"CREATE INDEX ValidationByHash ON \
|
||||
LedgerValidations(LedgerHash);",
|
||||
"CREATE INDEX ValidationsByHash ON \
|
||||
Validations(LedgerHash);",
|
||||
"CREATE INDEX ValidationsByTime ON \
|
||||
Validations(SignTime);",
|
||||
|
||||
"END TRANSACTION;"
|
||||
};
|
||||
|
||||
@@ -166,15 +166,9 @@ void HashedObjectStore::bulkWrite()
|
||||
HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash)
|
||||
{
|
||||
|
||||
HashedObject::pointer obj;
|
||||
{
|
||||
obj = mCache.fetch(hash);
|
||||
if (obj)
|
||||
{
|
||||
// cLog(lsTRACE) << "HOS: " << hash << " fetch: incache";
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
HashedObject::pointer obj = mCache.fetch(hash);
|
||||
if (obj)
|
||||
return obj;
|
||||
|
||||
if (mNegativeCache.isPresent(hash))
|
||||
return obj;
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
|
||||
KeyCache(const std::string& name, int size = 0, int age = 120) : mName(name), mTargetSize(size), mTargetAge(age)
|
||||
{
|
||||
assert((mTargetSize >= 0) && (mTargetAge > 2));
|
||||
assert((size >= 0) && (age > 2));
|
||||
}
|
||||
|
||||
void getSize()
|
||||
|
||||
@@ -113,14 +113,31 @@ Ledger::Ledger(const std::string& rawLedger, bool hasPrefix) :
|
||||
zeroFees();
|
||||
}
|
||||
|
||||
void Ledger::setImmutable()
|
||||
{
|
||||
if (!mImmutable)
|
||||
{
|
||||
updateHash();
|
||||
mImmutable = true;
|
||||
if (mTransactionMap)
|
||||
mTransactionMap->setImmutable();
|
||||
if (mAccountStateMap)
|
||||
mAccountStateMap->setImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
void Ledger::updateHash()
|
||||
{
|
||||
if (!mImmutable)
|
||||
{
|
||||
if (mTransactionMap) mTransHash = mTransactionMap->getHash();
|
||||
else mTransHash.zero();
|
||||
if (mAccountStateMap) mAccountHash = mAccountStateMap->getHash();
|
||||
else mAccountHash.zero();
|
||||
if (mTransactionMap)
|
||||
mTransHash = mTransactionMap->getHash();
|
||||
else
|
||||
mTransHash.zero();
|
||||
if (mAccountStateMap)
|
||||
mAccountHash = mAccountStateMap->getHash();
|
||||
else
|
||||
mAccountHash.zero();
|
||||
}
|
||||
|
||||
Serializer s(118);
|
||||
@@ -170,18 +187,17 @@ void Ledger::setAccepted(uint32 closeTime, int closeResolution, bool correctClos
|
||||
mCloseTime = correctCloseTime ? (closeTime - (closeTime % closeResolution)) : closeTime;
|
||||
mCloseResolution = closeResolution;
|
||||
mCloseFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime;
|
||||
updateHash();
|
||||
mAccepted = true;
|
||||
mImmutable = true;
|
||||
setImmutable();
|
||||
}
|
||||
|
||||
void Ledger::setAccepted()
|
||||
{ // used when we acquired the ledger
|
||||
// FIXME assert(mClosed && (mCloseTime != 0) && (mCloseResolution != 0));
|
||||
mCloseTime -= mCloseTime % mCloseResolution;
|
||||
updateHash();
|
||||
if ((mCloseFlags & sLCF_NoConsensusTime) == 0)
|
||||
mCloseTime -= mCloseTime % mCloseResolution;
|
||||
mAccepted = true;
|
||||
mImmutable = true;
|
||||
setImmutable();
|
||||
}
|
||||
|
||||
AccountState::pointer Ledger::getAccountState(const RippleAddress& accountID)
|
||||
@@ -504,10 +520,7 @@ Ledger::pointer Ledger::getSQL(const std::string& sql)
|
||||
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
|
||||
|
||||
if (!db->executeSQL(sql) || !db->startIterRows())
|
||||
{
|
||||
cLog(lsDEBUG) << "No ledger for query: " << sql;
|
||||
return Ledger::pointer();
|
||||
}
|
||||
|
||||
db->getStr("LedgerHash", hash);
|
||||
ledgerHash.SetHex(hash, true);
|
||||
@@ -530,6 +543,8 @@ Ledger::pointer Ledger::getSQL(const std::string& sql)
|
||||
Ledger::pointer ret = boost::make_shared<Ledger>(prevHash, transHash, accountHash, totCoins,
|
||||
closingTime, prevClosingTime, closeFlags, closeResolution, ledgerSeq);
|
||||
ret->setClosed();
|
||||
if (theApp->getOPs().haveLedger(ledgerSeq))
|
||||
ret->setAccepted();
|
||||
if (ret->getHash() != ledgerHash)
|
||||
{
|
||||
if (sLog(lsERROR))
|
||||
@@ -550,7 +565,7 @@ uint256 Ledger::getHashByIndex(uint32 ledgerIndex)
|
||||
{
|
||||
uint256 ret;
|
||||
|
||||
std::string sql="SELECT LedgerHash FROM Ledgers WHERE LedgerSeq='";
|
||||
std::string sql="SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
|
||||
sql.append(boost::lexical_cast<std::string>(ledgerIndex));
|
||||
sql.append("';");
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
void setClosed() { mClosed = true; }
|
||||
void setAccepted(uint32 closeTime, int closeResolution, bool correctCloseTime);
|
||||
void setAccepted();
|
||||
void setImmutable() { updateHash(); mImmutable = true; }
|
||||
void setImmutable();
|
||||
bool isClosed() { return mClosed; }
|
||||
bool isAccepted() { return mAccepted; }
|
||||
bool isImmutable() { return mImmutable; }
|
||||
|
||||
@@ -160,6 +160,7 @@ bool LedgerAcquire::tryLocal()
|
||||
{
|
||||
cLog(lsDEBUG) << "Had everything locally";
|
||||
mComplete = true;
|
||||
mLedger->setClosed();
|
||||
}
|
||||
|
||||
return mComplete;
|
||||
@@ -244,11 +245,9 @@ void LedgerAcquire::done()
|
||||
|
||||
if (isComplete() && !isFailed() && mLedger)
|
||||
{
|
||||
mLedger->setClosed();
|
||||
if (mAccept)
|
||||
{
|
||||
mLedger->setClosed();
|
||||
mLedger->setAccepted();
|
||||
}
|
||||
theApp->getLedgerMaster().storeLedger(mLedger);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -30,7 +30,7 @@ void LedgerHistory::addLedger(Ledger::pointer ledger)
|
||||
|
||||
void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger, bool fromConsensus)
|
||||
{
|
||||
assert(ledger && ledger->isAccepted());
|
||||
assert(ledger && ledger->isAccepted() && ledger->isImmutable());
|
||||
uint256 h(ledger->getHash());
|
||||
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||
mLedgersByHash.canonicalize(h, ledger, true);
|
||||
@@ -70,6 +70,7 @@ Ledger::pointer LedgerHistory::getLedgerBySeq(uint32 index)
|
||||
assert(ret->getLedgerSeq() == index);
|
||||
|
||||
sl.lock();
|
||||
assert(ret->isImmutable());
|
||||
mLedgersByHash.canonicalize(ret->getHash(), ret);
|
||||
mLedgersByIndex[ret->getLedgerSeq()] = ret->getHash();
|
||||
return (ret->getLedgerSeq() == index) ? ret : Ledger::pointer();
|
||||
@@ -80,13 +81,15 @@ Ledger::pointer LedgerHistory::getLedgerByHash(const uint256& hash)
|
||||
Ledger::pointer ret = mLedgersByHash.fetch(hash);
|
||||
if (ret)
|
||||
{
|
||||
assert(ret->getHash() == hash);
|
||||
assert(ret->isImmutable());
|
||||
assert(ret->getHash() == hash); // FIXME: We seem to be getting these
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = Ledger::loadByHash(hash);
|
||||
if (!ret)
|
||||
return ret;
|
||||
assert(ret->isImmutable());
|
||||
assert(ret->getHash() == hash);
|
||||
mLedgersByHash.canonicalize(ret->getHash(), ret);
|
||||
assert(ret->getHash() == hash);
|
||||
|
||||
@@ -133,6 +133,12 @@ bool LedgerMaster::haveLedgerRange(uint32 from, uint32 to)
|
||||
return (prevMissing == RangeSet::RangeSetAbsent) || (prevMissing < from);
|
||||
}
|
||||
|
||||
bool LedgerMaster::haveLedger(uint32 seq)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mCompleteLedgers.hasValue(seq);
|
||||
}
|
||||
|
||||
void LedgerMaster::asyncAccept(Ledger::pointer ledger)
|
||||
{
|
||||
uint32 seq = ledger->getLedgerSeq();
|
||||
|
||||
@@ -126,6 +126,7 @@ public:
|
||||
void fixMismatch(Ledger::ref ledger);
|
||||
|
||||
bool haveLedgerRange(uint32 from, uint32 to);
|
||||
bool haveLedger(uint32 seq);
|
||||
|
||||
void resumeAcquiring();
|
||||
|
||||
|
||||
@@ -113,6 +113,11 @@ bool NetworkOPs::haveLedgerRange(uint32 from, uint32 to)
|
||||
return mLedgerMaster->haveLedgerRange(from, to);
|
||||
}
|
||||
|
||||
bool NetworkOPs::haveLedger(uint32 seq)
|
||||
{
|
||||
return mLedgerMaster->haveLedger(seq);
|
||||
}
|
||||
|
||||
bool NetworkOPs::addWantedHash(const uint256& h)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mWantedHashLock);
|
||||
|
||||
@@ -150,6 +150,7 @@ public:
|
||||
|
||||
// Do we have this inclusive range of ledgers in our database
|
||||
bool haveLedgerRange(uint32 from, uint32 to);
|
||||
bool haveLedger(uint32 seq);
|
||||
|
||||
SerializedValidation::ref getLastValidation() { return mLastValidation; }
|
||||
void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; }
|
||||
|
||||
@@ -686,7 +686,7 @@ void Peer::recvHello(ripple::TMHello& packet)
|
||||
<< "Peer speaks version " <<
|
||||
(packet.protoversion() >> 16) << "." << (packet.protoversion() & 0xFF);
|
||||
mHello = packet;
|
||||
if (theApp->getUNL().nodeInCluster(mNodePublic))
|
||||
if (theApp->getUNL().nodeInCluster(mNodePublic, mNodeName))
|
||||
{
|
||||
mCluster = true;
|
||||
mLoad.setPrivileged();
|
||||
@@ -1785,7 +1785,11 @@ Json::Value Peer::getJson()
|
||||
if (mInbound)
|
||||
ret["inbound"] = true;
|
||||
if (mCluster)
|
||||
{
|
||||
ret["cluster"] = true;
|
||||
if (!mNodeName.empty())
|
||||
ret["name"] = mNodeName;
|
||||
}
|
||||
if (mHello.has_fullversion())
|
||||
ret["version"] = mHello.fullversion();
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ private:
|
||||
bool mActive;
|
||||
bool mCluster; // Node in our cluster
|
||||
RippleAddress mNodePublic; // Node public key of peer.
|
||||
std::string mNodeName;
|
||||
ipPort mIpPort;
|
||||
ipPort mIpPortConnect;
|
||||
uint256 mCookieHash;
|
||||
|
||||
@@ -296,6 +296,11 @@ Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit)
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("debug_signing")) {
|
||||
jvResult["tx_unsigned"] = strHex(stpTrans->getSerializer().peekData());
|
||||
jvResult["tx_signing_hash"] = stpTrans->getSigningHash().ToString();
|
||||
}
|
||||
|
||||
// FIXME: For performance, transactions should not be signed in this code path.
|
||||
stpTrans->sign(naAccountPrivate);
|
||||
|
||||
|
||||
@@ -387,6 +387,9 @@ public:
|
||||
static bool issuerFromString(uint160& uDstIssuer, const std::string& sIssuer);
|
||||
|
||||
Json::Value getJson(int) const;
|
||||
|
||||
STAmount getRound() const;
|
||||
void roundSelf();
|
||||
};
|
||||
|
||||
extern STAmount saZero;
|
||||
|
||||
@@ -31,30 +31,39 @@ public:
|
||||
typedef boost::weak_ptr<data_type> weak_data_ptr;
|
||||
typedef boost::shared_ptr<data_type> data_ptr;
|
||||
|
||||
typedef bool (*visitor_func)(const c_Key&, c_Data&);
|
||||
|
||||
protected:
|
||||
|
||||
typedef std::pair<time_t, data_ptr> cache_entry;
|
||||
class cache_entry
|
||||
{
|
||||
public:
|
||||
time_t 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) { ; }
|
||||
bool isCached() { return !!ptr; }
|
||||
bool isExpired() { return weak_ptr.expired(); }
|
||||
data_ptr lock() { return weak_ptr.lock(); }
|
||||
void touch() { last_use = time(NULL); }
|
||||
};
|
||||
|
||||
typedef std::pair<key_type, cache_entry> cache_pair;
|
||||
typedef boost::unordered_map<key_type, cache_entry> cache_type;
|
||||
typedef typename cache_type::iterator cache_iterator;
|
||||
typedef boost::unordered_map<key_type, weak_data_ptr> map_type;
|
||||
typedef typename map_type::iterator map_iterator;
|
||||
|
||||
mutable boost::recursive_mutex mLock;
|
||||
|
||||
std::string mName; // Used for logging
|
||||
unsigned int mTargetSize; // Desired number of cache entries (0 = ignore)
|
||||
int mTargetAge; // Desired maximum cache age
|
||||
int mCacheCount; // Number of items cached
|
||||
|
||||
cache_type mCache; // Hold strong reference to recent objects
|
||||
map_type mMap; // Track stored objects
|
||||
time_t mLastSweep;
|
||||
|
||||
public:
|
||||
TaggedCache(const char *name, int size, int age)
|
||||
: mName(name), mTargetSize(size), mTargetAge(age), mLastSweep(time(NULL)) { ; }
|
||||
: mName(name), mTargetSize(size), mTargetAge(age), mCacheCount(0), mLastSweep(time(NULL)) { ; }
|
||||
|
||||
int getTargetSize() const;
|
||||
int getTargetAge() const;
|
||||
@@ -66,8 +75,6 @@ public:
|
||||
void setTargetSize(int size);
|
||||
void setTargetAge(int age);
|
||||
void sweep();
|
||||
void visitAll(visitor_func); // Visits all tracked objects, removes selected objects
|
||||
void visitCached(visitor_func); // Visits all cached objects, uncaches selected objects
|
||||
|
||||
bool touch(const key_type& key);
|
||||
bool del(const key_type& key, bool valid);
|
||||
@@ -108,13 +115,13 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::setTa
|
||||
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getCacheSize()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mCache.size();
|
||||
return mCacheCount;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getTrackSize()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mMap.size();
|
||||
return mCache.size();
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep()
|
||||
@@ -123,134 +130,108 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
||||
|
||||
time_t mLastSweep = time(NULL);
|
||||
time_t target = mLastSweep - mTargetAge;
|
||||
int cacheRemovals = 0, mapRemovals = 0, cc = 0;
|
||||
|
||||
// Pass 1, remove old objects from cache
|
||||
int cacheRemovals = 0;
|
||||
if ((mTargetSize == 0) || (mCache.size() > mTargetSize))
|
||||
if ((mTargetSize != 0) && (mCache.size() > mTargetSize))
|
||||
{
|
||||
if (mTargetSize != 0)
|
||||
{
|
||||
target = mLastSweep - (mTargetAge * mTargetSize / mCache.size());
|
||||
if (target > (mLastSweep - 2))
|
||||
target = mLastSweep - 2;
|
||||
target = mLastSweep - (mTargetAge * mTargetSize / mCache.size());
|
||||
if (target > (mLastSweep - 2))
|
||||
target = mLastSweep - 2;
|
||||
Log(lsINFO, TaggedCachePartition) << mName << " is growing fast " <<
|
||||
mCache.size() << " of " << mTargetSize <<
|
||||
" aging at " << (mLastSweep - target) << " of " << mTargetAge;
|
||||
}
|
||||
|
||||
Log(lsINFO, TaggedCachePartition) << mName << " is growing fast " <<
|
||||
mCache.size() << " of " << mTargetSize <<
|
||||
" aging at " << (mLastSweep - target) << " of " << mTargetAge;
|
||||
}
|
||||
else
|
||||
target = mLastSweep - mTargetAge;
|
||||
|
||||
cache_iterator cit = mCache.begin();
|
||||
while (cit != mCache.end())
|
||||
{
|
||||
if (cit->second.first < target)
|
||||
cache_iterator cit = mCache.begin();
|
||||
while (cit != mCache.end())
|
||||
{
|
||||
if (!cit->second.ptr)
|
||||
{ // weak
|
||||
if (cit->second.weak_ptr.expired())
|
||||
{
|
||||
++cacheRemovals;
|
||||
++mapRemovals;
|
||||
mCache.erase(cit++);
|
||||
}
|
||||
else
|
||||
++cit;
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2, remove dead objects from map
|
||||
int mapRemovals = 0;
|
||||
map_iterator mit = mMap.begin();
|
||||
while (mit != mMap.end())
|
||||
{
|
||||
if (mit->second.expired())
|
||||
{
|
||||
++mapRemovals;
|
||||
mMap.erase(mit++);
|
||||
}
|
||||
else
|
||||
++mit;
|
||||
{ // strong
|
||||
if (cit->second.last_use < target)
|
||||
{ // expired
|
||||
--mCacheCount;
|
||||
++cacheRemovals;
|
||||
cit->second.ptr.reset();
|
||||
if (cit->second.weak_ptr.expired())
|
||||
{
|
||||
++mapRemovals;
|
||||
mCache.erase(cit++);
|
||||
}
|
||||
else
|
||||
++cit;
|
||||
}
|
||||
else
|
||||
{
|
||||
++cc;
|
||||
++cit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(cc == mCacheCount);
|
||||
if (TaggedCachePartition.doLog(lsTRACE) && (mapRemovals || cacheRemovals))
|
||||
Log(lsTRACE, TaggedCachePartition) << mName << ": cache = " << mCache.size() << "-" << cacheRemovals <<
|
||||
", map = " << mMap.size() << "-" << mapRemovals;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::visitAll(visitor_func func)
|
||||
{ // Visits all tracked objects, removes selected objects
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
map_iterator mit = mMap.begin();
|
||||
while (mit != mMap.end())
|
||||
{
|
||||
data_ptr cachedData = mit->second.lock();
|
||||
if (!cachedData)
|
||||
mMap.erase(mit++); // dead reference found
|
||||
else if (func(mit->first, mit->second))
|
||||
{
|
||||
mCache.erase(mit->first);
|
||||
mMap.erase(mit++);
|
||||
}
|
||||
else
|
||||
++mit;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::visitCached(visitor_func func)
|
||||
{ // Visits all cached objects, uncaches selected objects
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.begin();
|
||||
while (cit != mCache.end())
|
||||
{
|
||||
if (func(cit->first, cit->second.second))
|
||||
mCache.erase(cit++);
|
||||
else
|
||||
++cit;
|
||||
}
|
||||
", map-=" << mapRemovals;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch(const key_type& key)
|
||||
{ // If present, make current in cache
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
// Is the object in the map?
|
||||
map_iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end())
|
||||
return false;
|
||||
if (mit->second.expired())
|
||||
{ // in map, but expired
|
||||
mMap.erase(mit);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the object in the cache?
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit != mCache.end())
|
||||
{ // in both map and cache
|
||||
cit->second.first = time(NULL);
|
||||
if (cit == mCache.end()) // Don't have the object
|
||||
return false;
|
||||
cache_entry& entry = cit->second;
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
entry.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
// In map but not cache, put in cache
|
||||
mCache.insert(cache_pair(key, cache_entry(time(NULL), data_ptr(cit->second.second))));
|
||||
return true;
|
||||
entry.ptr = entry.lock();
|
||||
if (entry.isCached())
|
||||
{ // We just put the object back in cache
|
||||
++mCacheCount;
|
||||
entry.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Object fell out
|
||||
mCache.erase(cit);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::del(const key_type& key, bool valid)
|
||||
{ // Remove from cache, if !valid, remove from map too. Returns true if removed from cache
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
if (!valid)
|
||||
{ // remove from map too
|
||||
map_iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end()) // not in map, cannot be in cache
|
||||
return false;
|
||||
mMap.erase(mit);
|
||||
}
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end())
|
||||
return false;
|
||||
mCache.erase(cit);
|
||||
return true;
|
||||
cache_entry& entry = cit->second;
|
||||
|
||||
bool ret = false;
|
||||
if (entry.isCached())
|
||||
{
|
||||
--mCacheCount;
|
||||
entry.ptr.reset();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (!valid || entry.isExpired())
|
||||
mCache.erase(cit);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
@@ -259,40 +240,50 @@ bool TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key, boost::shared
|
||||
// Return values: true=we had the data already
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
map_iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end())
|
||||
{ // not in map
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end())
|
||||
{
|
||||
mCache.insert(cache_pair(key, cache_entry(time(NULL), data)));
|
||||
mMap.insert(std::make_pair(key, data));
|
||||
++mCacheCount;
|
||||
return false;
|
||||
}
|
||||
cache_entry& entry = cit->second;
|
||||
entry.touch();
|
||||
|
||||
data_ptr cachedData = mit->second.lock();
|
||||
if (!cachedData)
|
||||
{ // in map, but expired. Update in map, insert in cache
|
||||
mit->second = data;
|
||||
mCache.insert(cache_pair(key, cache_entry(time(NULL), data)));
|
||||
if (entry.isCached())
|
||||
{
|
||||
if (replace)
|
||||
{
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
}
|
||||
else
|
||||
data = entry.ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
// in map and cache, canonicalize
|
||||
if (replace)
|
||||
mit->second = data;
|
||||
else
|
||||
data = cachedData;
|
||||
|
||||
// Valid in map, is it in cache?
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit != mCache.end())
|
||||
data_ptr cachedData = entry.lock();
|
||||
if (cachedData)
|
||||
{
|
||||
cit->second.first = time(NULL); // Yes, refesh
|
||||
if (replace)
|
||||
cit->second.second = data;
|
||||
{
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.ptr = cachedData;
|
||||
data = cachedData;
|
||||
}
|
||||
++mCacheCount;
|
||||
return true;
|
||||
}
|
||||
else // no, add to cache
|
||||
mCache.insert(cache_pair(key, cache_entry(time(NULL), data)));
|
||||
|
||||
return true;
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
++mCacheCount;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
@@ -300,29 +291,23 @@ boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
|
||||
{ // fetch us a shared pointer to the stored data object
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
// Is it in the cache?
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit != mCache.end())
|
||||
if (cit == mCache.end())
|
||||
return data_ptr();
|
||||
cache_entry& entry = cit->second;
|
||||
entry.touch();
|
||||
|
||||
if (entry.isCached())
|
||||
return entry.ptr;
|
||||
|
||||
entry.ptr = entry.lock();
|
||||
if (entry.isCached())
|
||||
{
|
||||
cit->second.first = time(NULL); // Yes, refresh
|
||||
return cit->second.second;
|
||||
++mCacheCount;
|
||||
return entry.ptr;
|
||||
}
|
||||
|
||||
// Is it in the map?
|
||||
map_iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end())
|
||||
return data_ptr(); // No, we're done
|
||||
|
||||
data_ptr cachedData = mit->second.lock();
|
||||
if (!cachedData)
|
||||
{ // in map, but expired. Sorry, we don't have it
|
||||
mMap.erase(mit);
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
// Put it back in the cache
|
||||
mCache.insert(cache_pair(key, cache_entry(time(NULL), cachedData)));
|
||||
return cachedData;
|
||||
mCache.erase(cit);
|
||||
return data_ptr();
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
|
||||
@@ -64,15 +64,6 @@ void UniqueNodeList::start()
|
||||
// Load information about when we last updated.
|
||||
bool UniqueNodeList::miscLoad()
|
||||
{
|
||||
BOOST_FOREACH(const std::string& node, theConfig.CLUSTER_NODES)
|
||||
{
|
||||
RippleAddress a = RippleAddress::createNodePublic(node);
|
||||
if (a.isValid())
|
||||
sClusterNodes.insert(a);
|
||||
else
|
||||
cLog(lsWARNING) << "Entry in cluster list invalid: '" << node << "'";
|
||||
}
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl(theApp->getWalletDB()->getDBLock());
|
||||
Database *db=theApp->getWalletDB()->getDB();
|
||||
|
||||
@@ -105,13 +96,18 @@ bool UniqueNodeList::miscSave()
|
||||
|
||||
void UniqueNodeList::trustedLoad()
|
||||
{
|
||||
BOOST_FOREACH(const std::string& node, theConfig.CLUSTER_NODES)
|
||||
boost::regex rNode("\\`\\s*(\\S+)[\\s]*(.*)\\'");
|
||||
BOOST_FOREACH(const std::string& c, theConfig.CLUSTER_NODES)
|
||||
{
|
||||
RippleAddress a = RippleAddress::createNodePublic(node);
|
||||
if (a.isValid())
|
||||
sClusterNodes.insert(a);
|
||||
boost::smatch match;
|
||||
if (boost::regex_match(c, match, rNode))
|
||||
{
|
||||
RippleAddress a = RippleAddress::createNodePublic(match[1]);
|
||||
if (a.isValid())
|
||||
sClusterNodes.insert(std::make_pair(a, match[2]));
|
||||
}
|
||||
else
|
||||
cLog(lsWARNING) << "Entry in cluster list invalid: '" << node << "'";
|
||||
cLog(lsWARNING) << "Entry in cluster list invalid: '" << c << "'";
|
||||
}
|
||||
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
@@ -1731,7 +1727,17 @@ bool UniqueNodeList::nodeInUNL(const RippleAddress& naNodePublic)
|
||||
bool UniqueNodeList::nodeInCluster(const RippleAddress& naNodePublic)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mUNLLock);
|
||||
return sClusterNodes.count(naNodePublic) != 0;
|
||||
return sClusterNodes.end() != sClusterNodes.find(naNodePublic);
|
||||
}
|
||||
|
||||
bool UniqueNodeList::nodeInCluster(const RippleAddress& naNodePublic, std::string& name)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mUNLLock);
|
||||
std::map<RippleAddress, std::string>::iterator it = sClusterNodes.find(naNodePublic);
|
||||
if (it == sClusterNodes.end())
|
||||
return false;
|
||||
name = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -88,7 +88,7 @@ private:
|
||||
std::vector<int> viReferrals;
|
||||
} scoreNode;
|
||||
|
||||
std::set<RippleAddress> sClusterNodes;
|
||||
std::map<RippleAddress, std::string> sClusterNodes;
|
||||
|
||||
typedef boost::unordered_map<std::string,int> strIndex;
|
||||
typedef std::pair<std::string,int> ipPort;
|
||||
@@ -155,6 +155,7 @@ public:
|
||||
|
||||
bool nodeInUNL(const RippleAddress& naNodePublic);
|
||||
bool nodeInCluster(const RippleAddress& naNodePublic);
|
||||
bool nodeInCluster(const RippleAddress& naNodePublic, std::string& name);
|
||||
|
||||
void nodeBootstrap();
|
||||
bool nodeLoad(boost::filesystem::path pConfig);
|
||||
|
||||
@@ -300,8 +300,8 @@ void ValidationCollection::condWrite()
|
||||
void ValidationCollection::doWrite()
|
||||
{
|
||||
LoadEvent::autoptr event(theApp->getJobQueue().getLoadEventAP(jtDISK));
|
||||
static boost::format insVal("INSERT INTO LedgerValidations "
|
||||
"(LedgerHash,NodePubKey,Flags,SignTime,Signature) VALUES ('%s','%s','%u','%u',%s);");
|
||||
static boost::format insVal("INSERT INTO Validations "
|
||||
"(LedgerHash,NodePubKey,SignTime,RawData) VALUES ('%s','%s','%u',%s);");
|
||||
|
||||
boost::mutex::scoped_lock sl(mValidationLock);
|
||||
assert(mWriting);
|
||||
@@ -314,11 +314,16 @@ void ValidationCollection::doWrite()
|
||||
Database *db = theApp->getLedgerDB()->getDB();
|
||||
ScopedLock dbl(theApp->getLedgerDB()->getDBLock());
|
||||
|
||||
Serializer s(1024);
|
||||
db->executeSQL("BEGIN TRANSACTION;");
|
||||
BOOST_FOREACH(const SerializedValidation::pointer& it, vector)
|
||||
{
|
||||
s.erase();
|
||||
it->add(s);
|
||||
db->executeSQL(boost::str(insVal % it->getLedgerHash().GetHex()
|
||||
% it->getSignerPublic().humanNodePublic() % it->getFlags() % it->getSignTime()
|
||||
% sqlEscape(it->getSignature())));
|
||||
% it->getSignerPublic().humanNodePublic() % it->getSignTime()
|
||||
% sqlEscape(s.peekData())));
|
||||
}
|
||||
db->executeSQL("END TRANSACTION;");
|
||||
}
|
||||
sl.lock();
|
||||
|
||||
Reference in New Issue
Block a user