diff --git a/src/init.cpp b/src/init.cpp index 9bd5e6616..1163f756e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1087,8 +1087,8 @@ static const int64_t g_nMinCoinCacheMB = 256; // never thrash below this working // Scheduled task: nudge nCoinCacheUsage toward "use all RAM except the reserve". If free RAM is below // the reserve we shrink the target (the next per-block flush releases the excess); if there is spare -// RAM we grow it back toward the startup ceiling. Lock-free: it only reads system memory and writes -// the aligned size_t threshold that the flush path reads. +// RAM we grow it back toward the startup ceiling. nCoinCacheUsage is std::atomic, so this +// cross-thread write (vs the cs_main-held reads in FlushStateToDisk/VerifyDB) is well-defined, no lock needed. static void AdjustCoinCacheForMemoryPressure() { if (g_nMaxCoinCacheUsage == 0) @@ -2072,7 +2072,25 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); pcoinsTip = new CCoinsViewCache(pcoinscatcher); - pnotarizations = new NotarizationDB(100*1024*1024, false, fReindex); + try { + pnotarizations = new NotarizationDB(100*1024*1024, false, fReindex); + } catch (const std::exception& e) { + // The notarizations (dPoW) DB is non-essential and node-regenerable. It has been seen to + // snapshot/flush torn (0-byte log -> leveldb "Database I/O error" on reopen), which + // previously aborted startup with a spurious "Error opening block database" and forced a + // full resync. Wipe and recreate it instead of failing hard. + LogPrintf("%s: notarizations DB failed to open (%s); moving aside and regenerating (non-fatal)\n", __FUNCTION__, e.what()); + // Move (do NOT delete) the old DB aside, so a transient open failure (fd + // exhaustion, disk full, permissions) cannot permanently destroy notarization + // history. If the recreate below also fails it propagates as fatal and the old + // data survives in notarizations.corrupt for recovery. + { + boost::filesystem::path ndir = GetDataDir() / "notarizations"; + boost::filesystem::remove_all(ndir.string() + ".corrupt"); + boost::filesystem::rename(ndir, ndir.string() + ".corrupt"); + } + pnotarizations = new NotarizationDB(100*1024*1024, false, true); + } if (fReindex) {