@ -28,6 +28,34 @@ DbEnv dbenv(0);
static map < string , int > mapFileUseCount ;
static map < string , int > mapFileUseCount ;
static map < string , Db * > mapDb ;
static map < string , Db * > mapDb ;
static void EnvShutdown ( bool fRemoveLogFiles )
{
if ( ! fDbEnvInit )
return ;
fDbEnvInit = false ;
dbenv . close ( 0 ) ;
DbEnv ( 0 ) . remove ( GetDataDir ( ) . c_str ( ) , 0 ) ;
if ( fRemoveLogFiles )
{
filesystem : : path datadir ( GetDataDir ( ) ) ;
filesystem : : directory_iterator it ( datadir / " database " ) ;
while ( it ! = filesystem : : directory_iterator ( ) )
{
const filesystem : : path & p = it - > path ( ) ;
# if BOOST_FILESYSTEM_VERSION == 2
std : : string f = p . filename ( ) ;
# else
std : : string f = p . filename ( ) . generic_string ( ) ;
# endif
if ( f . find ( " log. " ) = = 0 )
filesystem : : remove ( p ) ;
+ + it ;
}
}
}
class CDBInit
class CDBInit
{
{
public :
public :
@ -36,11 +64,7 @@ public:
}
}
~ CDBInit ( )
~ CDBInit ( )
{
{
if ( fDbEnvInit )
EnvShutdown ( false ) ;
{
dbenv . close ( 0 ) ;
fDbEnvInit = false ;
}
}
}
}
}
instance_of_cdbinit ;
instance_of_cdbinit ;
@ -165,7 +189,100 @@ void static CloseDb(const string& strFile)
}
}
}
}
void DBFlush ( bool fShutdown )
bool CDB : : Rewrite ( const string & strFile , const char * pszSkip )
{
while ( ! fShutdown )
{
CRITICAL_BLOCK ( cs_db )
{
if ( ! mapFileUseCount . count ( strFile ) | | mapFileUseCount [ strFile ] = = 0 )
{
// Flush log data to the dat file
CloseDb ( strFile ) ;
dbenv . txn_checkpoint ( 0 , 0 , 0 ) ;
dbenv . lsn_reset ( strFile . c_str ( ) , 0 ) ;
mapFileUseCount . erase ( strFile ) ;
bool fSuccess = true ;
printf ( " Rewriting %s... \n " , strFile . c_str ( ) ) ;
string strFileRes = strFile + " .rewrite " ;
CDB db ( strFile . c_str ( ) , " r " ) ;
Db * pdbCopy = new Db ( & dbenv , 0 ) ;
int ret = pdbCopy - > open ( NULL , // Txn pointer
strFileRes . c_str ( ) , // Filename
" main " , // Logical db name
DB_BTREE , // Database type
DB_CREATE , // Flags
0 ) ;
if ( ret > 0 )
{
printf ( " Cannot create database file %s \n " , strFileRes . c_str ( ) ) ;
fSuccess = false ;
}
Dbc * pcursor = db . GetCursor ( ) ;
if ( pcursor )
while ( fSuccess )
{
CDataStream ssKey ;
CDataStream ssValue ;
int ret = db . ReadAtCursor ( pcursor , ssKey , ssValue , DB_NEXT ) ;
if ( ret = = DB_NOTFOUND )
break ;
else if ( ret ! = 0 )
{
pcursor - > close ( ) ;
fSuccess = false ;
break ;
}
if ( pszSkip & &
strncmp ( & ssKey [ 0 ] , pszSkip , std : : min ( ssKey . size ( ) , strlen ( pszSkip ) ) ) = = 0 )
continue ;
if ( strncmp ( & ssKey [ 0 ] , " \x07 version " , 8 ) = = 0 )
{
// Update version:
ssValue . clear ( ) ;
ssValue < < VERSION ;
}
Dbt datKey ( & ssKey [ 0 ] , ssKey . size ( ) ) ;
Dbt datValue ( & ssValue [ 0 ] , ssValue . size ( ) ) ;
int ret2 = pdbCopy - > put ( NULL , & datKey , & datValue , DB_NOOVERWRITE ) ;
if ( ret2 > 0 )
fSuccess = false ;
}
if ( fSuccess )
{
Db * pdb = mapDb [ strFile ] ;
if ( pdb - > close ( 0 ) )
fSuccess = false ;
if ( pdbCopy - > close ( 0 ) )
fSuccess = false ;
delete pdb ;
delete pdbCopy ;
mapDb [ strFile ] = NULL ;
}
if ( fSuccess )
{
Db dbA ( & dbenv , 0 ) ;
if ( dbA . remove ( strFile . c_str ( ) , NULL , 0 ) )
fSuccess = false ;
Db dbB ( & dbenv , 0 ) ;
if ( dbB . rename ( strFileRes . c_str ( ) , NULL , strFile . c_str ( ) , 0 ) )
fSuccess = false ;
}
if ( ! fSuccess )
printf ( " Rewriting of %s FAILED! \n " , strFileRes . c_str ( ) ) ;
return fSuccess ;
}
}
Sleep ( 100 ) ;
}
return false ;
}
void DBFlush ( bool fShutdown , bool fRemoveLogFiles )
{
{
// Flush log data to the actual data file
// Flush log data to the actual data file
// on all files that are not in use
// on all files that are not in use
@ -196,9 +313,10 @@ void DBFlush(bool fShutdown)
{
{
char * * listp ;
char * * listp ;
if ( mapFileUseCount . empty ( ) )
if ( mapFileUseCount . empty ( ) )
{
dbenv . log_archive ( & listp , DB_ARCH_REMOVE ) ;
dbenv . log_archive ( & listp , DB_ARCH_REMOVE ) ;
dbenv . close ( 0 ) ;
EnvShutdown ( fRemoveLogFiles ) ;
fDbEnvInit = false ;
}
}
}
}
}
}
}
@ -656,6 +774,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
pwallet - > vchDefaultKey . clear ( ) ;
pwallet - > vchDefaultKey . clear ( ) ;
int nFileVersion = 0 ;
int nFileVersion = 0 ;
vector < uint256 > vWalletUpgrade ;
vector < uint256 > vWalletUpgrade ;
bool fIsEncrypted = false ;
// Modify defaults
// Modify defaults
# ifndef WIN32
# ifndef WIN32
@ -781,6 +900,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
ssValue > > vchPrivKey ;
ssValue > > vchPrivKey ;
if ( ! pwallet - > LoadCryptedKey ( vchPubKey , vchPrivKey ) )
if ( ! pwallet - > LoadCryptedKey ( vchPubKey , vchPrivKey ) )
return DB_CORRUPT ;
return DB_CORRUPT ;
fIsEncrypted = true ;
}
}
else if ( strType = = " defaultkey " )
else if ( strType = = " defaultkey " )
{
{
@ -841,8 +961,11 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
printf ( " fUseUPnP = %d \n " , fUseUPnP ) ;
printf ( " fUseUPnP = %d \n " , fUseUPnP ) ;
// Upgrade
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
if ( nFileVersion < VERSION )
if ( fIsEncrypted & & ( nFileVersion = = 40000 | | nFileVersion = = 50000 ) )
return DB_NEED_REWRITE ;
if ( nFileVersion < VERSION ) // Update
{
{
// Get rid of old debug.log file in current directory
// Get rid of old debug.log file in current directory
if ( nFileVersion < = 105 & & ! pszSetDataDir [ 0 ] )
if ( nFileVersion < = 105 & & ! pszSetDataDir [ 0 ] )
@ -851,7 +974,6 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
WriteVersion ( VERSION ) ;
WriteVersion ( VERSION ) ;
}
}
return DB_LOAD_OK ;
return DB_LOAD_OK ;
}
}