Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/db.h
Show All 25 Lines | |||||
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100; | static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100; | ||||
static const bool DEFAULT_WALLET_PRIVDB = true; | static const bool DEFAULT_WALLET_PRIVDB = true; | ||||
struct WalletDatabaseFileId { | struct WalletDatabaseFileId { | ||||
u_int8_t value[DB_FILE_ID_LEN]; | u_int8_t value[DB_FILE_ID_LEN]; | ||||
bool operator==(const WalletDatabaseFileId &rhs) const; | bool operator==(const WalletDatabaseFileId &rhs) const; | ||||
}; | }; | ||||
class BerkeleyDatabase; | |||||
class BerkeleyEnvironment { | class BerkeleyEnvironment { | ||||
private: | private: | ||||
bool fDbEnvInit; | bool fDbEnvInit; | ||||
bool fMockDb; | bool fMockDb; | ||||
// Don't change into fs::path, as that can result in | // Don't change into fs::path, as that can result in | ||||
// shutdown problems/crashes caused by a static initialized internal | // shutdown problems/crashes caused by a static initialized internal | ||||
// pointer. | // pointer. | ||||
std::string strPath; | std::string strPath; | ||||
public: | public: | ||||
std::unique_ptr<DbEnv> dbenv; | std::unique_ptr<DbEnv> dbenv; | ||||
std::map<std::string, int> mapFileUseCount; | std::map<std::string, int> mapFileUseCount; | ||||
std::map<std::string, Db *> mapDb; | std::map<std::string, std::reference_wrapper<BerkeleyDatabase>> m_databases; | ||||
std::unordered_map<std::string, WalletDatabaseFileId> m_fileids; | std::unordered_map<std::string, WalletDatabaseFileId> m_fileids; | ||||
std::condition_variable_any m_db_in_use; | std::condition_variable_any m_db_in_use; | ||||
BerkeleyEnvironment(const fs::path &env_directory); | BerkeleyEnvironment(const fs::path &env_directory); | ||||
~BerkeleyEnvironment(); | ~BerkeleyEnvironment(); | ||||
void Reset(); | void Reset(); | ||||
void MakeMock(); | void MakeMock(); | ||||
bool IsMock() const { return fMockDb; } | bool IsMock() const { return fMockDb; } | ||||
bool IsInitialized() const { return fDbEnvInit; } | bool IsInitialized() const { return fDbEnvInit; } | ||||
bool IsDatabaseLoaded(const std::string &db_filename) const { | |||||
return m_databases.find(db_filename) != m_databases.end(); | |||||
} | |||||
fs::path Directory() const { return strPath; } | fs::path Directory() const { return strPath; } | ||||
/** | /** | ||||
* Verify that database file strFile is OK. If it is not, call the callback | * Verify that database file strFile is OK. If it is not, call the callback | ||||
* to try to recover. | * to try to recover. | ||||
* This must be called BEFORE strFile is opened. | * This must be called BEFORE strFile is opened. | ||||
* Returns true if strFile is OK. | * Returns true if strFile is OK. | ||||
*/ | */ | ||||
Show All 27 Lines | public: | ||||
DbTxn *TxnBegin(int flags = DB_TXN_WRITE_NOSYNC) { | DbTxn *TxnBegin(int flags = DB_TXN_WRITE_NOSYNC) { | ||||
DbTxn *ptxn = nullptr; | DbTxn *ptxn = nullptr; | ||||
int ret = dbenv->txn_begin(nullptr, &ptxn, flags); | int ret = dbenv->txn_begin(nullptr, &ptxn, flags); | ||||
if (!ptxn || ret != 0) return nullptr; | if (!ptxn || ret != 0) return nullptr; | ||||
return ptxn; | return ptxn; | ||||
} | } | ||||
}; | }; | ||||
/** Return whether a wallet database is currently loaded. */ | |||||
bool IsWalletLoaded(const fs::path &wallet_path); | |||||
/** Get BerkeleyEnvironment and database filename given a wallet path. */ | /** Get BerkeleyEnvironment and database filename given a wallet path. */ | ||||
BerkeleyEnvironment *GetWalletEnv(const fs::path &wallet_path, | BerkeleyEnvironment *GetWalletEnv(const fs::path &wallet_path, | ||||
std::string &database_filename); | std::string &database_filename); | ||||
/** | /** | ||||
* An instance of this class represents one database. | * An instance of this class represents one database. | ||||
* For BerkeleyDB this is just a (env, strFile) tuple. | * For BerkeleyDB this is just a (env, strFile) tuple. | ||||
*/ | */ | ||||
class BerkeleyDatabase { | class BerkeleyDatabase { | ||||
friend class BerkeleyBatch; | friend class BerkeleyBatch; | ||||
public: | public: | ||||
/** Create dummy DB handle */ | /** Create dummy DB handle */ | ||||
BerkeleyDatabase() | BerkeleyDatabase() | ||||
: nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), | : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), | ||||
nLastWalletUpdate(0), env(nullptr) {} | nLastWalletUpdate(0), env(nullptr) {} | ||||
/** Create DB handle to real database */ | /** Create DB handle to real database */ | ||||
BerkeleyDatabase(const fs::path &wallet_path, bool mock = false) | BerkeleyDatabase(const fs::path &wallet_path, bool mock = false) | ||||
: nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), | : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), | ||||
nLastWalletUpdate(0) { | nLastWalletUpdate(0) { | ||||
env = GetWalletEnv(wallet_path, strFile); | env = GetWalletEnv(wallet_path, strFile); | ||||
auto inserted = env->m_databases.emplace(strFile, std::ref(*this)); | |||||
assert(inserted.second); | |||||
if (mock) { | if (mock) { | ||||
env->Close(); | env->Close(); | ||||
env->Reset(); | env->Reset(); | ||||
env->MakeMock(); | env->MakeMock(); | ||||
} | } | ||||
} | } | ||||
~BerkeleyDatabase() { | |||||
if (env) { | |||||
size_t erased = env->m_databases.erase(strFile); | |||||
assert(erased == 1); | |||||
} | |||||
} | |||||
/** Return object for accessing database at specified path. */ | /** Return object for accessing database at specified path. */ | ||||
static std::unique_ptr<BerkeleyDatabase> Create(const fs::path &path) { | static std::unique_ptr<BerkeleyDatabase> Create(const fs::path &path) { | ||||
return std::make_unique<BerkeleyDatabase>(path); | return std::make_unique<BerkeleyDatabase>(path); | ||||
} | } | ||||
/** | /** | ||||
* Return object for accessing dummy database with no read/write | * Return object for accessing dummy database with no read/write | ||||
* capabilities. | * capabilities. | ||||
Show All 29 Lines | public: | ||||
void ReloadDbEnv(); | void ReloadDbEnv(); | ||||
std::atomic<unsigned int> nUpdateCounter; | std::atomic<unsigned int> nUpdateCounter; | ||||
unsigned int nLastSeen; | unsigned int nLastSeen; | ||||
unsigned int nLastFlushed; | unsigned int nLastFlushed; | ||||
int64_t nLastWalletUpdate; | int64_t nLastWalletUpdate; | ||||
/** | |||||
* Database pointer. This is initialized lazily and reset during flushes, | |||||
* so it can be null. | |||||
*/ | |||||
std::unique_ptr<Db> m_db; | |||||
private: | private: | ||||
/** BerkeleyDB specific */ | /** BerkeleyDB specific */ | ||||
BerkeleyEnvironment *env; | BerkeleyEnvironment *env; | ||||
std::string strFile; | std::string strFile; | ||||
/** | /** | ||||
* Return whether this database handle is a dummy for testing. | * Return whether this database handle is a dummy for testing. | ||||
* Only to be used at a low level, application should ideally not care | * Only to be used at a low level, application should ideally not care | ||||
▲ Show 20 Lines • Show All 248 Lines • Show Last 20 Lines |