Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/db.h
Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
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, std::reference_wrapper<BerkeleyDatabase>> m_databases; | 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(); | ~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 { | bool IsDatabaseLoaded(const std::string &db_filename) const { | ||||
return m_databases.find(db_filename) != m_databases.end(); | return m_databases.find(db_filename) != m_databases.end(); | ||||
Show All 40 Lines | DbTxn *TxnBegin(int flags = DB_TXN_WRITE_NOSYNC) { | ||||
return ptxn; | return ptxn; | ||||
} | } | ||||
}; | }; | ||||
/** Return whether a wallet database is currently loaded. */ | /** Return whether a wallet database is currently loaded. */ | ||||
bool IsWalletLoaded(const fs::path &wallet_path); | 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, | std::shared_ptr<BerkeleyEnvironment> | ||||
std::string &database_filename); | GetWalletEnv(const fs::path &wallet_path, 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(std::shared_ptr<BerkeleyEnvironment> env, | ||||
std::string filename) | |||||
: nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), | : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), | ||||
nLastWalletUpdate(0) { | nLastWalletUpdate(0), env(std::move(env)), | ||||
env = GetWalletEnv(wallet_path, strFile); | strFile(std::move(filename)) { | ||||
auto inserted = env->m_databases.emplace(strFile, std::ref(*this)); | auto inserted = | ||||
this->env->m_databases.emplace(strFile, std::ref(*this)); | |||||
assert(inserted.second); | assert(inserted.second); | ||||
if (mock) { | |||||
env->Close(); | |||||
env->Reset(); | |||||
env->MakeMock(); | |||||
} | |||||
} | } | ||||
~BerkeleyDatabase() { | ~BerkeleyDatabase() { | ||||
if (env) { | if (env) { | ||||
size_t erased = env->m_databases.erase(strFile); | size_t erased = env->m_databases.erase(strFile); | ||||
assert(erased == 1); | 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); | std::string filename; | ||||
return std::make_unique<BerkeleyDatabase>(GetWalletEnv(path, filename), | |||||
std::move(filename)); | |||||
} | } | ||||
/** | /** | ||||
* Return object for accessing dummy database with no read/write | * Return object for accessing dummy database with no read/write | ||||
* capabilities. | * capabilities. | ||||
*/ | */ | ||||
static std::unique_ptr<BerkeleyDatabase> CreateDummy() { | static std::unique_ptr<BerkeleyDatabase> CreateDummy() { | ||||
return std::make_unique<BerkeleyDatabase>(); | return std::make_unique<BerkeleyDatabase>(); | ||||
} | } | ||||
/** | /** | ||||
* Return object for accessing temporary in-memory database. | * Return object for accessing temporary in-memory database. | ||||
*/ | */ | ||||
static std::unique_ptr<BerkeleyDatabase> CreateMock() { | static std::unique_ptr<BerkeleyDatabase> CreateMock() { | ||||
return std::make_unique<BerkeleyDatabase>("", true /* mock */); | return std::make_unique<BerkeleyDatabase>( | ||||
std::make_shared<BerkeleyEnvironment>(), ""); | |||||
} | } | ||||
/** | /** | ||||
* Rewrite the entire database on disk, with the exception of key pszSkip if | * Rewrite the entire database on disk, with the exception of key pszSkip if | ||||
* non-zero | * non-zero | ||||
*/ | */ | ||||
bool Rewrite(const char *pszSkip = nullptr); | bool Rewrite(const char *pszSkip = nullptr); | ||||
Show All 12 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; | ||||
/** | /** | ||||
* Pointer to shared database environment. | |||||
* | |||||
* Normally there is only one BerkeleyDatabase object per | |||||
* BerkeleyEnvivonment, but in the special, backwards compatible case where | |||||
* multiple wallet BDB data files are loaded from the same directory, this | |||||
* will point to a shared instance that gets freed when the last data file | |||||
* is closed. | |||||
*/ | |||||
std::shared_ptr<BerkeleyEnvironment> env; | |||||
/** | |||||
* Database pointer. This is initialized lazily and reset during flushes, | * Database pointer. This is initialized lazily and reset during flushes, | ||||
* so it can be null. | * so it can be null. | ||||
*/ | */ | ||||
std::unique_ptr<Db> m_db; | std::unique_ptr<Db> m_db; | ||||
private: | private: | ||||
/** BerkeleyDB specific */ | |||||
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 | ||||
* about this. | * about this. | ||||
*/ | */ | ||||
bool IsDummy() { return env == nullptr; } | bool IsDummy() { return env == nullptr; } | ||||
▲ Show 20 Lines • Show All 245 Lines • Show Last 20 Lines |