@ -5,6 +5,7 @@
# include <wallet/sqlite.h>
# include <logging.h>
# include <sync.h>
# include <util/memory.h>
# include <util/strencodings.h>
# include <util/translation.h>
@ -15,18 +16,66 @@
static const char * const DATABASE_FILENAME = " wallet.dat " ;
static Mutex g_sqlite_mutex ;
static int g_sqlite_count GUARDED_BY ( g_sqlite_mutex ) = 0 ;
static void ErrorLogCallback ( void * arg , int code , const char * msg )
{
// From sqlite3_config() documentation for the SQLITE_CONFIG_LOG option:
// "The void pointer that is the second argument to SQLITE_CONFIG_LOG is passed through as
// the first parameter to the application-defined logger function whenever that function is
// invoked."
// Assert that this is the case:
assert ( arg = = nullptr ) ;
LogPrintf ( " SQLite Error. Code: %d. Message: %s \n " , code , msg ) ;
}
SQLiteDatabase : : SQLiteDatabase ( const fs : : path & dir_path , const fs : : path & file_path , bool mock )
: WalletDatabase ( ) , m_mock ( mock ) , m_dir_path ( dir_path . string ( ) ) , m_file_path ( file_path . string ( ) )
{
LogPrintf ( " Using SQLite Version %s \n " , SQLiteDatabaseVersion ( ) ) ;
LogPrintf ( " Using wallet %s \n " , m_dir_path ) ;
Open ( ) ;
{
LOCK ( g_sqlite_mutex ) ;
LogPrintf ( " Using SQLite Version %s \n " , SQLiteDatabaseVersion ( ) ) ;
LogPrintf ( " Using wallet %s \n " , m_dir_path ) ;
if ( + + g_sqlite_count = = 1 ) {
// Setup logging
int ret = sqlite3_config ( SQLITE_CONFIG_LOG , ErrorLogCallback , nullptr ) ;
if ( ret ! = SQLITE_OK ) {
throw std : : runtime_error ( strprintf ( " SQLiteDatabase: Failed to setup error log: %s \n " , sqlite3_errstr ( ret ) ) ) ;
}
}
int ret = sqlite3_initialize ( ) ; // This is a no-op if sqlite3 is already initialized
if ( ret ! = SQLITE_OK ) {
throw std : : runtime_error ( strprintf ( " SQLiteDatabase: Failed to initialize SQLite: %s \n " , sqlite3_errstr ( ret ) ) ) ;
}
}
try {
Open ( ) ;
} catch ( const std : : runtime_error & ) {
// If open fails, cleanup this object and rethrow the exception
Cleanup ( ) ;
throw ;
}
}
SQLiteDatabase : : ~ SQLiteDatabase ( )
{
Cleanup ( ) ;
}
void SQLiteDatabase : : Cleanup ( ) noexcept
{
Close ( ) ;
LOCK ( g_sqlite_mutex ) ;
if ( - - g_sqlite_count = = 0 ) {
int ret = sqlite3_shutdown ( ) ;
if ( ret ! = SQLITE_OK ) {
LogPrintf ( " SQLiteDatabase: Failed to shutdown SQLite: %s \n " , sqlite3_errstr ( ret ) ) ;
}
}
}
void SQLiteDatabase : : Open ( )