Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/bdb.cpp
Show First 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
BerkeleyEnvironment::~BerkeleyEnvironment() { | BerkeleyEnvironment::~BerkeleyEnvironment() { | ||||
LOCK(cs_db); | LOCK(cs_db); | ||||
g_dbenvs.erase(strPath); | g_dbenvs.erase(strPath); | ||||
Close(); | Close(); | ||||
} | } | ||||
bool BerkeleyEnvironment::Open(bool retry) { | bool BerkeleyEnvironment::Open(bilingual_str &err) { | ||||
if (fDbEnvInit) { | if (fDbEnvInit) { | ||||
return true; | return true; | ||||
} | } | ||||
fs::path pathIn = strPath; | fs::path pathIn = strPath; | ||||
TryCreateDirectories(pathIn); | TryCreateDirectories(pathIn); | ||||
if (!LockDirectory(pathIn, ".walletlock")) { | if (!LockDirectory(pathIn, ".walletlock")) { | ||||
LogPrintf("Cannot obtain a lock on wallet directory %s. Another " | LogPrintf("Cannot obtain a lock on wallet directory %s. Another " | ||||
"instance of bitcoin may be using it.\n", | "instance of bitcoin may be using it.\n", | ||||
strPath); | strPath); | ||||
err = strprintf(_("Error initializing wallet database environment %s!"), | |||||
Directory()); | |||||
return false; | return false; | ||||
} | } | ||||
fs::path pathLogDir = pathIn / "database"; | fs::path pathLogDir = pathIn / "database"; | ||||
TryCreateDirectories(pathLogDir); | TryCreateDirectories(pathLogDir); | ||||
fs::path pathErrorFile = pathIn / "db.log"; | fs::path pathErrorFile = pathIn / "db.log"; | ||||
LogPrintf("BerkeleyEnvironment::Open: LogDir=%s ErrorFile=%s\n", | LogPrintf("BerkeleyEnvironment::Open: LogDir=%s ErrorFile=%s\n", | ||||
pathLogDir.string(), pathErrorFile.string()); | pathLogDir.string(), pathErrorFile.string()); | ||||
Show All 26 Lines | if (ret != 0) { | ||||
ret, DbEnv::strerror(ret)); | ret, DbEnv::strerror(ret)); | ||||
int ret2 = dbenv->close(0); | int ret2 = dbenv->close(0); | ||||
if (ret2 != 0) { | if (ret2 != 0) { | ||||
LogPrintf("BerkeleyEnvironment::Open: Error %d closing failed " | LogPrintf("BerkeleyEnvironment::Open: Error %d closing failed " | ||||
"database environment: %s\n", | "database environment: %s\n", | ||||
ret2, DbEnv::strerror(ret2)); | ret2, DbEnv::strerror(ret2)); | ||||
} | } | ||||
Reset(); | Reset(); | ||||
if (retry) { | err = strprintf(_("Error initializing wallet database environment %s!"), | ||||
// try moving the database env out of the way | Directory()); | ||||
fs::path pathDatabaseBak = | if (ret == DB_RUNRECOVERY) { | ||||
pathIn / strprintf("database.%d.bak", GetTime()); | err += Untranslated(" ") + | ||||
try { | _("This error could occur if this wallet was not shutdown " | ||||
fs::rename(pathLogDir, pathDatabaseBak); | "cleanly and was last loaded using a build with a newer " | ||||
LogPrintf("Moved old %s to %s. Retrying.\n", | "version of Berkeley DB. If so, please use the software " | ||||
pathLogDir.string(), pathDatabaseBak.string()); | "that last loaded this wallet"); | ||||
} catch (const fs::filesystem_error &) { | |||||
// failure is ok (well, not really, but it's not worse than what | |||||
// we started with) | |||||
} | |||||
// try opening it again one more time | |||||
if (!Open(false /* retry */)) { | |||||
// if it still fails, it probably means we can't even create the | |||||
// database env | |||||
return false; | |||||
} | } | ||||
} else { | |||||
return false; | return false; | ||||
} | } | ||||
} | |||||
fDbEnvInit = true; | fDbEnvInit = true; | ||||
fMockDb = false; | fMockDb = false; | ||||
return true; | return true; | ||||
} | } | ||||
//! Construct an in-memory mock Berkeley environment for testing | //! Construct an in-memory mock Berkeley environment for testing | ||||
BerkeleyEnvironment::BerkeleyEnvironment() { | BerkeleyEnvironment::BerkeleyEnvironment() { | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
bool BerkeleyDatabase::Verify(bilingual_str &errorStr) { | bool BerkeleyDatabase::Verify(bilingual_str &errorStr) { | ||||
fs::path walletDir = env->Directory(); | fs::path walletDir = env->Directory(); | ||||
fs::path file_path = walletDir / strFile; | fs::path file_path = walletDir / strFile; | ||||
LogPrintf("Using BerkeleyDB version %s\n", | LogPrintf("Using BerkeleyDB version %s\n", | ||||
DbEnv::version(nullptr, nullptr, nullptr)); | DbEnv::version(nullptr, nullptr, nullptr)); | ||||
LogPrintf("Using wallet %s\n", file_path.string()); | LogPrintf("Using wallet %s\n", file_path.string()); | ||||
if (!env->Open(true /* retry */)) { | if (!env->Open(errorStr)) { | ||||
errorStr = strprintf( | |||||
_("Error initializing wallet database environment %s!"), walletDir); | |||||
return false; | return false; | ||||
} | } | ||||
if (fs::exists(file_path)) { | if (fs::exists(file_path)) { | ||||
if (!env->Verify(strFile)) { | if (!env->Verify(strFile)) { | ||||
errorStr = | errorStr = | ||||
strprintf(_("%s corrupt. Try using the wallet tool " | strprintf(_("%s corrupt. Try using the wallet tool " | ||||
"bitcoin-wallet to salvage or restoring a backup."), | "bitcoin-wallet to salvage or restoring a backup."), | ||||
Show All 28 Lines | BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase &database, const char *pszMode, | ||||
bool fCreate = strchr(pszMode, 'c') != nullptr; | bool fCreate = strchr(pszMode, 'c') != nullptr; | ||||
unsigned int nFlags = DB_THREAD; | unsigned int nFlags = DB_THREAD; | ||||
if (fCreate) { | if (fCreate) { | ||||
nFlags |= DB_CREATE; | nFlags |= DB_CREATE; | ||||
} | } | ||||
{ | { | ||||
LOCK(cs_db); | LOCK(cs_db); | ||||
if (!env->Open(false /* retry */)) { | bilingual_str open_err; | ||||
if (!env->Open(open_err)) { | |||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"BerkeleyBatch: Failed to open database environment."); | "BerkeleyBatch: Failed to open database environment."); | ||||
} | } | ||||
pdb = database.m_db.get(); | pdb = database.m_db.get(); | ||||
if (pdb == nullptr) { | if (pdb == nullptr) { | ||||
int ret; | int ret; | ||||
std::unique_ptr<Db> pdb_temp = | std::unique_ptr<Db> pdb_temp = | ||||
std::make_unique<Db>(env->dbenv.get(), 0); | std::make_unique<Db>(env->dbenv.get(), 0); | ||||
bool fMockDb = env->IsMock(); | bool fMockDb = env->IsMock(); | ||||
if (fMockDb) { | if (fMockDb) { | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | void BerkeleyEnvironment::ReloadDbEnv() { | ||||
// Close the individual Db's | // Close the individual Db's | ||||
for (const std::string &filename : filenames) { | for (const std::string &filename : filenames) { | ||||
CloseDb(filename); | CloseDb(filename); | ||||
} | } | ||||
// Reset the environment | // Reset the environment | ||||
// This will flush and close the environment | // This will flush and close the environment | ||||
Flush(true); | Flush(true); | ||||
Reset(); | Reset(); | ||||
Open(true); | bilingual_str open_err; | ||||
Open(open_err); | |||||
} | } | ||||
bool BerkeleyDatabase::Rewrite(const char *pszSkip) { | bool BerkeleyDatabase::Rewrite(const char *pszSkip) { | ||||
if (IsDummy()) { | if (IsDummy()) { | ||||
return true; | return true; | ||||
} | } | ||||
while (true) { | while (true) { | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 393 Lines • Show Last 20 Lines |