Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2021 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #ifndef BITCOIN_WALLET_BDB_H
# 7 : : #define BITCOIN_WALLET_BDB_H
# 8 : :
# 9 : : #include <clientversion.h>
# 10 : : #include <fs.h>
# 11 : : #include <serialize.h>
# 12 : : #include <streams.h>
# 13 : : #include <util/system.h>
# 14 : : #include <wallet/db.h>
# 15 : :
# 16 : : #include <atomic>
# 17 : : #include <map>
# 18 : : #include <memory>
# 19 : : #include <string>
# 20 : : #include <unordered_map>
# 21 : : #include <vector>
# 22 : :
# 23 : : #if defined(__GNUC__) && !defined(__clang__)
# 24 : : #pragma GCC diagnostic push
# 25 : : #pragma GCC diagnostic ignored "-Wsuggest-override"
# 26 : : #endif
# 27 : : #include <db_cxx.h>
# 28 : : #if defined(__GNUC__) && !defined(__clang__)
# 29 : : #pragma GCC diagnostic pop
# 30 : : #endif
# 31 : :
# 32 : : struct bilingual_str;
# 33 : :
# 34 : : namespace wallet {
# 35 : :
# 36 : : struct WalletDatabaseFileId {
# 37 : : u_int8_t value[DB_FILE_ID_LEN];
# 38 : : bool operator==(const WalletDatabaseFileId& rhs) const;
# 39 : : };
# 40 : :
# 41 : : class BerkeleyDatabase;
# 42 : :
# 43 : : class BerkeleyEnvironment
# 44 : : {
# 45 : : private:
# 46 : : bool fDbEnvInit;
# 47 : : bool fMockDb;
# 48 : : // Don't change into fs::path, as that can result in
# 49 : : // shutdown problems/crashes caused by a static initialized internal pointer.
# 50 : : std::string strPath;
# 51 : :
# 52 : : public:
# 53 : : std::unique_ptr<DbEnv> dbenv;
# 54 : : std::map<std::string, std::reference_wrapper<BerkeleyDatabase>> m_databases;
# 55 : : std::unordered_map<std::string, WalletDatabaseFileId> m_fileids;
# 56 : : std::condition_variable_any m_db_in_use;
# 57 : : bool m_use_shared_memory;
# 58 : :
# 59 : : explicit BerkeleyEnvironment(const fs::path& env_directory, bool use_shared_memory);
# 60 : : BerkeleyEnvironment();
# 61 : : ~BerkeleyEnvironment();
# 62 : : void Reset();
# 63 : :
# 64 : 2228 : bool IsMock() const { return fMockDb; }
# 65 : 0 : bool IsInitialized() const { return fDbEnvInit; }
# 66 : 1042 : fs::path Directory() const { return fs::PathFromString(strPath); }
# 67 : :
# 68 : : bool Open(bilingual_str& error);
# 69 : : void Close();
# 70 : : void Flush(bool fShutdown);
# 71 : : void CheckpointLSN(const std::string& strFile);
# 72 : :
# 73 : : void CloseDb(const std::string& strFile);
# 74 : : void ReloadDbEnv();
# 75 : :
# 76 : : DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
# 77 : 26 : {
# 78 : 26 : DbTxn* ptxn = nullptr;
# 79 : 26 : int ret = dbenv->txn_begin(nullptr, &ptxn, flags);
# 80 [ - + ][ - + ]: 26 : if (!ptxn || ret != 0)
# 81 : 0 : return nullptr;
# 82 : 26 : return ptxn;
# 83 : 26 : }
# 84 : : };
# 85 : :
# 86 : : /** Get BerkeleyEnvironment given a directory path. */
# 87 : : std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory, bool use_shared_memory);
# 88 : :
# 89 : : class BerkeleyBatch;
# 90 : :
# 91 : : /** An instance of this class represents one database.
# 92 : : * For BerkeleyDB this is just a (env, strFile) tuple.
# 93 : : **/
# 94 : : class BerkeleyDatabase : public WalletDatabase
# 95 : : {
# 96 : : public:
# 97 : : BerkeleyDatabase() = delete;
# 98 : :
# 99 : : /** Create DB handle to real database */
# 100 : : BerkeleyDatabase(std::shared_ptr<BerkeleyEnvironment> env, std::string filename, const DatabaseOptions& options) :
# 101 : : WalletDatabase(), env(std::move(env)), strFile(std::move(filename)), m_max_log_mb(options.max_log_mb)
# 102 : 598 : {
# 103 : 598 : auto inserted = this->env->m_databases.emplace(strFile, std::ref(*this));
# 104 : 598 : assert(inserted.second);
# 105 : 598 : }
# 106 : :
# 107 : : ~BerkeleyDatabase() override;
# 108 : :
# 109 : : /** Open the database if it is not already opened. */
# 110 : : void Open() override;
# 111 : :
# 112 : : /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
# 113 : : */
# 114 : : bool Rewrite(const char* pszSkip=nullptr) override;
# 115 : :
# 116 : : /** Indicate that a new database user has begun using the database. */
# 117 : : void AddRef() override;
# 118 : : /** Indicate that database user has stopped using the database and that it could be flushed or closed. */
# 119 : : void RemoveRef() override;
# 120 : :
# 121 : : /** Back up the entire database to a file.
# 122 : : */
# 123 : : bool Backup(const std::string& strDest) const override;
# 124 : :
# 125 : : /** Make sure all changes are flushed to database file.
# 126 : : */
# 127 : : void Flush() override;
# 128 : : /** Flush to the database file and close the database.
# 129 : : * Also close the environment if no other databases are open in it.
# 130 : : */
# 131 : : void Close() override;
# 132 : : /* flush the wallet passively (TRY_LOCK)
# 133 : : ideal to be called periodically */
# 134 : : bool PeriodicFlush() override;
# 135 : :
# 136 : : void IncrementUpdateCounter() override;
# 137 : :
# 138 : : void ReloadDbEnv() override;
# 139 : :
# 140 : : /** Verifies the environment and database file */
# 141 : : bool Verify(bilingual_str& error);
# 142 : :
# 143 : : /** Return path to main database filename */
# 144 : 489 : std::string Filename() override { return fs::PathToString(env->Directory() / strFile); }
# 145 : :
# 146 : 658 : std::string Format() override { return "bdb"; }
# 147 : : /**
# 148 : : * Pointer to shared database environment.
# 149 : : *
# 150 : : * Normally there is only one BerkeleyDatabase object per
# 151 : : * BerkeleyEnvivonment, but in the special, backwards compatible case where
# 152 : : * multiple wallet BDB data files are loaded from the same directory, this
# 153 : : * will point to a shared instance that gets freed when the last data file
# 154 : : * is closed.
# 155 : : */
# 156 : : std::shared_ptr<BerkeleyEnvironment> env;
# 157 : :
# 158 : : /** Database pointer. This is initialized lazily and reset during flushes, so it can be null. */
# 159 : : std::unique_ptr<Db> m_db;
# 160 : :
# 161 : : std::string strFile;
# 162 : : int64_t m_max_log_mb;
# 163 : :
# 164 : : /** Make a BerkeleyBatch connected to this database */
# 165 : : std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override;
# 166 : : };
# 167 : :
# 168 : : /** RAII class that provides access to a Berkeley database */
# 169 : : class BerkeleyBatch : public DatabaseBatch
# 170 : : {
# 171 : : /** RAII class that automatically cleanses its data on destruction */
# 172 : : class SafeDbt final
# 173 : : {
# 174 : : Dbt m_dbt;
# 175 : :
# 176 : : public:
# 177 : : // construct Dbt with internally-managed data
# 178 : : SafeDbt();
# 179 : : // construct Dbt with provided data
# 180 : : SafeDbt(void* data, size_t size);
# 181 : : ~SafeDbt();
# 182 : :
# 183 : : // delegate to Dbt
# 184 : : const void* get_data() const;
# 185 : : u_int32_t get_size() const;
# 186 : :
# 187 : : // conversion operator to access the underlying Dbt
# 188 : : operator Dbt*();
# 189 : : };
# 190 : :
# 191 : : private:
# 192 : : bool ReadKey(CDataStream&& key, CDataStream& value) override;
# 193 : : bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite = true) override;
# 194 : : bool EraseKey(CDataStream&& key) override;
# 195 : : bool HasKey(CDataStream&& key) override;
# 196 : :
# 197 : : protected:
# 198 : : Db* pdb;
# 199 : : std::string strFile;
# 200 : : DbTxn* activeTxn;
# 201 : : Dbc* m_cursor;
# 202 : : bool fReadOnly;
# 203 : : bool fFlushOnClose;
# 204 : : BerkeleyEnvironment *env;
# 205 : : BerkeleyDatabase& m_database;
# 206 : :
# 207 : : public:
# 208 : : explicit BerkeleyBatch(BerkeleyDatabase& database, const bool fReadOnly, bool fFlushOnCloseIn=true);
# 209 : : ~BerkeleyBatch() override;
# 210 : :
# 211 : : BerkeleyBatch(const BerkeleyBatch&) = delete;
# 212 : : BerkeleyBatch& operator=(const BerkeleyBatch&) = delete;
# 213 : :
# 214 : : void Flush() override;
# 215 : : void Close() override;
# 216 : :
# 217 : : bool StartCursor() override;
# 218 : : bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override;
# 219 : : void CloseCursor() override;
# 220 : : bool TxnBegin() override;
# 221 : : bool TxnCommit() override;
# 222 : : bool TxnAbort() override;
# 223 : : };
# 224 : :
# 225 : : std::string BerkeleyDatabaseVersion();
# 226 : :
# 227 : : /** Perform sanity check of runtime BDB version versus linked BDB version.
# 228 : : */
# 229 : : bool BerkeleyDatabaseSanityCheck();
# 230 : :
# 231 : : //! Return object giving access to Berkeley database at specified path.
# 232 : : std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
# 233 : : } // namespace wallet
# 234 : :
# 235 : : #endif // BITCOIN_WALLET_BDB_H
|