Changeset View
Changeset View
Standalone View
Standalone View
src/index/base.cpp
- This file was copied from src/index/txindex.cpp.
// Copyright (c) 2017-2018 The Bitcoin Core developers | // Copyright (c) 2017-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 <config.h> | #include <config.h> | ||||
#include <index/txindex.h> | #include <index/base.h> | ||||
#include <init.h> | #include <init.h> | ||||
#include <tinyformat.h> | #include <tinyformat.h> | ||||
#include <ui_interface.h> | #include <ui_interface.h> | ||||
#include <util.h> | #include <util.h> | ||||
#include <validation.h> | #include <validation.h> | ||||
#include <warnings.h> | #include <warnings.h> | ||||
constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds | constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds | ||||
constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds | constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds | ||||
std::unique_ptr<TxIndex> g_txindex; | |||||
template <typename... Args> | template <typename... Args> | ||||
static void FatalError(const char *fmt, const Args &... args) { | static void FatalError(const char *fmt, const Args &... args) { | ||||
std::string strMessage = tfm::format(fmt, args...); | std::string strMessage = tfm::format(fmt, args...); | ||||
SetMiscWarning(strMessage); | SetMiscWarning(strMessage); | ||||
LogPrintf("*** %s\n", strMessage); | LogPrintf("*** %s\n", strMessage); | ||||
uiInterface.ThreadSafeMessageBox( | uiInterface.ThreadSafeMessageBox( | ||||
"Error: A fatal internal error occurred, see debug.log for details", "", | "Error: A fatal internal error occurred, see debug.log for details", "", | ||||
CClientUIInterface::MSG_ERROR); | CClientUIInterface::MSG_ERROR); | ||||
StartShutdown(); | StartShutdown(); | ||||
} | } | ||||
TxIndex::TxIndex(std::unique_ptr<TxIndexDB> db) : m_db(std::move(db)) {} | |||||
BaseIndex::~BaseIndex() { | BaseIndex::~BaseIndex() { | ||||
Interrupt(); | Interrupt(); | ||||
Stop(); | Stop(); | ||||
} | } | ||||
bool TxIndex::Init() { | |||||
LOCK(cs_main); | |||||
// Attempt to migrate txindex from the old database to the new one. Even if | |||||
// chain_tip is null, the node could be reindexing and we still want to | |||||
// delete txindex records in the old database. | |||||
if (!m_db->MigrateData(*pblocktree, chainActive.GetLocator())) { | |||||
return false; | |||||
} | |||||
return BaseIndex::Init(); | |||||
} | |||||
bool BaseIndex::Init() { | bool BaseIndex::Init() { | ||||
CBlockLocator locator; | CBlockLocator locator; | ||||
if (!GetDB().ReadBestBlock(locator)) { | if (!GetDB().ReadBestBlock(locator)) { | ||||
locator.SetNull(); | locator.SetNull(); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
m_best_block_index = FindForkInGlobalIndex(chainActive, locator); | m_best_block_index = FindForkInGlobalIndex(chainActive, locator); | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | void BaseIndex::ThreadSync() { | ||||
if (pindex) { | if (pindex) { | ||||
LogPrintf("%s is enabled at height %d\n", GetName(), pindex->nHeight); | LogPrintf("%s is enabled at height %d\n", GetName(), pindex->nHeight); | ||||
} else { | } else { | ||||
LogPrintf("%s is enabled\n", GetName()); | LogPrintf("%s is enabled\n", GetName()); | ||||
} | } | ||||
} | } | ||||
bool TxIndex::WriteBlock(const CBlock &block, const CBlockIndex *pindex) { | |||||
CDiskTxPos pos(pindex->GetBlockPos(), | |||||
GetSizeOfCompactSize(block.vtx.size())); | |||||
std::vector<std::pair<uint256, CDiskTxPos>> vPos; | |||||
vPos.reserve(block.vtx.size()); | |||||
for (const auto &tx : block.vtx) { | |||||
vPos.emplace_back(tx->GetHash(), pos); | |||||
pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION); | |||||
} | |||||
return m_db->WriteTxs(vPos); | |||||
} | |||||
BaseIndexDB &TxIndex::GetDB() const { | |||||
return *m_db; | |||||
} | |||||
bool BaseIndex::WriteBestBlock(const CBlockIndex *block_index) { | bool BaseIndex::WriteBestBlock(const CBlockIndex *block_index) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (!GetDB().WriteBestBlock(chainActive.GetLocator(block_index))) { | if (!GetDB().WriteBestBlock(chainActive.GetLocator(block_index))) { | ||||
return error("%s: Failed to write locator to disk", __func__); | return error("%s: Failed to write locator to disk", __func__); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | bool BaseIndex::BlockUntilSyncedToCurrentChain() { | ||||
} | } | ||||
LogPrintf("%s: %s is catching up on block notifications\n", __func__, | LogPrintf("%s: %s is catching up on block notifications\n", __func__, | ||||
GetName()); | GetName()); | ||||
SyncWithValidationInterfaceQueue(); | SyncWithValidationInterfaceQueue(); | ||||
return true; | return true; | ||||
} | } | ||||
bool TxIndex::FindTx(const uint256 &tx_hash, uint256 &block_hash, | |||||
CTransactionRef &tx) const { | |||||
CDiskTxPos postx; | |||||
if (!m_db->ReadTxPos(tx_hash, postx)) { | |||||
return false; | |||||
} | |||||
CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); | |||||
if (file.IsNull()) { | |||||
return error("%s: OpenBlockFile failed", __func__); | |||||
} | |||||
CBlockHeader header; | |||||
try { | |||||
file >> header; | |||||
fseek(file.Get(), postx.nTxOffset, SEEK_CUR); | |||||
file >> tx; | |||||
} catch (const std::exception &e) { | |||||
return error("%s: Deserialize or I/O error - %s", __func__, e.what()); | |||||
} | |||||
if (tx->GetHash() != tx_hash) { | |||||
return error("%s: txid mismatch", __func__); | |||||
} | |||||
block_hash = header.GetHash(); | |||||
return true; | |||||
} | |||||
void BaseIndex::Interrupt() { | void BaseIndex::Interrupt() { | ||||
m_interrupt(); | m_interrupt(); | ||||
} | } | ||||
void BaseIndex::Start() { | void BaseIndex::Start() { | ||||
// Need to register this ValidationInterface before running Init(), so that | // Need to register this ValidationInterface before running Init(), so that | ||||
// callbacks are not missed if Init sets m_synced to true. | // callbacks are not missed if Init sets m_synced to true. | ||||
RegisterValidationInterface(this); | RegisterValidationInterface(this); | ||||
Show All 16 Lines |