Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gui, util: Enhance verify checkpoints fail handling; use RegistryBookmarks for DB passivation #2758

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions src/gridcoin/beacon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1391,21 +1391,6 @@ BeaconRegistry::BeaconDB &BeaconRegistry::GetBeaconDB()
return m_beacon_db;
}

// This is static and called by the scheduler.
void BeaconRegistry::RunDBPassivation()
{
TRY_LOCK(cs_main, locked_main);

if (!locked_main)
{
return;
}

BeaconRegistry& beacons = GetBeaconRegistry();

beacons.PassivateDB();
}

template<> const std::string BeaconRegistry::BeaconDB::KeyType()
{
return std::string("beacon");
Expand Down
7 changes: 1 addition & 6 deletions src/gridcoin/beacon.h
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ class BeaconRegistry : public IContractHandler
//!
//! \return The number of elements passivated.
//!
uint64_t PassivateDB();
uint64_t PassivateDB() override;

//!
//! \brief This function walks the linked beacon entries back (using the m_previous_hash member) from a provided
Expand All @@ -795,11 +795,6 @@ class BeaconRegistry : public IContractHandler
//!
bool SetNeedsIsContractCorrection(bool flag);

//!
//! \brief A static function that is called by the scheduler to run the beacon database passivation.
//!
static void RunDBPassivation();

//!
//! \brief Specializes the template RegistryDB for the ScraperEntry class
//!
Expand Down
15 changes: 15 additions & 0 deletions src/gridcoin/contract/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef GRIDCOIN_CONTRACT_HANDLER_H
#define GRIDCOIN_CONTRACT_HANDLER_H

#include <cstdint>
#include <string>

class CBlockIndex;
Expand Down Expand Up @@ -153,6 +154,20 @@ struct IContractHandler
//! \param height
//!
virtual void SetDBHeight(int& height);

//!
//! \brief Passivates the elements in the underlying db, which means remove from memory elements in the
//! historical map that are not referenced by any of the in memory maps. The backing store of
//! the element removed from memory is retained and will be transparently restored if find()
//! is called on the hash key for the element.
//!
//! \return The number of elements passivated.
//!
virtual uint64_t PassivateDB()
{
// The default method here does nothing.
return uint64_t {0};
};
};

} // namespace GRC
Expand Down
78 changes: 52 additions & 26 deletions src/gridcoin/gridcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extern bool fExplorer;
extern unsigned int nScraperSleep;
extern unsigned int nActiveBeforeSB;
extern bool fScraperActive;
extern bool fQtActive;

