X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fdb.cpp;h=9a904ec2e07a69acf033089886bed2d41067366f;hb=4efbda3f257bd8e635715377d85862d322c57c4b;hp=f2363647aa3fd368c6785e256c9258d1462e153c;hpb=565c4771b6eba0eeb82f8602735100bbcf4b053e;p=novacoin.git diff --git a/src/db.cpp b/src/db.cpp index f236364..9a904ec 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -1,11 +1,12 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2011 The Bitcoin developers +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" #include "db.h" #include "net.h" +#include #include #include @@ -28,6 +29,23 @@ DbEnv dbenv(0); static map mapFileUseCount; static map mapDb; +static void EnvShutdown() +{ + if (!fDbEnvInit) + return; + + fDbEnvInit = false; + try + { + dbenv.close(0); + } + catch (const DbException& e) + { + printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno()); + } + DbEnv(0).remove(GetDataDir().c_str(), 0); +} + class CDBInit { public: @@ -36,11 +54,7 @@ public: } ~CDBInit() { - if (fDbEnvInit) - { - dbenv.close(0); - fDbEnvInit = false; - } + EnvShutdown(); } } instance_of_cdbinit; @@ -118,7 +132,7 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL) { bool fTmp = fReadOnly; fReadOnly = false; - WriteVersion(VERSION); + WriteVersion(CLIENT_VERSION); fReadOnly = fTmp; } @@ -165,6 +179,101 @@ void static CloseDb(const string& strFile) } } +bool CDB::Rewrite(const string& strFile, const char* pszSkip) +{ + while (!fShutdown) + { + CRITICAL_BLOCK(cs_db) + { + if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0) + { + // Flush log data to the dat file + CloseDb(strFile); + dbenv.txn_checkpoint(0, 0, 0); + dbenv.lsn_reset(strFile.c_str(), 0); + mapFileUseCount.erase(strFile); + + bool fSuccess = true; + printf("Rewriting %s...\n", strFile.c_str()); + string strFileRes = strFile + ".rewrite"; + { // surround usage of db with extra {} + CDB db(strFile.c_str(), "r"); + Db* pdbCopy = new Db(&dbenv, 0); + + int ret = pdbCopy->open(NULL, // Txn pointer + strFileRes.c_str(), // Filename + "main", // Logical db name + DB_BTREE, // Database type + DB_CREATE, // Flags + 0); + if (ret > 0) + { + printf("Cannot create database file %s\n", strFileRes.c_str()); + fSuccess = false; + } + + Dbc* pcursor = db.GetCursor(); + if (pcursor) + while (fSuccess) + { + CDataStream ssKey; + CDataStream ssValue; + int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT); + if (ret == DB_NOTFOUND) + { + pcursor->close(); + break; + } + else if (ret != 0) + { + pcursor->close(); + fSuccess = false; + break; + } + if (pszSkip && + strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0) + continue; + if (strncmp(&ssKey[0], "\x07version", 8) == 0) + { + // Update version: + ssValue.clear(); + ssValue << CLIENT_VERSION; + } + Dbt datKey(&ssKey[0], ssKey.size()); + Dbt datValue(&ssValue[0], ssValue.size()); + int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE); + if (ret2 > 0) + fSuccess = false; + } + if (fSuccess) + { + db.Close(); + CloseDb(strFile); + if (pdbCopy->close(0)) + fSuccess = false; + delete pdbCopy; + } + } + if (fSuccess) + { + Db dbA(&dbenv, 0); + if (dbA.remove(strFile.c_str(), NULL, 0)) + fSuccess = false; + Db dbB(&dbenv, 0); + if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) + fSuccess = false; + } + if (!fSuccess) + printf("Rewriting of %s FAILED!\n", strFileRes.c_str()); + return fSuccess; + } + } + Sleep(100); + } + return false; +} + + void DBFlush(bool fShutdown) { // Flush log data to the actual data file @@ -196,9 +305,10 @@ void DBFlush(bool fShutdown) { char** listp; if (mapFileUseCount.empty()) + { dbenv.log_archive(&listp, DB_ARCH_REMOVE); - dbenv.close(0); - fDbEnvInit = false; + EnvShutdown(); + } } } } @@ -520,24 +630,6 @@ bool CAddrDB::LoadAddresses() { CRITICAL_BLOCK(cs_mapAddresses) { - // Load user provided addresses - CAutoFile filein = fopen((GetDataDir() + "/addr.txt").c_str(), "rt"); - if (filein) - { - try - { - char psz[1000]; - while (fgets(psz, sizeof(psz), filein)) - { - CAddress addr(psz, false, NODE_NETWORK); - addr.nTime = 0; // so it won't relay unless successfully connected - if (addr.IsValid()) - AddAddress(addr); - } - } - catch (...) { } - } - // Get cursor Dbc* pcursor = GetCursor(); if (!pcursor) @@ -674,9 +766,10 @@ int CWalletDB::LoadWallet(CWallet* pwallet) pwallet->vchDefaultKey.clear(); int nFileVersion = 0; vector vWalletUpgrade; + bool fIsEncrypted = false; // Modify defaults -#ifndef __WXMSW__ +#ifndef WIN32 // Tray icon sometimes disappears on 9.10 karmic koala 64-bit, leaving no way to access the program fMinimizeToTray = false; fMinimizeOnClose = false; @@ -718,7 +811,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet) ssKey >> hash; CWalletTx& wtx = pwallet->mapWallet[hash]; ssValue >> wtx; - wtx.pwallet = pwallet; + wtx.BindWallet(pwallet); if (wtx.GetHash() != hash) printf("Error in wallet.dat, hash mismatch\n"); @@ -768,13 +861,19 @@ int CWalletDB::LoadWallet(CWallet* pwallet) { CPrivKey pkey; ssValue >> pkey; + key.SetPubKey(vchPubKey); key.SetPrivKey(pkey); + if (key.GetPubKey() != vchPubKey || !key.IsValid()) + return DB_CORRUPT; } else { CWalletKey wkey; ssValue >> wkey; + key.SetPubKey(vchPubKey); key.SetPrivKey(wkey.vchPrivKey); + if (key.GetPubKey() != vchPubKey || !key.IsValid()) + return DB_CORRUPT; } if (!pwallet->LoadKey(key)) return DB_CORRUPT; @@ -799,6 +898,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet) ssValue >> vchPrivKey; if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey)) return DB_CORRUPT; + fIsEncrypted = true; } else if (strType == "defaultkey") { @@ -838,9 +938,18 @@ int CWalletDB::LoadWallet(CWallet* pwallet) { int nMinVersion = 0; ssValue >> nMinVersion; - if (nMinVersion > VERSION) + if (nMinVersion > CLIENT_VERSION) return DB_TOO_NEW; } + else if (strType == "cscript") + { + uint160 hash; + ssKey >> hash; + CScript script; + ssValue >> script; + if (!pwallet->LoadCScript(script)) + return DB_CORRUPT; + } } pcursor->close(); } @@ -859,17 +968,19 @@ int CWalletDB::LoadWallet(CWallet* pwallet) printf("fUseUPnP = %d\n", fUseUPnP); - // Upgrade - if (nFileVersion < VERSION) + // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: + if (fIsEncrypted && (nFileVersion == 40000 || nFileVersion == 50000)) + return DB_NEED_REWRITE; + + if (nFileVersion < CLIENT_VERSION) // Update { // Get rid of old debug.log file in current directory if (nFileVersion <= 105 && !pszSetDataDir[0]) unlink("debug.log"); - WriteVersion(VERSION); + WriteVersion(CLIENT_VERSION); } - return DB_LOAD_OK; } @@ -880,7 +991,7 @@ void ThreadFlushWalletDB(void* parg) if (fOneThread) return; fOneThread = true; - if (mapArgs.count("-noflushwallet")) + if (!GetBoolArg("-flushwallet", true)) return; unsigned int nLastSeen = nWalletDBUpdated; @@ -954,14 +1065,19 @@ bool BackupWallet(const CWallet& wallet, const string& strDest) filesystem::path pathDest(strDest); if (filesystem::is_directory(pathDest)) pathDest = pathDest / wallet.strWalletFile; + + try { #if BOOST_VERSION >= 104000 - filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists); + filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists); #else - filesystem::copy_file(pathSrc, pathDest); + filesystem::copy_file(pathSrc, pathDest); #endif - printf("copied wallet.dat to %s\n", pathDest.string().c_str()); - - return true; + printf("copied wallet.dat to %s\n", pathDest.string().c_str()); + return true; + } catch(const filesystem::filesystem_error &e) { + printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what()); + return false; + } } } Sleep(100);