From 5fa4bad9b503b421f5eae3051b717706f11313a3 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Thu, 26 Jul 2012 04:07:37 -0700 Subject: [PATCH] Switch to the new LedgerEntrySet code. This provides more sophisticated checkpointing and rewinding. --- src/LedgerEntrySet.cpp | 17 ++++++- src/LedgerEntrySet.h | 1 + src/TransactionEngine.cpp | 100 +++++++++----------------------------- src/TransactionEngine.h | 18 +------ 4 files changed, 41 insertions(+), 95 deletions(-) diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index b07c9ec0ee..803d244b28 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -64,7 +64,7 @@ void LedgerEntrySet::entryCreate(SLE::pointer sle) if (it == mEntries.end()) mEntries.insert(std::make_pair(sle->getIndex(), LedgerEntrySetEntry(sle, taaDELETE, mSeq))); else if (it->second.mAction == taaDELETE) - throw std::runtime_error("Create after delete"); + throw std::runtime_error("Create after delete"); // We could make this a modify else if (it->second.mAction == taaMODIFY) throw std::runtime_error("Create after modify"); else @@ -89,3 +89,18 @@ void LedgerEntrySet::entryModify(SLE::pointer sle) it->second.mAction = (it->second.mAction == taaCREATE) ? taaCREATE : taaDELETE; } } + +void LedgerEntrySet::entryDelete(SLE::pointer sle) +{ + boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); + if (it == mEntries.end()) + mEntries.insert(std::make_pair(sle->getIndex(), LedgerEntrySetEntry(sle, taaDELETE, mSeq))); + else if (it->second.mAction == taaCREATE) // We support delete after create + mEntries.erase(it); + else + { + it->second.mSeq = mSeq; + it->second.mEntry = sle; + it->second.mAction = taaDELETE; + } +} diff --git a/src/LedgerEntrySet.h b/src/LedgerEntrySet.h index 04ec8d70dd..8b3686568c 100644 --- a/src/LedgerEntrySet.h +++ b/src/LedgerEntrySet.h @@ -44,6 +44,7 @@ public: int getSeq() const { return mSeq; } void bumpSeq() { ++mSeq; } + void clear() { mEntries.empty(); mSeq = 0; } // basic entry functions SLE::pointer getEntry(const uint256& index, LedgerEntryAction&); diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 72b852f23a..ee25d91d0b 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -699,26 +699,16 @@ SLE::pointer TransactionEngine::entryCache(LedgerEntryType letType, const uint25 if (!uIndex.isZero()) { - entryMap::const_iterator it = mEntries.find(uIndex); - - switch (it == mEntries.end() ? taaNONE : it->second.second) + LedgerEntryAction action; + sleEntry = mNodes.getEntry(uIndex, action); + if (!sleEntry) { - case taaNONE: - sleEntry = mLedger->getSLE(uIndex); - if (sleEntry) - mEntries[uIndex] = std::make_pair(sleEntry, taaCACHED); // Add to cache. - break; - - case taaCREATE: - case taaCACHED: - case taaMODIFY: - sleEntry = it->second.first; // Get from cache. - break; - - case taaDELETE: - assert(false); // Unexpected case. - break; + sleEntry = mLedger->getSLE(uIndex); + if (sleEntry) + mNodes.entryCache(sleEntry); } + else if(action == taaDELETE) + assert(false); } return sleEntry; @@ -729,10 +719,8 @@ SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint2 assert(!uIndex.isZero()); SLE::pointer sleNew = boost::make_shared(letType); - sleNew->setIndex(uIndex); - - mEntries[uIndex] = std::make_pair(sleNew, taaCREATE); + mNodes.entryCreate(sleNew); return sleNew; } @@ -740,60 +728,23 @@ SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint2 void TransactionEngine::entryDelete(SLE::pointer sleEntry) { - assert(sleEntry); - const uint256& uIndex = sleEntry->getIndex(); - entryMap::const_iterator it = mEntries.find(uIndex); - - switch (it == mEntries.end() ? taaNONE : it->second.second) - { - case taaCREATE: - assert(false); // Unexpected case. - break; - - case taaCACHED: - case taaMODIFY: - case taaNONE: - mEntries[uIndex] = std::make_pair(sleEntry, taaDELETE); // Upgrade. - break; - - case taaDELETE: - nothing(); // No change. - break; - } + mNodes.entryDelete(sleEntry); } void TransactionEngine::entryModify(SLE::pointer sleEntry) { - assert(sleEntry); - const uint256& uIndex = sleEntry->getIndex(); - entryMap::const_iterator it = mEntries.find(uIndex); - - switch (it == mEntries.end() ? taaNONE : it->second.second) - { - case taaDELETE: - assert(false); // Unexpected case. - break; - - case taaCACHED: - case taaNONE: - mEntries[uIndex] = std::make_pair(sleEntry, taaMODIFY); // Upgrade. - break; - - case taaCREATE: - case taaMODIFY: - nothing(); // No change. - break; - } + mNodes.entryModify(sleEntry); } void TransactionEngine::txnWrite() { // Write back the account states and add the transaction to the ledger - BOOST_FOREACH(entryMap_value_type it, mEntries) + for (boost::unordered_map::iterator it = mNodes.begin(), end = mNodes.end(); + it != end; ++it) { - const SLE::pointer& sleEntry = it.second.first; + const SLE::pointer& sleEntry = it->second.mEntry; - switch (it.second.second) + switch (it->second.mAction) { case taaNONE: assert(false); @@ -824,7 +775,7 @@ void TransactionEngine::txnWrite() { Log(lsINFO) << "applyTransaction: taaDELETE: " << sleEntry->getText(); - if (!mLedger->peekAccountStateMap()->delItem(it.first)) + if (!mLedger->peekAccountStateMap()->delItem(it->first)) assert(false); } break; @@ -836,17 +787,7 @@ void TransactionEngine::txnWrite() // actions can be applied to the ledger. void TransactionEngine::entryReset(const SerializedTransaction& txn) { - mEntries.clear(); // Lose old SLE modifications. - mTxnAccount = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(mTxnAccountID)); // Get new SLE. - - entryModify(mTxnAccount); - - STAmount saPaid = txn.getTransactionFee(); - STAmount saSrcBalance = mTxnAccount->getIValueFieldAmount(sfBalance); - - mTxnAccount->setIFieldAmount(sfBalance, saSrcBalance - saPaid); - - // XXX Bump sequence too. + mNodes.setTo(mOrigNodes); } TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn, @@ -855,6 +796,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran Log(lsTRACE) << "applyTransaction>"; assert(mLedger); mLedgerParentCloseTime = mLedger->getParentCloseTimeNC(); + mNodes.clear(); #ifdef DEBUG if (1) @@ -1017,7 +959,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran bHaveAuthKey = mTxnAccount->getIFieldPresent(sfAuthorizedKey); } - // Check if account cliamed. + // Check if account claimed. if (terSUCCESS == terResult) { switch (txn.getTxnType()) @@ -1168,6 +1110,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran if (terSUCCESS == terResult) { entryModify(mTxnAccount); + mOrigNodes = mNodes.duplicate(); switch (txn.getTxnType()) { @@ -1251,7 +1194,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran } mTxnAccount = SLE::pointer(); - mEntries.clear(); + mNodes.clear(); + mOrigNodes.clear(); mUnfunded.clear(); return terResult; diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index a02d5009f5..509e52c6fd 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -7,6 +7,7 @@ #include "Ledger.h" #include "SerializedTransaction.h" #include "SerializedLedger.h" +#include "LedgerEntrySet.h" // A TransactionEngine applies serialized transactions to a ledger // It can also, verify signatures, verify fees, and give rejection reasons @@ -97,17 +98,6 @@ enum TransactionEngineParams tepMETADATA = 5, // put metadata in tree, not transaction }; -enum TransactionAccountAction -{ - taaNONE, - taaCACHED, // Unmodified. - taaMODIFY, // Modifed, must have previously been taaCACHED. - taaDELETE, // Delete, must have previously been taaDELETE or taaMODIFY. - taaCREATE, // Newly created. -}; - -typedef std::pair AffectedAccount; - // Hold a path state under incremental application. class PathState { @@ -129,10 +119,7 @@ public: class TransactionEngine { private: - typedef boost::unordered_map > entryMap; - typedef entryMap::iterator entryMap_iterator; - typedef entryMap::const_iterator entryMap_const_iterator; - typedef entryMap::iterator::value_type entryMap_value_type; + LedgerEntrySet mNodes, mOrigNodes; TransactionEngineResult dirAdd( uint64& uNodeDir, // Node of entry. @@ -194,7 +181,6 @@ protected: uint160 mTxnAccountID; SLE::pointer mTxnAccount; - entryMap mEntries; boost::unordered_set mUnfunded; // Indexes that were found unfunded. SLE::pointer entryCreate(LedgerEntryType letType, const uint256& uIndex);