Changeset View
Changeset View
Standalone View
Standalone View
src/txdb.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2018 The Bitcoin Core developers | // Copyright (c) 2009-2018 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <txdb.h> | #include <txdb.h> | ||||
#include <chain.h> | #include <chain.h> | ||||
#include <chainparams.h> | #include <chainparams.h> | ||||
#include <hash.h> | #include <hash.h> | ||||
#include <pow.h> | #include <pow.h> | ||||
#include <random.h> | #include <random.h> | ||||
#include <shutdown.h> | #include <shutdown.h> | ||||
#include <ui_interface.h> | #include <ui_interface.h> | ||||
#include <uint256.h> | |||||
#include <util/system.h> | #include <util/system.h> | ||||
#include <boost/thread.hpp> // boost::this_thread::interruption_point() (mingw) | #include <boost/thread.hpp> // boost::this_thread::interruption_point() (mingw) | ||||
#include <cstdint> | #include <cstdint> | ||||
static const char DB_COIN = 'C'; | static const char DB_COIN = 'C'; | ||||
static const char DB_COINS = 'c'; | static const char DB_COINS = 'c'; | ||||
Show All 37 Lines | |||||
bool CCoinsViewDB::GetCoin(const COutPoint &outpoint, Coin &coin) const { | bool CCoinsViewDB::GetCoin(const COutPoint &outpoint, Coin &coin) const { | ||||
return db.Read(CoinEntry(&outpoint), coin); | return db.Read(CoinEntry(&outpoint), coin); | ||||
} | } | ||||
bool CCoinsViewDB::HaveCoin(const COutPoint &outpoint) const { | bool CCoinsViewDB::HaveCoin(const COutPoint &outpoint) const { | ||||
return db.Exists(CoinEntry(&outpoint)); | return db.Exists(CoinEntry(&outpoint)); | ||||
} | } | ||||
uint256 CCoinsViewDB::GetBestBlock() const { | BlockHash CCoinsViewDB::GetBestBlock() const { | ||||
uint256 hashBestChain; | BlockHash hashBestChain; | ||||
if (!db.Read(DB_BEST_BLOCK, hashBestChain)) { | if (!db.Read(DB_BEST_BLOCK, hashBestChain)) { | ||||
return uint256(); | return BlockHash(); | ||||
} | } | ||||
return hashBestChain; | return hashBestChain; | ||||
} | } | ||||
std::vector<uint256> CCoinsViewDB::GetHeadBlocks() const { | std::vector<BlockHash> CCoinsViewDB::GetHeadBlocks() const { | ||||
std::vector<uint256> vhashHeadBlocks; | std::vector<BlockHash> vhashHeadBlocks; | ||||
if (!db.Read(DB_HEAD_BLOCKS, vhashHeadBlocks)) { | if (!db.Read(DB_HEAD_BLOCKS, vhashHeadBlocks)) { | ||||
return std::vector<uint256>(); | return std::vector<BlockHash>(); | ||||
} | } | ||||
return vhashHeadBlocks; | return vhashHeadBlocks; | ||||
} | } | ||||
bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { | bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const BlockHash &hashBlock) { | ||||
CDBBatch batch(db); | CDBBatch batch(db); | ||||
size_t count = 0; | size_t count = 0; | ||||
size_t changed = 0; | size_t changed = 0; | ||||
size_t batch_size = | size_t batch_size = | ||||
(size_t)gArgs.GetArg("-dbbatchsize", nDefaultDbBatchSize); | (size_t)gArgs.GetArg("-dbbatchsize", nDefaultDbBatchSize); | ||||
int crash_simulate = gArgs.GetArg("-dbcrashratio", 0); | int crash_simulate = gArgs.GetArg("-dbcrashratio", 0); | ||||
assert(!hashBlock.IsNull()); | assert(!hashBlock.IsNull()); | ||||
uint256 old_tip = GetBestBlock(); | BlockHash old_tip = GetBestBlock(); | ||||
if (old_tip.IsNull()) { | if (old_tip.IsNull()) { | ||||
// We may be in the middle of replaying. | // We may be in the middle of replaying. | ||||
std::vector<uint256> old_heads = GetHeadBlocks(); | std::vector<BlockHash> old_heads = GetHeadBlocks(); | ||||
if (old_heads.size() == 2) { | if (old_heads.size() == 2) { | ||||
assert(old_heads[0] == hashBlock); | assert(old_heads[0] == hashBlock); | ||||
old_tip = old_heads[1]; | old_tip = old_heads[1]; | ||||
} | } | ||||
} | } | ||||
// In the first batch, mark the database as being in the middle of a | // In the first batch, mark the database as being in the middle of a | ||||
// transition from old_tip to hashBlock. | // transition from old_tip to hashBlock. | ||||
// A vector is used for future extensibility, as we may want to support | // A vector is used for future extensibility, as we may want to support | ||||
// interrupting after partial writes from multiple independent reorgs. | // interrupting after partial writes from multiple independent reorgs. | ||||
batch.Erase(DB_BEST_BLOCK); | batch.Erase(DB_BEST_BLOCK); | ||||
batch.Write(DB_HEAD_BLOCKS, std::vector<uint256>{hashBlock, old_tip}); | batch.Write(DB_HEAD_BLOCKS, std::vector<BlockHash>{hashBlock, old_tip}); | ||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { | for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { | ||||
if (it->second.flags & CCoinsCacheEntry::DIRTY) { | if (it->second.flags & CCoinsCacheEntry::DIRTY) { | ||||
CoinEntry entry(&it->first); | CoinEntry entry(&it->first); | ||||
if (it->second.coin.IsSpent()) { | if (it->second.coin.IsSpent()) { | ||||
batch.Erase(entry); | batch.Erase(entry); | ||||
} else { | } else { | ||||
batch.Write(entry, it->second.coin); | batch.Write(entry, it->second.coin); | ||||
▲ Show 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | if (!Read(std::make_pair(DB_FLAG, name), ch)) { | ||||
return false; | return false; | ||||
} | } | ||||
fValue = ch == '1'; | fValue = ch == '1'; | ||||
return true; | return true; | ||||
} | } | ||||
bool CBlockTreeDB::LoadBlockIndexGuts( | bool CBlockTreeDB::LoadBlockIndexGuts( | ||||
const Consensus::Params ¶ms, | const Consensus::Params ¶ms, | ||||
std::function<CBlockIndex *(const uint256 &)> insertBlockIndex) { | std::function<CBlockIndex *(const BlockHash &)> insertBlockIndex) { | ||||
std::unique_ptr<CDBIterator> pcursor(NewIterator()); | std::unique_ptr<CDBIterator> pcursor(NewIterator()); | ||||
pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256())); | pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256())); | ||||
// Load mapBlockIndex | // Load mapBlockIndex | ||||
while (pcursor->Valid()) { | while (pcursor->Valid()) { | ||||
boost::this_thread::interruption_point(); | boost::this_thread::interruption_point(); | ||||
▲ Show 20 Lines • Show All 169 Lines • Show Last 20 Lines |