10 #include <boost/filesystem.hpp>
11 #include <boost/filesystem/fstream.hpp>
18 using namespace boost;
37 int ret = dbenv.close(0);
39 printf(
"EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
41 DbEnv(0).remove(path.string().c_str(), 0);
65 boost::this_thread::interruption_point();
68 filesystem::path pathLogDir =
path /
"database";
69 filesystem::create_directory(pathLogDir);
70 filesystem::path pathErrorFile =
path /
"db.log";
71 printf(
"dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
73 unsigned int nEnvFlags = 0;
75 nEnvFlags |= DB_PRIVATE;
77 dbenv.set_lg_dir(pathLogDir.string().c_str());
78 dbenv.set_cachesize(0, 0x100000, 1);
79 dbenv.set_lg_bsize(0x10000);
80 dbenv.set_lg_max(1048576);
81 dbenv.set_lk_max_locks(40000);
82 dbenv.set_lk_max_objects(40000);
83 dbenv.set_errfile(fopen(pathErrorFile.string().c_str(),
"a"));
84 dbenv.set_flags(DB_AUTO_COMMIT, 1);
85 dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
86 dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
87 int ret =
dbenv.open(
path.string().c_str(),
98 return error(
"CDB() : error %s (%d) opening database environment", DbEnv::strerror(ret), ret);
108 throw runtime_error(
"CDBEnv::MakeMock(): already initialized");
110 boost::this_thread::interruption_point();
112 printf(
"CDBEnv::MakeMock()\n");
114 dbenv.set_cachesize(1, 0, 1);
115 dbenv.set_lg_bsize(10485760*4);
116 dbenv.set_lg_max(10485760);
117 dbenv.set_lk_max_locks(10000);
118 dbenv.set_lk_max_objects(10000);
119 dbenv.set_flags(DB_AUTO_COMMIT, 1);
120 dbenv.log_set_config(DB_LOG_IN_MEMORY, 1);
121 int ret =
dbenv.open(NULL,
131 throw runtime_error(
strprintf(
"CDBEnv::MakeMock(): error %d opening database environment", ret));
143 int result = db.verify(strFile.c_str(), NULL, NULL, 0);
146 else if (recoverFunc == NULL)
150 bool fRecovered = (*recoverFunc)(*
this, strFile);
155 std::vector<CDBEnv::KeyValPair >& vResult)
160 u_int32_t flags = DB_SALVAGE;
161 if (fAggressive) flags |= DB_AGGRESSIVE;
163 stringstream strDump;
166 int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
167 if (result == DB_VERIFY_BAD)
169 printf(
"Error: Salvage found errors, all data may not be recoverable.\n");
172 printf(
"Error: Rerun with aggressive mode to ignore errors and continue.\n");
176 if (result != 0 && result != DB_VERIFY_BAD)
178 printf(
"ERROR: db salvage failed: %d\n",result);
191 while (!strDump.eof() && strLine !=
"HEADER=END")
192 getline(strDump, strLine);
194 std::string keyHex, valueHex;
195 while (!strDump.eof() && keyHex !=
"DATA=END")
197 getline(strDump, keyHex);
198 if (keyHex !=
"DATA_END")
200 getline(strDump, valueHex);
205 return (result == 0);
211 dbenv.txn_checkpoint(0, 0, 0);
214 dbenv.lsn_reset(strFile.c_str(), 0);
218 CDB::CDB(
const char *pszFile,
const char* pszMode) :
219 pdb(NULL), activeTxn(NULL)
225 fReadOnly = (!strchr(pszMode,
'+') && !strchr(pszMode,
'w'));
226 bool fCreate = strchr(pszMode,
'c');
227 unsigned int nFlags = DB_THREAD;
234 throw runtime_error(
"env open failed");
243 bool fMockDb = bitdb.
IsMock();
246 DbMpoolFile*mpf =
pdb->get_mpf();
247 ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
249 throw runtime_error(
strprintf(
"CDB() : failed to configure for no temp file backing for database %s", pszFile));
252 ret =
pdb->open(NULL,
253 fMockDb ? NULL : pszFile,
254 fMockDb ? pszFile :
"main",
265 throw runtime_error(
strprintf(
"CDB() : can't open database file %s, error %d", pszFile, ret));
268 if (fCreate && !
Exists(
string(
"version")))
287 unsigned int nMinutes = 0;
291 bitdb.
dbenv.txn_checkpoint(nMinutes ?
GetArg(
"-dblogsize", 100)*1024 : 0, nMinutes, 0);
315 if (
mapDb[strFile] != NULL)
318 Db* pdb =
mapDb[strFile];
321 mapDb[strFile] = NULL;
331 int rc =
dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT);
348 bool fSuccess =
true;
349 printf(
"Rewriting %s...\n", strFile.c_str());
350 string strFileRes = strFile +
".rewrite";
352 CDB db(strFile.c_str(),
"r");
353 Db* pdbCopy =
new Db(&bitdb.
dbenv, 0);
355 int ret = pdbCopy->open(NULL,
363 printf(
"Cannot create database file %s\n", strFileRes.c_str());
367 Dbc* pcursor = db.GetCursor();
373 int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
374 if (ret == DB_NOTFOUND)
386 strncmp(&ssKey[0], pszSkip, std::min(ssKey.
size(), strlen(pszSkip))) == 0)
388 if (strncmp(&ssKey[0],
"\x07version", 8) == 0)
392 ssValue << CLIENT_VERSION;
394 Dbt datKey(&ssKey[0], ssKey.
size());
395 Dbt datValue(&ssValue[0], ssValue.
size());
396 int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE);
404 if (pdbCopy->close(0))
411 Db dbA(&bitdb.
dbenv, 0);
412 if (dbA.remove(strFile.c_str(), NULL, 0))
414 Db dbB(&bitdb.
dbenv, 0);
415 if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
419 printf(
"Rewriting of %s FAILED!\n", strFileRes.c_str());
434 printf(
"Flush(%s)%s\n", fShutdown ?
"true" :
"false",
fDbEnvInit ?
"" :
" db not started");
442 string strFile = (*mi).first;
443 int nRefCount = (*mi).second;
444 printf(
"%s refcount=%d\n", strFile.c_str(), nRefCount);
449 printf(
"%s checkpoint\n", strFile.c_str());
450 dbenv.txn_checkpoint(0, 0, 0);
451 printf(
"%s detach\n", strFile.c_str());
453 dbenv.lsn_reset(strFile.c_str(), 0);
454 printf(
"%s closed\n", strFile.c_str());
466 dbenv.log_archive(&listp, DB_ARCH_REMOVE);
469 boost::filesystem::remove_all(
path /
"database");
498 unsigned short randv = 0;
499 RAND_bytes((
unsigned char *)&randv,
sizeof(randv));
500 std::string tmpfn =
strprintf(
"peers.dat.%04x", randv);
510 boost::filesystem::path pathTmp =
GetDataDir() / tmpfn;
511 FILE *file = fopen(pathTmp.string().c_str(),
"wb");
514 return error(
"CAddrman::Write() : open failed");
520 catch (std::exception &e) {
521 return error(
"CAddrman::Write() : I/O error");
528 return error(
"CAddrman::Write() : Rename-into-place failed");
536 FILE *file = fopen(
pathAddr.string().c_str(),
"rb");
539 return error(
"CAddrman::Read() : open failed");
543 int dataSize = fileSize -
sizeof(
uint256);
545 if ( dataSize < 0 ) dataSize = 0;
546 vector<unsigned char> vchData;
547 vchData.resize(dataSize);
552 filein.read((
char *)&vchData[0], dataSize);
555 catch (std::exception &e) {
556 return error(
"CAddrman::Read() 2 : I/O error or stream data corrupted");
564 if (hashIn != hashTmp)
565 return error(
"CAddrman::Read() : checksum mismatch; data corrupted");
567 unsigned char pchMsgTmp[4];
574 return error(
"CAddrman::Read() : invalid network magic number");
579 catch (std::exception &e) {
580 return error(
"CAddrman::Read() : I/O error or stream data corrupted");
bool error(const char *format,...)
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
unsigned int nWalletDBUpdated
#define strprintf(format,...)
std::map< std::string, int > mapFileUseCount
void CheckpointLSN(std::string strFile)
const_iterator begin() const
void FileCommit(FILE *fileout)
static bool Rewrite(const std::string &strFile, const char *pszSkip=NULL)
void Flush(bool fShutdown)
bool Exists(const K &key)
Double ended buffer combining vector and stream-like interfaces.
bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
boost::filesystem::path path
Stochastical (IP) address manager.
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
bool Write(const CAddrMan &addr)
std::map< std::string, Db * > mapDb
RAII class that provides access to a Berkeley database.
uint256 Hash(const T1 pbegin, const T1 pend)
bool RemoveDb(const std::string &strFile)
int GetFilesize(FILE *file)
bool Salvage(std::string strFile, bool fAggressive, std::vector< KeyValPair > &vResult)
boost::filesystem::path pathAddr
void CloseDb(const std::string &strFile)
bool WriteVersion(int nVersion)
CDB(const char *pszFile, const char *pszMode="r+")
VerifyResult Verify(std::string strFile, bool(*recoverFunc)(CDBEnv &dbenv, std::string strFile))
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
unsigned char pchMessageStart[4]
bool Open(const boost::filesystem::path &path)
vector< unsigned char > ParseHex(const char *psz)
bool Read(CAddrMan &addr)
const_iterator end() const