From d83d8080fdbf36d87ce88e22c6ad51414d0ddddd Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 17 Jul 2012 03:10:05 -0700 Subject: [PATCH] Efficiently save validations. --- src/Application.cpp | 1 + src/DBInit.cpp | 19 +++++----- src/SerializedValidation.cpp | 5 +++ src/SerializedValidation.h | 2 +- src/ValidationCollection.cpp | 72 ++++++++++++++++++++++++++++++++++++ src/ValidationCollection.h | 12 +++++- 6 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 532618bcaf..dd4fd40a26 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -52,6 +52,7 @@ void Application::stop() { mIOService.stop(); mHashedObjectStore.bulkWrite(); + mValidations.flush(); Log(lsINFO) << "Stopped: " << mIOService.stopped(); } diff --git a/src/DBInit.cpp b/src/DBInit.cpp index c9c00ce7a6..245b2c5f78 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -26,7 +26,7 @@ const char *TxnDBInit[] = { );", "CREATE INDEX AcctTxindex ON \ AccountTransactions(Account, LedgerSeq, TransID);", - "CREATE INDEX AcctLgrIndex ON \ + "CREATE INDEX AcctLgrIndex ON \ AccountTransactions(LedgerSeq, Account, TransID);", "END TRANSACTION;" @@ -46,21 +46,22 @@ const char *LedgerDBInit[] = { ClosingTime BIGINT UNSIGNED, \ PrevClosingTime BIGINT UNSIGNED, \ CloseTimeRes BIGINT UNSIGNED, \ - CloseFlags, BIGINT UNSIGNED, \ + CloseFlags BIGINT UNSIGNED, \ AccountSetHash CHARACTER(64), \ TransSetHash CHARACTER(64) \ );", "CREATE INDEX SeqLedger ON Ledgers(LedgerSeq);", -#if 0 - "CREATE TABLE LedgerConfirmations ( \ - LedgerSeq BIGINT UNSIGNED, \ + + "CREATE TABLE LedgerValidations ( \ LedgerHash CHARACTER(64), \ - Hanko CHARACTER(35), \ + NodePubKey CHARACTER(56), \ + Flags BIGINT UNSIGNED, \ + CloseTime BIGINT UNSIGNED, \ Signature BLOB \ );", - "CREATE INDEX LedgerConfByHash ON \ - LedgerConfirmations(LedgerHash)", -#endif + "CREATE INDEX ValidationByHash ON \ + LedgerValidations(LedgerHash);", + "END TRANSACTION;" }; diff --git a/src/SerializedValidation.cpp b/src/SerializedValidation.cpp index f3b6799d6c..a87aa141e5 100644 --- a/src/SerializedValidation.cpp +++ b/src/SerializedValidation.cpp @@ -55,6 +55,11 @@ uint32 SerializedValidation::getCloseTime() const return getValueFieldU32(sfCloseTime); } +uint32 SerializedValidation::getFlags() const +{ + return getValueFieldU32(sfFlags); +} + bool SerializedValidation::isValid() const { return isValid(getSigningHash()); diff --git a/src/SerializedValidation.h b/src/SerializedValidation.h index dc5b7bbf0b..dddd1fdce6 100644 --- a/src/SerializedValidation.h +++ b/src/SerializedValidation.h @@ -26,11 +26,11 @@ public: uint256 getLedgerHash() const; uint32 getCloseTime() const; + uint32 getFlags() const; NewcoinAddress getSignerPublic() const; bool isValid() const; bool isFull() const; bool isTrusted() const { return mTrusted; } - CKey::pointer getSigningKey() const; uint256 getSigningHash() const; bool isValid(const uint256&) const; diff --git a/src/ValidationCollection.cpp b/src/ValidationCollection.cpp index 22bf0deb7f..99d2d5e0a0 100644 --- a/src/ValidationCollection.cpp +++ b/src/ValidationCollection.cpp @@ -30,7 +30,11 @@ bool ValidationCollection::addValidation(SerializedValidation::pointer val) { boost::unordered_map::iterator it = mCurrentValidations.find(node); if ((it == mCurrentValidations.end()) || (val->getCloseTime() >= it->second->getCloseTime())) + { + mStaleValidations.push_back(it->second); mCurrentValidations[node] = val; + condWrite(); + } } } @@ -112,17 +116,85 @@ boost::unordered_map ValidationCollection::getCurrentValidations() { boost::mutex::scoped_lock sl(mValidationLock); boost::unordered_map::iterator it = mCurrentValidations.begin(); + bool anyNew = false; while (it != mCurrentValidations.end()) { if (now > (it->second->getCloseTime() + LEDGER_MAX_INTERVAL)) + { + mStaleValidations.push_back(it->second); it = mCurrentValidations.erase(it); + anyNew = true; + } else { ++ret[it->second->getLedgerHash()]; ++it; } } + if (anyNew) + condWrite(); } return ret; } + +void ValidationCollection::flush() +{ + boost::mutex::scoped_lock sl(mValidationLock); + boost::unordered_map::iterator it = mCurrentValidations.begin(); + bool anyNew = false; + while (it != mCurrentValidations.end()) + { + mStaleValidations.push_back(it->second); + ++it; + anyNew = true; + } + mCurrentValidations.clear(); + if (anyNew) + condWrite(); + while (mWriting) + { + sl.unlock(); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + sl.lock(); + } +} + +void ValidationCollection::condWrite() +{ + if (mWriting) + return; + mWriting = true; + boost::thread(boost::bind(&ValidationCollection::doWrite, this)); + thread.detach(); +} + +void ValidationCollection::doWrite() +{ + static boost::format insVal("INSERT INTO LedgerValidations " + "(LedgerHash,NodePubKey,Flags,CloseTime,Signature) VALUES " + "('%s','%s','%u','%u',%s);"); + + boost::mutex::scoped_lock sl(mValidationLock); + assert(mWriting); + while (!mStaleValidations.empty()) + { + std::vector vector; + mStaleValidations.swap(vector); + sl.unlock(); + + { + ScopedLock dbl(theApp->getLedgerDB()->getDBLock()); + Database *db = theApp->getLedgerDB()->getDB(); + db->executeSQL("BEGIN TRANSACTION;"); + for (std::vector::iterator it = vector.begin(); it != vector.end(); ++it) + db->executeSQL(boost::str(insVal % (*it)->getLedgerHash().GetHex() + % (*it)->getSignerPublic().humanNodePublic() % (*it)->getFlags() % (*it)->getCloseTime() + % db->escape(strCopy((*it)->getSignature())))); + db->executeSQL("END TRANSACTION;"); + } + + sl.lock(); + } + mWriting = false; +} diff --git a/src/ValidationCollection.h b/src/ValidationCollection.h index 5c6feacfea..2b2760ff36 100644 --- a/src/ValidationCollection.h +++ b/src/ValidationCollection.h @@ -1,6 +1,8 @@ #ifndef __VALIDATION_COLLECTION__ #define __VALIDATION_COLLECTION__ +#include + #include #include @@ -12,14 +14,19 @@ typedef boost::unordered_map ValidationS class ValidationCollection { - protected: +protected: boost::mutex mValidationLock; boost::unordered_map mValidations; boost::unordered_map mCurrentValidations; + std::vector mStaleValidations; + bool mWriting; + + void doWrite(); + void condWrite(); public: - ValidationCollection() { ; } + ValidationCollection() : mWriting(false) { ; } bool addValidation(SerializedValidation::pointer); ValidationSet getValidations(const uint256& ledger); @@ -27,6 +34,7 @@ public: int getTrustedValidationCount(const uint256& ledger); int getCurrentValidationCount(uint32 afterTime); boost::unordered_map getCurrentValidations(); + void flush(); }; #endif