void Scraper(bool bSingleShot = false);
void ScraperSubscriber();
Expand All @@ -40,17 +41,29 @@ namespace {
//!
void ShowChainCorruptedMessage()
{
uiInterface.ThreadSafeMessageBox(
_("WARNING: Blockchain data may be corrupted.\n\n"
"Gridcoin detected bad index entries. This may occur because of an "
"unexpected exit, a power failure, or a late software upgrade.\n\n"
"Please exit Gridcoin, open the data directory, and delete:\n"
" - the blk****.dat files\n"
" - the txleveldb folder\n\n"
"Your wallet will re-download the blockchain. Your balance may "
"appear incorrect until the synchronization finishes.\n" ),
"Gridcoin",
CClientUIInterface::BTN_OK | CClientUIInterface::MODAL);
fResetBlockchainRequest = true;

if (fQtActive) {
uiInterface.ThreadSafeMessageBox(
_("ERROR: Checkpoint mismatch: Blockchain data may be corrupted.\n\n"
"Gridcoin detected bad index entries. This may occur because of a "
"late software upgrade, unexpected exit, or a power failure. "
"Your blockchain data is being reset and your wallet will resync "
"from genesis when you restart. Your balance may appear incorrect "
"until the synchronization finishes."),
"Gridcoin",
CClientUIInterface::BTN_OK | CClientUIInterface::MODAL);
} else {
uiInterface.ThreadSafeMessageBox(
_("ERROR: Checkpoint mismatch: Blockchain data may be corrupted.\n\n"
"Gridcoin detected bad index entries. This may occur because of a "
"late software upgrade, unexpected exit, or a power failure. "
"Please run gridcoinresearchd with the -resetblockchaindata "
"parameter. Your wallet will re-download the blockchain. Your "
"balance may appear incorrect until the synchronization finishes." ),
"Gridcoin",
CClientUIInterface::BTN_OK | CClientUIInterface::MODAL);
}
}

//!
Expand Down Expand Up @@ -361,20 +374,23 @@ void InitializeExplorerFeatures()
//! whether the index contains invalid state caused by an unclean shutdown.
//! This condition was originally detected by an assertion in a routine for
//! stake modifier checksum verification. Because Gridcoin removed modifier
//! checksums and checkpoints, we reinstate that assertion here as a formal
//! inspection.
//! checksums, we reinstate that assertion here as a formal inspection done
//! at initialization before the VerifyCheckpoints.
//!
//! This function checks that no block index entries contain a null pointer
//! to a previous block. The symptom may indicate a deeper problem that can
//! be resolved by tuning disk synchronization in LevelDB. Until then, this
//! heuristic has proven itself to be effective for identifying a corrupted
//! database.
//! database. This type of error has not been seen in the wild in several
//! years as of Gridcoin 5.4.7.0, but is retained for thoroughness.
//!
void CheckBlockIndexJob()
bool CheckBlockIndex()
{
LogPrintf("Gridcoin: checking block index...");
uiInterface.InitMessage(_("Checking block index..."));

bool corrupted = false;
// Block index integrity status
bool status = true;

if (pindexGenesisBlock) {
LOCK(cs_main);
Expand All @@ -383,18 +399,20 @@ void CheckBlockIndexJob()
const CBlockIndex* const pindex = index_pair.second;

if (!pindex || !(pindex->pprev || pindex == pindexGenesisBlock)) {
corrupted = true;
status = false;
break;
}
}
}

if (!corrupted) {
if (status) {
LogPrintf("Gridcoin: block index is clean");
return;
return status;
}

ShowChainCorruptedMessage();

return status;
}

//!
Expand Down Expand Up @@ -466,11 +484,8 @@ void ScheduleRegistriesPassivation(CScheduler& scheduler)
{
// Run registry database passivation every 5 minutes. This is a very thin call most of the time.
// Please see the PassivateDB function and passivate_db.
// TODO: Turn into a loop using extension of RegistryBookmarks
scheduler.scheduleEvery(BeaconRegistry::RunDBPassivation, std::chrono::minutes{5});
scheduler.scheduleEvery(ScraperRegistry::RunDBPassivation, std::chrono::minutes{5});
scheduler.scheduleEvery(ProtocolRegistry::RunDBPassivation, std::chrono::minutes{5});
scheduler.scheduleEvery(Whitelist::RunDBPassivation, std::chrono::minutes{5});

scheduler.scheduleEvery(RunDBPassivation, std::chrono::minutes{5});
}
} // Anonymous namespace

Expand All @@ -490,6 +505,9 @@ bool GRC::Initialize(ThreadHandlerPtr threads, CBlockIndex* pindexBest)
{
LogPrintf("Gridcoin: initializing...");

if (!CheckBlockIndex()) {
return false;
}
if (!VerifyCheckpoints(pindexBest)) {
return false;
}
Expand Down Expand Up @@ -518,8 +536,6 @@ void GRC::CloseResearcherRegistryFile()

void GRC::ScheduleBackgroundJobs(CScheduler& scheduler)
{
scheduler.schedule(CheckBlockIndexJob, std::chrono::system_clock::now());

// Primitive, but this is what the scraper does in the scraper housekeeping
// loop. It checks to see if the logs need to be archived by default every
// 5 mins. Note that passing false to the archive function means that if we
Expand Down Expand Up @@ -589,3 +605,13 @@ skip:;
return true;
}

void GRC::RunDBPassivation()
{
LOCK(cs_main);

for (const auto& contract_type : RegistryBookmarks::CONTRACT_TYPES_WITH_REG_DB) {
Registry& registry = RegistryBookmarks::GetRegistryWithDB(contract_type);

registry.PassivateDB();
}
}
6 changes: 6 additions & 0 deletions src/gridcoin/gridcoin.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ void ScheduleBackgroundJobs(CScheduler& scheduler);
//! \return \c true if no errors occurred.
//!
bool CleanConfig();

//!
//! \brief Function to allow cycling through DB passivation for all contract types backed
//! with registry db.
//!
void RunDBPassivation();
} // namespace GRC

#endif // GRIDCOIN_GRIDCOIN_H
15 changes: 0 additions & 15 deletions src/gridcoin/project.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,21 +541,6 @@ Whitelist::ProjectEntryDB &Whitelist::GetProjectDB()
return m_project_db;
}

// This is static and called by the scheduler.
void Whitelist::RunDBPassivation()
{
TRY_LOCK(cs_main, locked_main);

if (!locked_main)
{
return;
}

Whitelist& project_entries = GetWhitelist();

project_entries.PassivateDB();
}

