@ -26,14 +26,11 @@ unsigned int nWalletDBUpdated;
// CDB
// CDB
//
//
CCriticalSection cs_db ;
CDBEnv bitdb ;
static bool fDbEnvInit = false ;
bool fDetachDB = false ;
DbEnv dbenv ( 0 ) ;
map < string , int > mapFileUseCount ;
map < string , int > mapFileUseCount ;
static map < string , Db * > mapDb ;
static map < string , Db * > mapDb ;
static void EnvShutdown ( )
void CDBEnv : : EnvShutdown ( )
{
{
if ( ! fDbEnvInit )
if ( ! fDbEnvInit )
return ;
return ;
@ -50,39 +47,30 @@ static void EnvShutdown()
DbEnv ( 0 ) . remove ( GetDataDir ( ) . string ( ) . c_str ( ) , 0 ) ;
DbEnv ( 0 ) . remove ( GetDataDir ( ) . string ( ) . c_str ( ) , 0 ) ;
}
}
class CDBInit
CDBEnv : : CDBEnv ( ) : dbenv ( 0 )
{
public :
CDBInit ( )
{
{
}
}
~ CDBInit ( )
CDBEnv : : ~ CDBEnv ( )
{
{
EnvShutdown ( ) ;
EnvShutdown ( ) ;
}
}
}
instance_of_cdbinit ;
CDB : : CDB ( const char * pszFile , const char * pszMode ) : pdb ( NULL )
void CDBEnv : : Close ( )
{
{
int ret ;
EnvShutdown ( ) ;
if ( pszFile = = NULL )
}
return ;
fReadOnly = ( ! strchr ( pszMode , ' + ' ) & & ! strchr ( pszMode , ' w ' ) ) ;
bool fCreate = strchr ( pszMode , ' c ' ) ;
unsigned int nFlags = DB_THREAD ;
if ( fCreate )
nFlags | = DB_CREATE ;
bool CDBEnv : : Open ( boost : : filesystem : : path pathEnv_ )
{
{
LOCK ( cs_db ) ;
if ( fDbEnvInit )
if ( ! fDbEnvInit )
return true ;
{
if ( fShutdown )
if ( fShutdown )
return ;
return false ;
filesystem : : path pathDataDir = GetDataDir ( ) ;
pathEnv = pathEnv_ ;
filesystem : : path pathDataDir = pathEnv ;
filesystem : : path pathLogDir = pathDataDir / " database " ;
filesystem : : path pathLogDir = pathDataDir / " database " ;
filesystem : : create_directory ( pathLogDir ) ;
filesystem : : create_directory ( pathLogDir ) ;
filesystem : : path pathErrorFile = pathDataDir / " db.log " ;
filesystem : : path pathErrorFile = pathDataDir / " db.log " ;
@ -96,10 +84,10 @@ CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
dbenv . set_lk_max_locks ( 10000 ) ;
dbenv . set_lk_max_locks ( 10000 ) ;
dbenv . set_lk_max_objects ( 10000 ) ;
dbenv . set_lk_max_objects ( 10000 ) ;
dbenv . set_errfile ( fopen ( pathErrorFile . string ( ) . c_str ( ) , " a " ) ) ; /// debug
dbenv . set_errfile ( fopen ( pathErrorFile . string ( ) . c_str ( ) , " a " ) ) ; /// debug
dbenv . set_flags ( DB_TXN_WRITE_NOSYNC , 1 ) ;
dbenv . set_flags ( DB_AUTO_COMMIT , 1 ) ;
dbenv . set_flags ( DB_AUTO_COMMIT , 1 ) ;
dbenv . set_flags ( DB_TXN_WRITE_NOSYNC , 1 ) ;
dbenv . log_set_config ( DB_LOG_AUTO_REMOVE , 1 ) ;
dbenv . log_set_config ( DB_LOG_AUTO_REMOVE , 1 ) ;
ret = dbenv . open ( pathDataDir . string ( ) . c_str ( ) ,
int ret = dbenv . open ( pathDataDir . string ( ) . c_str ( ) ,
DB_CREATE |
DB_CREATE |
DB_INIT_LOCK |
DB_INIT_LOCK |
DB_INIT_LOG |
DB_INIT_LOG |
@ -109,16 +97,42 @@ CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
DB_RECOVER ,
DB_RECOVER ,
S_IRUSR | S_IWUSR ) ;
S_IRUSR | S_IWUSR ) ;
if ( ret > 0 )
if ( ret > 0 )
throw runtime_error ( strprintf ( " CDB() : error % d opening database environment " , ret)) ;
return error ( " CDB() : error % d opening database environment " , ret) ;
fDbEnvInit = true ;
fDbEnvInit = true ;
return true ;
}
}
void CDBEnv : : CheckpointLSN ( std : : string strFile )
{
dbenv . txn_checkpoint ( 0 , 0 , 0 ) ;
dbenv . lsn_reset ( strFile . c_str ( ) , 0 ) ;
}
CDB : : CDB ( const char * pszFile , const char * pszMode ) : pdb ( NULL )
{
int ret ;
if ( pszFile = = NULL )
return ;
fReadOnly = ( ! strchr ( pszMode , ' + ' ) & & ! strchr ( pszMode , ' w ' ) ) ;
bool fCreate = strchr ( pszMode , ' c ' ) ;
unsigned int nFlags = DB_THREAD ;
if ( fCreate )
nFlags | = DB_CREATE ;
{
LOCK ( bitdb . cs_db ) ;
if ( ! bitdb . Open ( GetDataDir ( ) ) )
throw runtime_error ( " env open failed " ) ;
strFile = pszFile ;
strFile = pszFile ;
+ + mapFileUseCount [ strFile ] ;
+ + mapFileUseCount [ strFile ] ;
pdb = mapDb [ strFile ] ;
pdb = mapDb [ strFile ] ;
if ( pdb = = NULL )
if ( pdb = = NULL )
{
{
pdb = new Db ( & dbenv , 0 ) ;
pdb = new Db ( & bitdb . dbenv , 0 ) ;
ret = pdb - > open ( NULL , // Txn pointer
ret = pdb - > open ( NULL , // Txn pointer
pszFile , // Filename
pszFile , // Filename
@ -132,7 +146,7 @@ CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
delete pdb ;
delete pdb ;
pdb = NULL ;
pdb = NULL ;
{
{
LOCK ( cs_db ) ;
LOCK ( bitdb . cs_db ) ;
- - mapFileUseCount [ strFile ] ;
- - mapFileUseCount [ strFile ] ;
}
}
strFile = " " ;
strFile = " " ;
@ -170,10 +184,10 @@ void CDB::Close()
if ( strFile = = " blkindex.dat " & & IsInitialBlockDownload ( ) )
if ( strFile = = " blkindex.dat " & & IsInitialBlockDownload ( ) )
nMinutes = 5 ;
nMinutes = 5 ;
dbenv . txn_checkpoint ( nMinutes ? GetArg ( " -dblogsize " , 100 ) * 1024 : 0 , nMinutes , 0 ) ;
bitdb . dbenv . txn_checkpoint ( nMinutes ? GetArg ( " -dblogsize " , 100 ) * 1024 : 0 , nMinutes , 0 ) ;
{
{
LOCK ( cs_db ) ;
LOCK ( bitdb . cs_db ) ;
- - mapFileUseCount [ strFile ] ;
- - mapFileUseCount [ strFile ] ;
}
}
}
}
@ -181,7 +195,7 @@ void CDB::Close()
void CloseDb ( const string & strFile )
void CloseDb ( const string & strFile )
{
{
{
{
LOCK ( cs_db ) ;
LOCK ( bitdb . cs_db ) ;
if ( mapDb [ strFile ] ! = NULL )
if ( mapDb [ strFile ] ! = NULL )
{
{
// Close the database handle
// Close the database handle
@ -198,13 +212,12 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
while ( ! fShutdown )
while ( ! fShutdown )
{
{
{
{
LOCK ( cs_db ) ;
LOCK ( bitdb . cs_db ) ;
if ( ! mapFileUseCount . count ( strFile ) | | mapFileUseCount [ strFile ] = = 0 )
if ( ! mapFileUseCount . count ( strFile ) | | mapFileUseCount [ strFile ] = = 0 )
{
{
// Flush log data to the dat file
// Flush log data to the dat file
CloseDb ( strFile ) ;
CloseDb ( strFile ) ;
dbenv . txn_checkpoint ( 0 , 0 , 0 ) ;
bitdb . CheckpointLSN ( strFile ) ;
dbenv . lsn_reset ( strFile . c_str ( ) , 0 ) ;
mapFileUseCount . erase ( strFile ) ;
mapFileUseCount . erase ( strFile ) ;
bool fSuccess = true ;
bool fSuccess = true ;
@ -212,7 +225,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
string strFileRes = strFile + " .rewrite " ;
string strFileRes = strFile + " .rewrite " ;
{ // surround usage of db with extra {}
{ // surround usage of db with extra {}
CDB db ( strFile . c_str ( ) , " r " ) ;
CDB db ( strFile . c_str ( ) , " r " ) ;
Db * pdbCopy = new Db ( & dbenv , 0 ) ;
Db * pdbCopy = new Db ( & bitdb . dbenv , 0 ) ;
int ret = pdbCopy - > open ( NULL , // Txn pointer
int ret = pdbCopy - > open ( NULL , // Txn pointer
strFileRes . c_str ( ) , // Filename
strFileRes . c_str ( ) , // Filename
@ -270,10 +283,10 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
}
}
if ( fSuccess )
if ( fSuccess )
{
{
Db dbA ( & dbenv , 0 ) ;
Db dbA ( & bitdb . dbenv , 0 ) ;
if ( dbA . remove ( strFile . c_str ( ) , NULL , 0 ) )
if ( dbA . remove ( strFile . c_str ( ) , NULL , 0 ) )
fSuccess = false ;
fSuccess = false ;
Db dbB ( & dbenv , 0 ) ;
Db dbB ( & bitdb . dbenv , 0 ) ;
if ( dbB . rename ( strFileRes . c_str ( ) , NULL , strFile . c_str ( ) , 0 ) )
if ( dbB . rename ( strFileRes . c_str ( ) , NULL , strFile . c_str ( ) , 0 ) )
fSuccess = false ;
fSuccess = false ;
}
}
@ -288,12 +301,12 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
}
}
void DBFlush ( bool fShutdown )
void C DBEnv : : Flush ( bool fShutdown )
{
{
int64 nStart = GetTimeMillis ( ) ;
int64 nStart = GetTimeMillis ( ) ;
// 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
printf ( " DB Flush(%s)%s\n " , fShutdown ? " true " : " false " , fDbEnvInit ? " " : " db not started " ) ;
printf ( " Flush(%s)%s \n " , fShutdown ? " true " : " false " , fDbEnvInit ? " " : " db not started " ) ;
if ( ! fDbEnvInit )
if ( ! fDbEnvInit )
return ;
return ;
{
{
@ -327,7 +340,7 @@ void DBFlush(bool fShutdown)
if ( mapFileUseCount . empty ( ) )
if ( mapFileUseCount . empty ( ) )
{
{
dbenv . log_archive ( & listp , DB_ARCH_REMOVE ) ;
dbenv . log_archive ( & listp , DB_ARCH_REMOVE ) ;
EnvShutdown ( ) ;
Close ( ) ;
}
}
}
}
}
}