aboutsummaryrefslogtreecommitdiff
path: root/src/db.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/db.cpp')
-rw-r--r--src/db.cpp193
1 files changed, 49 insertions, 144 deletions
diff --git a/src/db.cpp b/src/db.cpp
index 94629f3ca..591d4ed47 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -1,19 +1,25 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "db.h"
+
+#include "addrman.h"
+#include "hash.h"
+#include "protocol.h"
#include "util.h"
-#include "main.h"
-#include <boost/version.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/filesystem/fstream.hpp>
+
+#include <stdint.h>
#ifndef WIN32
-#include "sys/stat.h"
+#include <sys/stat.h>
#endif
+#include <boost/filesystem.hpp>
+#include <boost/version.hpp>
+#include <openssl/rand.h>
+
using namespace std;
using namespace boost;
@@ -36,9 +42,9 @@ void CDBEnv::EnvShutdown()
fDbEnvInit = false;
int ret = dbenv.close(0);
if (ret != 0)
- printf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
+ LogPrintf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
if (!fMockDb)
- DbEnv(0).remove(strPath.c_str(), 0);
+ DbEnv(0).remove(path.string().c_str(), 0);
}
CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS)
@@ -57,36 +63,34 @@ void CDBEnv::Close()
EnvShutdown();
}
-bool CDBEnv::Open(const boost::filesystem::path& path)
+bool CDBEnv::Open(const boost::filesystem::path& pathIn)
{
if (fDbEnvInit)
return true;
- if (fShutdown)
- return false;
+ boost::this_thread::interruption_point();
- strPath = path.string();
+ path = pathIn;
filesystem::path pathLogDir = path / "database";
filesystem::create_directory(pathLogDir);
filesystem::path pathErrorFile = path / "db.log";
- printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
+ LogPrintf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());
unsigned int nEnvFlags = 0;
if (GetBoolArg("-privdb", true))
nEnvFlags |= DB_PRIVATE;
- unsigned int nDbCache = GetArg("-dbcache", 25);
dbenv.set_lg_dir(pathLogDir.string().c_str());
- dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1);
- dbenv.set_lg_bsize(1048576);
- dbenv.set_lg_max(10485760);
+ dbenv.set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet
+ dbenv.set_lg_bsize(0x10000);
+ dbenv.set_lg_max(1048576);
dbenv.set_lk_max_locks(40000);
dbenv.set_lk_max_objects(40000);
dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
dbenv.set_flags(DB_AUTO_COMMIT, 1);
dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
- int ret = dbenv.open(strPath.c_str(),
+ int ret = dbenv.open(path.string().c_str(),
DB_CREATE |
DB_INIT_LOCK |
DB_INIT_LOG |
@@ -109,10 +113,9 @@ void CDBEnv::MakeMock()
if (fDbEnvInit)
throw runtime_error("CDBEnv::MakeMock(): already initialized");
- if (fShutdown)
- throw runtime_error("CDBEnv::MakeMock(): during shutdown");
+ boost::this_thread::interruption_point();
- printf("CDBEnv::MakeMock()\n");
+ LogPrint("db", "CDBEnv::MakeMock()\n");
dbenv.set_cachesize(1, 0, 1);
dbenv.set_lg_bsize(10485760*4);
@@ -167,9 +170,18 @@ bool CDBEnv::Salvage(std::string strFile, bool fAggressive,
Db db(&dbenv, 0);
int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
- if (result != 0)
+ if (result == DB_VERIFY_BAD)
{
- printf("ERROR: db salvage failed\n");
+ LogPrintf("Error: Salvage found errors, all data may not be recoverable.\n");
+ if (!fAggressive)
+ {
+ LogPrintf("Error: Rerun with aggressive mode to ignore errors and continue.\n");
+ return false;
+ }
+ }
+ if (result != 0 && result != DB_VERIFY_BAD)
+ {
+ LogPrintf("ERROR: db salvage failed: %d\n",result);
return false;
}
@@ -328,7 +340,7 @@ bool CDBEnv::RemoveDb(const string& strFile)
bool CDB::Rewrite(const string& strFile, const char* pszSkip)
{
- while (!fShutdown)
+ while (true)
{
{
LOCK(bitdb.cs_db);
@@ -340,7 +352,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
bitdb.mapFileUseCount.erase(strFile);
bool fSuccess = true;
- printf("Rewriting %s...\n", strFile.c_str());
+ LogPrintf("Rewriting %s...\n", strFile);
string strFileRes = strFile + ".rewrite";
{ // surround usage of db with extra {}
CDB db(strFile.c_str(), "r");
@@ -354,7 +366,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
0);
if (ret > 0)
{
- printf("Cannot create database file %s\n", strFileRes.c_str());
+ LogPrintf("Cannot create database file %s\n", strFileRes);
fSuccess = false;
}
@@ -410,11 +422,11 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
fSuccess = false;
}
if (!fSuccess)
- printf("Rewriting of %s FAILED!\n", strFileRes.c_str());
+ LogPrintf("Rewriting of %s FAILED!\n", strFileRes);
return fSuccess;
}
}
- Sleep(100);
+ MilliSleep(100);
}
return false;
}
@@ -422,10 +434,10 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
void CDBEnv::Flush(bool fShutdown)
{
- int64 nStart = GetTimeMillis();
+ int64_t nStart = GetTimeMillis();
// Flush log data to the actual data file
// on all files that are not in use
- printf("Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
+ LogPrint("db", "Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
if (!fDbEnvInit)
return;
{
@@ -435,23 +447,23 @@ void CDBEnv::Flush(bool fShutdown)
{
string strFile = (*mi).first;
int nRefCount = (*mi).second;
- printf("%s refcount=%d\n", strFile.c_str(), nRefCount);
+ LogPrint("db", "%s refcount=%d\n", strFile, nRefCount);
if (nRefCount == 0)
{
// Move log data to the dat file
CloseDb(strFile);
- printf("%s checkpoint\n", strFile.c_str());
+ LogPrint("db", "%s checkpoint\n", strFile);
dbenv.txn_checkpoint(0, 0, 0);
- printf("%s detach\n", strFile.c_str());
+ LogPrint("db", "%s detach\n", strFile);
if (!fMockDb)
dbenv.lsn_reset(strFile.c_str(), 0);
- printf("%s closed\n", strFile.c_str());
+ LogPrint("db", "%s closed\n", strFile);
mapFileUseCount.erase(mi++);
}
else
mi++;
}
- printf("DBFlush(%s)%s ended %15"PRI64d"ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart);
+ LogPrint("db", "DBFlush(%s)%s ended %15"PRId64"ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart);
if (fShutdown)
{
char** listp;
@@ -459,117 +471,10 @@ void CDBEnv::Flush(bool fShutdown)
{
dbenv.log_archive(&listp, DB_ARCH_REMOVE);
Close();
+ if (!fMockDb)
+ boost::filesystem::remove_all(path / "database");
}
}
}
}
-
-
-
-
-
-
-
-
-
-
-//
-// CAddrDB
-//
-
-
-CAddrDB::CAddrDB()
-{
- pathAddr = GetDataDir() / "peers.dat";
-}
-
-bool CAddrDB::Write(const CAddrMan& addr)
-{
- // Generate random temporary filename
- unsigned short randv = 0;
- RAND_bytes((unsigned char *)&randv, sizeof(randv));
- std::string tmpfn = strprintf("peers.dat.%04x", randv);
-
- // serialize addresses, checksum data up to that point, then append csum
- CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
- ssPeers << FLATDATA(pchMessageStart);
- ssPeers << addr;
- uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
- ssPeers << hash;
-
- // open temp output file, and associate with CAutoFile
- boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
- FILE *file = fopen(pathTmp.string().c_str(), "wb");
- CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION);
- if (!fileout)
- return error("CAddrman::Write() : open failed");
-
- // Write and commit header, data
- try {
- fileout << ssPeers;
- }
- catch (std::exception &e) {
- return error("CAddrman::Write() : I/O error");
- }
- FileCommit(fileout);
- fileout.fclose();
-
- // replace existing peers.dat, if any, with new peers.dat.XXXX
- if (!RenameOver(pathTmp, pathAddr))
- return error("CAddrman::Write() : Rename-into-place failed");
-
- return true;
-}
-
-bool CAddrDB::Read(CAddrMan& addr)
-{
- // open input file, and associate with CAutoFile
- FILE *file = fopen(pathAddr.string().c_str(), "rb");
- CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION);
- if (!filein)
- return error("CAddrman::Read() : open failed");
-
- // use file size to size memory buffer
- int fileSize = GetFilesize(filein);
- int dataSize = fileSize - sizeof(uint256);
- vector<unsigned char> vchData;
- vchData.resize(dataSize);
- uint256 hashIn;
-
- // read data and checksum from file
- try {
- filein.read((char *)&vchData[0], dataSize);
- filein >> hashIn;
- }
- catch (std::exception &e) {
- return error("CAddrman::Read() 2 : I/O error or stream data corrupted");
- }
- filein.fclose();
-
- CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
-
- // verify stored checksum matches input data
- uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
- if (hashIn != hashTmp)
- return error("CAddrman::Read() : checksum mismatch; data corrupted");
-
- unsigned char pchMsgTmp[4];
- try {
- // de-serialize file header (pchMessageStart magic number) and
- ssPeers >> FLATDATA(pchMsgTmp);
-
- // verify the network matches ours
- if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp)))
- return error("CAddrman::Read() : invalid network magic number");
-
- // de-serialize address data into one CAddrMan object
- ssPeers >> addr;
- }
- catch (std::exception &e) {
- return error("CAddrman::Read() : I/O error or stream data corrupted");
- }
-
- return true;
-}
-