template<> const std::string Whitelist::ProjectEntryDB::KeyType()
{
return std::string("project");
Expand Down
9 changes: 2 additions & 7 deletions src/gridcoin/project.h
Original file line number Diff line number Diff line change
Expand Up @@ -603,19 +603,14 @@ class Whitelist : public IContractHandler
void ResetInMemoryOnly();

//!
//! \brief Passivates the elements in the scraper db, which means remove from memory elements in the
//! \brief Passivates the elements in the project db, which means remove from memory elements in the
//! historical map that are not referenced by m_projects. The backing store of the element removed
//! from memory is retained and will be transparently restored if find() is called on the hash key
//! for the element.
//!
//! \return The number of elements passivated.
//!
uint64_t PassivateDB();

//!
//! \brief A static function that is called by the scheduler to run the project entry database passivation.
//!
static void RunDBPassivation();
uint64_t PassivateDB() override;

//!
//! \brief Specializes the template RegistryDB for the ScraperEntry class. Note that std::set<ProjectEntry> is not
Expand Down
15 changes: 0 additions & 15 deletions src/gridcoin/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,21 +528,6 @@ ProtocolRegistry::ProtocolEntryDB &ProtocolRegistry::GetProtocolEntryDB()
return m_protocol_db;
}

// This is static and called by the scheduler.
void ProtocolRegistry::RunDBPassivation()
{
TRY_LOCK(cs_main, locked_main);

if (!locked_main)
{
return;
}

ProtocolRegistry& protocol_entries = GetProtocolRegistry();

protocol_entries.PassivateDB();
}

template<> const std::string ProtocolRegistry::ProtocolEntryDB::KeyType()
{
return std::string("protocol");
Expand Down
7 changes: 1 addition & 6 deletions src/gridcoin/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -559,12 +559,7 @@ class ProtocolRegistry : public IContractHandler
//!
//! \return The number of elements passivated.
//!
uint64_t PassivateDB();

//!
//! \brief A static function that is called by the scheduler to run the protocol entry database passivation.
//!
static void RunDBPassivation();
uint64_t PassivateDB() override;

//!
//! \brief Specializes the template RegistryDB for the ProtocolEntry class. Note that std::set<ProtocolEntry>
Expand Down
15 changes: 0 additions & 15 deletions src/gridcoin/scraper/scraper_registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,21 +573,6 @@ ScraperRegistry::ScraperEntryDB &ScraperRegistry::GetScraperDB()
return m_scraper_db;
}

// This is static and called by the scheduler.
void ScraperRegistry::RunDBPassivation()
{
TRY_LOCK(cs_main, locked_main);

if (!locked_main)
{
return;
}

ScraperRegistry& scraper_entries = GetScraperRegistry();

scraper_entries.PassivateDB();
}

template<> const std::string ScraperRegistry::ScraperEntryDB::KeyType()
{
return std::string("scraper");
Expand Down
7 changes: 1 addition & 6 deletions src/gridcoin/scraper/scraper_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -598,12 +598,7 @@ class ScraperRegistry : public IContractHandler
//!
//! \return The number of elements passivated.
//!
uint64_t PassivateDB();

//!
//! \brief A static function that is called by the scheduler to run the scraper entry database passivation.
//!
static void RunDBPassivation();
uint64_t PassivateDB() override;

//!
//! \brief Specializes the template RegistryDB for the ScraperEntry class. Note that std::set<ScraperEntry> is
Expand Down
15 changes: 0 additions & 15 deletions src/gridcoin/sidestake.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1164,21 +1164,6 @@ SideStakeRegistry::SideStakeDB &SideStakeRegistry::GetSideStakeDB()
return m_sidestake_db;
}

// This is static and called by the scheduler.
void SideStakeRegistry::RunDBPassivation()
{
TRY_LOCK(cs_main, locked_main);

if (!locked_main)
{
return;
}

SideStakeRegistry& SideStake_entries = GetSideStakeRegistry();

SideStake_entries.PassivateDB();
}

template<> const std::string SideStakeRegistry::SideStakeDB::KeyType()
{
return std::string("SideStake");
Expand Down
7 changes: 1 addition & 6 deletions src/gridcoin/sidestake.h
Original file line number Diff line number Diff line change
Expand Up @@ -830,19 +830,14 @@ class SideStakeRegistry : public IContractHandler
//!
//! \return The number of elements passivated.
//!
uint64_t PassivateDB();
uint64_t PassivateDB() override;

//!
//! \brief This method parses the config file for local sidestakes. It is based on the original GetSideStakingStatusAndAlloc()
//! that was in miner.cpp prior to the implementation of the SideStake class.
//!
void LoadLocalSideStakesFromConfig();

//!
//! \brief A static function that is called by the scheduler to run the sidestake entry database passivation.
//!
static void RunDBPassivation();

//!
//! \brief Specializes the template RegistryDB for the SideStake class. Note that std::set<MandatorySideStake>
//! is not actually used.
Expand Down
Loading
Loading