@@ -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+
320326bool 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-
481482void BerkeleyEnvironment::CheckpointLSN (const std::string& strFile)
482483{
483484 dbenv->txn_checkpoint (0 , 0 , 0 );
0 commit comments