@@ -359,31 +359,34 @@ void CDBEnv::CheckpointLSN(const std::string& strFile)
359
359
}
360
360
361
361
362
- CDB::CDB (const std::string& strFilename , const char * pszMode, bool fFlushOnCloseIn ) : pdb(NULL ), activeTxn(NULL )
362
+ CDB::CDB (CWalletDBWrapper& dbw , const char * pszMode, bool fFlushOnCloseIn ) : pdb(NULL ), activeTxn(NULL )
363
363
{
364
364
int ret;
365
365
fReadOnly = (!strchr (pszMode, ' +' ) && !strchr (pszMode, ' w' ));
366
366
fFlushOnClose = fFlushOnCloseIn ;
367
- if (strFilename.empty ())
367
+ env = dbw.env ;
368
+ if (dbw.IsDummy ()) {
368
369
return ;
370
+ }
371
+ const std::string &strFilename = dbw.strFile ;
369
372
370
373
bool fCreate = strchr (pszMode, ' c' ) != NULL ;
371
374
unsigned int nFlags = DB_THREAD;
372
375
if (fCreate )
373
376
nFlags |= DB_CREATE;
374
377
375
378
{
376
- LOCK (bitdb. cs_db );
377
- if (!bitdb. Open (GetDataDir ()))
379
+ LOCK (env-> cs_db );
380
+ if (!env-> Open (GetDataDir ()))
378
381
throw std::runtime_error (" CDB: Failed to open database environment." );
379
382
380
383
strFile = strFilename;
381
- ++bitdb. mapFileUseCount [strFile];
382
- pdb = bitdb. mapDb [strFile];
384
+ ++env-> mapFileUseCount [strFile];
385
+ pdb = env-> mapDb [strFile];
383
386
if (pdb == NULL ) {
384
- pdb = new Db (bitdb. dbenv , 0 );
387
+ pdb = new Db (env-> dbenv , 0 );
385
388
386
- bool fMockDb = bitdb. IsMock ();
389
+ bool fMockDb = env-> IsMock ();
387
390
if (fMockDb ) {
388
391
DbMpoolFile* mpf = pdb->get_mpf ();
389
392
ret = mpf->set_flags (DB_MPOOL_NOFILE, 1 );
@@ -401,7 +404,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose
401
404
if (ret != 0 ) {
402
405
delete pdb;
403
406
pdb = NULL ;
404
- --bitdb. mapFileUseCount [strFile];
407
+ --env-> mapFileUseCount [strFile];
405
408
strFile = " " ;
406
409
throw std::runtime_error (strprintf (" CDB: Error %d, can't open database %s" , ret, strFilename));
407
410
}
@@ -413,7 +416,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose
413
416
fReadOnly = fTmp ;
414
417
}
415
418
416
- bitdb. mapDb [strFile] = pdb;
419
+ env-> mapDb [strFile] = pdb;
417
420
}
418
421
}
419
422
}
@@ -428,7 +431,7 @@ void CDB::Flush()
428
431
if (fReadOnly )
429
432
nMinutes = 1 ;
430
433
431
- bitdb. dbenv ->txn_checkpoint (nMinutes ? GetArg (" -dblogsize" , DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0 , nMinutes, 0 );
434
+ env-> dbenv ->txn_checkpoint (nMinutes ? GetArg (" -dblogsize" , DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0 , nMinutes, 0 );
432
435
}
433
436
434
437
void CDB::Close ()
@@ -444,8 +447,8 @@ void CDB::Close()
444
447
Flush ();
445
448
446
449
{
447
- LOCK (bitdb. cs_db );
448
- --bitdb. mapFileUseCount [strFile];
450
+ LOCK (env-> cs_db );
451
+ --env-> mapFileUseCount [strFile];
449
452
}
450
453
}
451
454
@@ -472,23 +475,28 @@ bool CDBEnv::RemoveDb(const std::string& strFile)
472
475
return (rc == 0 );
473
476
}
474
477
475
- bool CDB::Rewrite (const std::string& strFile , const char * pszSkip)
478
+ bool CDB::Rewrite (CWalletDBWrapper& dbw , const char * pszSkip)
476
479
{
480
+ if (dbw.IsDummy ()) {
481
+ return true ;
482
+ }
483
+ CDBEnv *env = dbw.env ;
484
+ const std::string& strFile = dbw.strFile ;
477
485
while (true ) {
478
486
{
479
- LOCK (bitdb. cs_db );
480
- if (!bitdb. mapFileUseCount .count (strFile) || bitdb. mapFileUseCount [strFile] == 0 ) {
487
+ LOCK (env-> cs_db );
488
+ if (!env-> mapFileUseCount .count (strFile) || env-> mapFileUseCount [strFile] == 0 ) {
481
489
// Flush log data to the dat file
482
- bitdb. CloseDb (strFile);
483
- bitdb. CheckpointLSN (strFile);
484
- bitdb. mapFileUseCount .erase (strFile);
490
+ env-> CloseDb (strFile);
491
+ env-> CheckpointLSN (strFile);
492
+ env-> mapFileUseCount .erase (strFile);
485
493
486
494
bool fSuccess = true ;
487
495
LogPrintf (" CDB::Rewrite: Rewriting %s...\n " , strFile);
488
496
std::string strFileRes = strFile + " .rewrite" ;
489
497
{ // surround usage of db with extra {}
490
- CDB db (strFile. c_str () , " r" );
491
- Db* pdbCopy = new Db (bitdb. dbenv , 0 );
498
+ CDB db (dbw , " r" );
499
+ Db* pdbCopy = new Db (env-> dbenv , 0 );
492
500
493
501
int ret = pdbCopy->open (NULL , // Txn pointer
494
502
strFileRes.c_str (), // Filename
@@ -531,17 +539,17 @@ bool CDB::Rewrite(const std::string& strFile, const char* pszSkip)
531
539
}
532
540
if (fSuccess ) {
533
541
db.Close ();
534
- bitdb. CloseDb (strFile);
542
+ env-> CloseDb (strFile);
535
543
if (pdbCopy->close (0 ))
536
544
fSuccess = false ;
537
545
delete pdbCopy;
538
546
}
539
547
}
540
548
if (fSuccess ) {
541
- Db dbA (bitdb. dbenv , 0 );
549
+ Db dbA (env-> dbenv , 0 );
542
550
if (dbA.remove (strFile.c_str (), NULL , 0 ))
543
551
fSuccess = false ;
544
- Db dbB (bitdb. dbenv , 0 );
552
+ Db dbB (env-> dbenv , 0 );
545
553
if (dbB.rename (strFileRes.c_str (), NULL , strFile.c_str (), 0 ))
546
554
fSuccess = false ;
547
555
}
@@ -596,16 +604,21 @@ void CDBEnv::Flush(bool fShutdown)
596
604
}
597
605
}
598
606
599
- bool CDB::PeriodicFlush (std::string strFile )
607
+ bool CDB::PeriodicFlush (CWalletDBWrapper& dbw )
600
608
{
609
+ if (dbw.IsDummy ()) {
610
+ return true ;
611
+ }
601
612
bool ret = false ;
613
+ CDBEnv *env = dbw.env ;
614
+ const std::string& strFile = dbw.strFile ;
602
615
TRY_LOCK (bitdb.cs_db ,lockDb);
603
616
if (lockDb)
604
617
{
605
618
// Don't do this if any databases are in use
606
619
int nRefCount = 0 ;
607
- std::map<std::string, int >::iterator mit = bitdb. mapFileUseCount .begin ();
608
- while (mit != bitdb. mapFileUseCount .end ())
620
+ std::map<std::string, int >::iterator mit = env-> mapFileUseCount .begin ();
621
+ while (mit != env-> mapFileUseCount .end ())
609
622
{
610
623
nRefCount += (*mit).second ;
611
624
mit++;
@@ -614,17 +627,17 @@ bool CDB::PeriodicFlush(std::string strFile)
614
627
if (nRefCount == 0 )
615
628
{
616
629
boost::this_thread::interruption_point ();
617
- std::map<std::string, int >::iterator mi = bitdb. mapFileUseCount .find (strFile);
618
- if (mi != bitdb. mapFileUseCount .end ())
630
+ std::map<std::string, int >::iterator mi = env-> mapFileUseCount .find (strFile);
631
+ if (mi != env-> mapFileUseCount .end ())
619
632
{
620
633
LogPrint (BCLog::DB, " Flushing %s\n " , strFile);
621
634
int64_t nStart = GetTimeMillis ();
622
635
623
636
// Flush wallet file so it's self contained
624
- bitdb. CloseDb (strFile);
625
- bitdb. CheckpointLSN (strFile);
637
+ env-> CloseDb (strFile);
638
+ env-> CheckpointLSN (strFile);
626
639
627
- bitdb. mapFileUseCount .erase (mi++);
640
+ env-> mapFileUseCount .erase (mi++);
628
641
LogPrint (BCLog::DB, " Flushed %s %dms\n " , strFile, GetTimeMillis () - nStart);
629
642
ret = true ;
630
643
}
@@ -633,3 +646,52 @@ bool CDB::PeriodicFlush(std::string strFile)
633
646
634
647
return ret;
635
648
}
649
+
650
+ bool CWalletDBWrapper::Rewrite (const char * pszSkip)
651
+ {
652
+ return CDB::Rewrite (*this , pszSkip);
653
+ }
654
+
655
+ bool CWalletDBWrapper::Backup (const std::string& strDest)
656
+ {
657
+ if (IsDummy ()) {
658
+ return false ;
659
+ }
660
+ while (true )
661
+ {
662
+ {
663
+ LOCK (env->cs_db );
664
+ if (!env->mapFileUseCount .count (strFile) || env->mapFileUseCount [strFile] == 0 )
665
+ {
666
+ // Flush log data to the dat file
667
+ env->CloseDb (strFile);
668
+ env->CheckpointLSN (strFile);
669
+ env->mapFileUseCount .erase (strFile);
670
+
671
+ // Copy wallet file
672
+ fs::path pathSrc = GetDataDir () / strFile;
673
+ fs::path pathDest (strDest);
674
+ if (fs::is_directory (pathDest))
675
+ pathDest /= strFile;
676
+
677
+ try {
678
+ fs::copy_file (pathSrc, pathDest, fs::copy_option::overwrite_if_exists);
679
+ LogPrintf (" copied %s to %s\n " , strFile, pathDest.string ());
680
+ return true ;
681
+ } catch (const fs::filesystem_error& e) {
682
+ LogPrintf (" error copying %s to %s - %s\n " , strFile, pathDest.string (), e.what ());
683
+ return false ;
684
+ }
685
+ }
686
+ }
687
+ MilliSleep (100 );
688
+ }
689
+ return false ;
690
+ }
691
+
692
+ void CWalletDBWrapper::Flush (bool shutdown)
693
+ {
694
+ if (!IsDummy ()) {
695
+ env->Flush (shutdown);
696
+ }
697
+ }
0 commit comments