Skip to content

Commit ced95d0

Browse files
committed
Move BerkeleyEnvironment::Salvage into BerkeleyBatch::Recover
1 parent 07250b8 commit ced95d0

File tree

2 files changed

+62
-70
lines changed

2 files changed

+62
-70
lines changed

src/wallet/db.cpp

Lines changed: 62 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ BerkeleyBatch::SafeDbt::operator Dbt*()
317317
return &m_dbt;
318318
}
319319

320+
/* End of headers, beginning of key/value data */
321+
static const char *HEADER_END = "HEADER=END";
322+
/* End of key/value data */
323+
static const char *DATA_END = "DATA=END";
324+
typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
325+
320326
bool BerkeleyBatch::Recover(const fs::path& file_path, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename)
321327
{
322328
std::string filename;
@@ -342,8 +348,61 @@ bool BerkeleyBatch::Recover(const fs::path& file_path, void *callbackDataIn, boo
342348
return false;
343349
}
344350

345-
std::vector<BerkeleyEnvironment::KeyValPair> salvagedData;
346-
bool fSuccess = env->Salvage(newFilename, salvagedData);
351+
/**
352+
* Salvage data from a file. The DB_AGGRESSIVE flag is being used (see berkeley DB->verify() method documentation).
353+
* key/value pairs are appended to salvagedData which are then written out to a new wallet file.
354+
* NOTE: reads the entire database into memory, so cannot be used
355+
* for huge databases.
356+
*/
357+
std::vector<KeyValPair> salvagedData;
358+
359+
std::stringstream strDump;
360+
361+
Db db(env->dbenv.get(), 0);
362+
result = db.verify(newFilename.c_str(), nullptr, &strDump, DB_SALVAGE | DB_AGGRESSIVE);
363+
if (result == DB_VERIFY_BAD) {
364+
LogPrintf("Salvage: Database salvage found errors, all data may not be recoverable.\n");
365+
}
366+
if (result != 0 && result != DB_VERIFY_BAD) {
367+
LogPrintf("Salvage: Database salvage failed with result %d.\n", result);
368+
return false;
369+
}
370+
371+
// Format of bdb dump is ascii lines:
372+
// header lines...
373+
// HEADER=END
374+
// hexadecimal key
375+
// hexadecimal value
376+
// ... repeated
377+
// DATA=END
378+
379+
std::string strLine;
380+
while (!strDump.eof() && strLine != HEADER_END)
381+
getline(strDump, strLine); // Skip past header
382+
383+
std::string keyHex, valueHex;
384+
while (!strDump.eof() && keyHex != DATA_END) {
385+
getline(strDump, keyHex);
386+
if (keyHex != DATA_END) {
387+
if (strDump.eof())
388+
break;
389+
getline(strDump, valueHex);
390+
if (valueHex == DATA_END) {
391+
LogPrintf("Salvage: WARNING: Number of keys in data does not match number of values.\n");
392+
break;
393+
}
394+
salvagedData.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
395+
}
396+
}
397+
398+
bool fSuccess;
399+
if (keyHex != DATA_END) {
400+
LogPrintf("Salvage: WARNING: Unexpected end of file while reading salvage output.\n");
401+
fSuccess = false;
402+
} else {
403+
fSuccess = (result == 0);
404+
}
405+
347406
if (salvagedData.empty())
348407
{
349408
LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename);
@@ -365,7 +424,7 @@ bool BerkeleyBatch::Recover(const fs::path& file_path, void *callbackDataIn, boo
365424
}
366425

367426
DbTxn* ptxn = env->TxnBegin();
368-
for (BerkeleyEnvironment::KeyValPair& row : salvagedData)
427+
for (KeyValPair& row : salvagedData)
369428
{
370429
if (recoverKVcallback)
371430
{
@@ -420,64 +479,6 @@ bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, bilingual_str&
420479
return true;
421480
}
422481

423-
/* End of headers, beginning of key/value data */
424-
static const char *HEADER_END = "HEADER=END";
425-
/* End of key/value data */
426-
static const char *DATA_END = "DATA=END";
427-
428-
bool BerkeleyEnvironment::Salvage(const std::string& strFile, std::vector<BerkeleyEnvironment::KeyValPair>& vResult)
429-
{
430-
LOCK(cs_db);
431-
assert(mapFileUseCount.count(strFile) == 0);
432-
433-
std::stringstream strDump;
434-
435-
Db db(dbenv.get(), 0);
436-
int result = db.verify(strFile.c_str(), nullptr, &strDump, DB_SALVAGE | DB_AGGRESSIVE);
437-
if (result == DB_VERIFY_BAD) {
438-
LogPrintf("BerkeleyEnvironment::Salvage: Database salvage found errors, all data may not be recoverable.\n");
439-
}
440-
if (result != 0 && result != DB_VERIFY_BAD) {
441-
LogPrintf("BerkeleyEnvironment::Salvage: Database salvage failed with result %d.\n", result);
442-
return false;
443-
}
444-
445-
// Format of bdb dump is ascii lines:
446-
// header lines...
447-
// HEADER=END
448-
// hexadecimal key
449-
// hexadecimal value
450-
// ... repeated
451-
// DATA=END
452-
453-
std::string strLine;
454-
while (!strDump.eof() && strLine != HEADER_END)
455-
getline(strDump, strLine); // Skip past header
456-
457-
std::string keyHex, valueHex;
458-
while (!strDump.eof() && keyHex != DATA_END) {
459-
getline(strDump, keyHex);
460-
if (keyHex != DATA_END) {
461-
if (strDump.eof())
462-
break;
463-
getline(strDump, valueHex);
464-
if (valueHex == DATA_END) {
465-
LogPrintf("BerkeleyEnvironment::Salvage: WARNING: Number of keys in data does not match number of values.\n");
466-
break;
467-
}
468-
vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
469-
}
470-
}
471-
472-
if (keyHex != DATA_END) {
473-
LogPrintf("BerkeleyEnvironment::Salvage: WARNING: Unexpected end of file while reading salvage output.\n");
474-
return false;
475-
}
476-
477-
return (result == 0);
478-
}
479-
480-
481482
void BerkeleyEnvironment::CheckpointLSN(const std::string& strFile)
482483
{
483484
dbenv->txn_checkpoint(0, 0, 0);

src/wallet/db.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,6 @@ class BerkeleyEnvironment
6767
fs::path Directory() const { return strPath; }
6868

6969
bool Verify(const std::string& strFile);
70-
/**
71-
* Salvage data from a file that Verify says is bad.
72-
* fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
73-
* Appends binary key/value pairs to vResult, returns true if successful.
74-
* NOTE: reads the entire database into memory, so cannot be used
75-
* for huge databases.
76-
*/
77-
typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
78-
bool Salvage(const std::string& strFile, std::vector<KeyValPair>& vResult);
7970

8071
bool Open(bool retry);
8172
void Close();

0 commit comments

Comments
 (0)