diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2014-10-08 14:57:31 -0700 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2014-10-08 14:58:16 -0700 |
commit | d4a42334d447cad48fb3996cad0fd5c945b75571 (patch) | |
tree | ed1c616af0038cf7fb5a5b95e3c2dc5eddbf5fdc /src/coins.h | |
parent | 97a34c28d568cb8b2171d8dd8eb12ca8afb08a7b (diff) | |
parent | 7c70438dc67547e83953ba0343a071fae304ce65 (diff) |
Merge pull request #4834
7c70438 Get rid of the dummy CCoinsViewCache constructor arg (Pieter Wuille)
ed27e53 Add coins_tests with a large randomized CCoinViewCache test. (Pieter Wuille)
058b08c Do not keep fully spent but unwritten CCoins entries cached. (Pieter Wuille)
c9d1a81 Get rid of CCoinsView's SetCoins and SetBestBlock. (Pieter Wuille)
f28aec0 Use ModifyCoins instead of mutable GetCoins. (Pieter Wuille)
Diffstat (limited to 'src/coins.h')
-rw-r--r-- | src/coins.h | 81 |
1 files changed, 63 insertions, 18 deletions
diff --git a/src/coins.h b/src/coins.h index 2583475323..b8f1e5bcc5 100644 --- a/src/coins.h +++ b/src/coins.h @@ -83,11 +83,26 @@ public: // as new tx version will probably only be introduced at certain heights int nVersion; - // construct a CCoins from a CTransaction, at a given height - CCoins(const CTransaction &tx, int nHeightIn) : fCoinBase(tx.IsCoinBase()), vout(tx.vout), nHeight(nHeightIn), nVersion(tx.nVersion) { + void FromTx(const CTransaction &tx, int nHeightIn) { + fCoinBase = tx.IsCoinBase(); + vout = tx.vout; + nHeight = nHeightIn; + nVersion = tx.nVersion; ClearUnspendable(); } + // construct a CCoins from a CTransaction, at a given height + CCoins(const CTransaction &tx, int nHeightIn) { + FromTx(tx, nHeightIn); + } + + void Clear() { + fCoinBase = false; + std::vector<CTxOut>().swap(vout); + nHeight = 0; + nVersion = 0; + } + // empty constructor CCoins() : fCoinBase(false), vout(0), nHeight(0), nVersion(0) { } @@ -256,7 +271,20 @@ public: } }; -typedef boost::unordered_map<uint256, CCoins, CCoinsKeyHasher> CCoinsMap; +struct CCoinsCacheEntry +{ + CCoins coins; // The actual cached data. + unsigned char flags; + + enum Flags { + DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view. + FRESH = (1 << 1), // The parent view does not have this entry (or it is pruned). + }; + + CCoinsCacheEntry() : coins(), flags(0) {} +}; + +typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap; struct CCoinsStats { @@ -279,9 +307,6 @@ public: // Retrieve the CCoins (unspent transaction outputs) for a given txid virtual bool GetCoins(const uint256 &txid, CCoins &coins) const; - // Modify the CCoins for a given txid - virtual bool SetCoins(const uint256 &txid, const CCoins &coins); - // Just check whether we have data for a given txid. // This may (but cannot always) return true for fully spent transactions virtual bool HaveCoins(const uint256 &txid) const; @@ -289,10 +314,7 @@ public: // Retrieve the block hash whose state this CCoinsView currently represents virtual uint256 GetBestBlock() const; - // Modify the currently active block hash - virtual bool SetBestBlock(const uint256 &hashBlock); - - // Do a bulk modification (multiple SetCoins + one SetBestBlock). + // Do a bulk modification (multiple CCoins changes + BestBlock change). // The passed mapCoins can be modified. virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); @@ -311,22 +333,41 @@ protected: CCoinsView *base; public: - CCoinsViewBacked(CCoinsView &viewIn); + CCoinsViewBacked(CCoinsView *viewIn); bool GetCoins(const uint256 &txid, CCoins &coins) const; - bool SetCoins(const uint256 &txid, const CCoins &coins); bool HaveCoins(const uint256 &txid) const; uint256 GetBestBlock() const; - bool SetBestBlock(const uint256 &hashBlock); void SetBackend(CCoinsView &viewIn); bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); bool GetStats(CCoinsStats &stats) const; }; +class CCoinsViewCache; + +/** A reference to a mutable cache entry. Encapsulating it allows us to run + * cleanup code after the modification is finished, and keeping track of + * concurrent modifications. */ +class CCoinsModifier +{ +private: + CCoinsViewCache& cache; + CCoinsMap::iterator it; + CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_); + +public: + CCoins* operator->() { return &it->second.coins; } + CCoins& operator*() { return it->second.coins; } + ~CCoinsModifier(); + friend class CCoinsViewCache; +}; + /** CCoinsView that adds a memory cache for transactions to another CCoinsView */ class CCoinsViewCache : public CCoinsViewBacked { protected: + /* Whether this cache has an active modifier. */ + bool hasModifier; /* Make mutable so that we can "fill the cache" even from Get-methods declared as "const". */ @@ -334,14 +375,14 @@ protected: mutable CCoinsMap cacheCoins; public: - CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false); + CCoinsViewCache(CCoinsView *baseIn); + ~CCoinsViewCache(); // Standard CCoinsView methods bool GetCoins(const uint256 &txid, CCoins &coins) const; - bool SetCoins(const uint256 &txid, const CCoins &coins); bool HaveCoins(const uint256 &txid) const; uint256 GetBestBlock() const; - bool SetBestBlock(const uint256 &hashBlock); + void SetBestBlock(const uint256 &hashBlock); bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); // Return a pointer to CCoins in the cache, or NULL if not found. This is @@ -349,8 +390,10 @@ public: // allowed while accessing the returned pointer. const CCoins* AccessCoins(const uint256 &txid) const; - // Return a modifiable reference to a CCoins. Check HaveCoins first. - CCoins &GetCoins(const uint256 &txid); + // Return a modifiable reference to a CCoins. If no entry with the given + // txid exists, a new one is created. Simultaneous modifications are not + // allowed. + CCoinsModifier ModifyCoins(const uint256 &txid); // Push the modifications applied to this cache to its base. // Failure to call this method before destruction will cause the changes to be forgotten. @@ -377,6 +420,8 @@ public: const CTxOut &GetOutputFor(const CTxIn& input) const; + friend class CCoinsModifier; + private: CCoinsMap::iterator FetchCoins(const uint256 &txid); CCoinsMap::const_iterator FetchCoins(const uint256 &txid) const; |