/Users/eugenesiegel/btc/bitcoin/src/wallet/bdb.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-present 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 <common/system.h> |
11 | | #include <serialize.h> |
12 | | #include <streams.h> |
13 | | #include <util/fs.h> |
14 | | #include <wallet/db.h> |
15 | | |
16 | | #include <atomic> |
17 | | #include <condition_variable> |
18 | | #include <map> |
19 | | #include <memory> |
20 | | #include <string> |
21 | | #include <unordered_map> |
22 | | #include <vector> |
23 | | |
24 | | struct bilingual_str; |
25 | | |
26 | | class DbEnv; |
27 | | class DbTxn; |
28 | | class Db; |
29 | | class Dbc; |
30 | | |
31 | | // This constant was introduced in BDB 4.0.14 and has never changed, but there |
32 | | // is a belt-and-suspenders check in the cpp file just in case. |
33 | | #define BDB_DB_FILE_ID_LEN 20 /* Unique file ID length. */ |
34 | | |
35 | | namespace wallet { |
36 | | |
37 | | struct WalletDatabaseFileId { |
38 | | uint8_t value[BDB_DB_FILE_ID_LEN]; |
39 | | bool operator==(const WalletDatabaseFileId& rhs) const; |
40 | | }; |
41 | | |
42 | | class BerkeleyDatabase; |
43 | | |
44 | | class BerkeleyEnvironment |
45 | | { |
46 | | private: |
47 | | bool fDbEnvInit; |
48 | | bool fMockDb; |
49 | | // Don't change into fs::path, as that can result in |
50 | | // shutdown problems/crashes caused by a static initialized internal pointer. |
51 | | std::string strPath; |
52 | | |
53 | | public: |
54 | | std::unique_ptr<DbEnv> dbenv; |
55 | | std::map<fs::path, std::reference_wrapper<BerkeleyDatabase>> m_databases; |
56 | | std::unordered_map<std::string, WalletDatabaseFileId> m_fileids; |
57 | | std::condition_variable_any m_db_in_use; |
58 | | bool m_use_shared_memory; |
59 | | |
60 | | explicit BerkeleyEnvironment(const fs::path& env_directory, bool use_shared_memory); |
61 | | BerkeleyEnvironment(); |
62 | | ~BerkeleyEnvironment(); |
63 | | void Reset(); |
64 | | |
65 | 0 | bool IsMock() const { return fMockDb; } |
66 | 0 | bool IsInitialized() const { return fDbEnvInit; } |
67 | 0 | fs::path Directory() const { return fs::PathFromString(strPath); } |
68 | | |
69 | | bool Open(bilingual_str& error); |
70 | | void Close(); |
71 | | void Flush(bool fShutdown); |
72 | | void CheckpointLSN(const std::string& strFile); |
73 | | |
74 | | void CloseDb(const fs::path& filename); |
75 | | void ReloadDbEnv(); |
76 | | |
77 | | DbTxn* TxnBegin(int flags); |
78 | | }; |
79 | | |
80 | | /** Get BerkeleyEnvironment given a directory path. */ |
81 | | std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory, bool use_shared_memory); |
82 | | |
83 | | class BerkeleyBatch; |
84 | | |
85 | | /** An instance of this class represents one database. |
86 | | * For BerkeleyDB this is just a (env, strFile) tuple. |
87 | | **/ |
88 | | class BerkeleyDatabase : public WalletDatabase |
89 | | { |
90 | | public: |
91 | | BerkeleyDatabase() = delete; |
92 | | |
93 | | /** Create DB handle to real database */ |
94 | | BerkeleyDatabase(std::shared_ptr<BerkeleyEnvironment> env, fs::path filename, const DatabaseOptions& options); |
95 | | |
96 | | ~BerkeleyDatabase() override; |
97 | | |
98 | | /** Open the database if it is not already opened. */ |
99 | | void Open() override; |
100 | | |
101 | | /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero |
102 | | */ |
103 | | bool Rewrite(const char* pszSkip=nullptr) override; |
104 | | |
105 | | /** Indicate that a new database user has begun using the database. */ |
106 | | void AddRef() override; |
107 | | /** Indicate that database user has stopped using the database and that it could be flushed or closed. */ |
108 | | void RemoveRef() override; |
109 | | |
110 | | /** Back up the entire database to a file. |
111 | | */ |
112 | | bool Backup(const std::string& strDest) const override; |
113 | | |
114 | | /** Make sure all changes are flushed to database file. |
115 | | */ |
116 | | void Flush() override; |
117 | | /** Flush to the database file and close the database. |
118 | | * Also close the environment if no other databases are open in it. |
119 | | */ |
120 | | void Close() override; |
121 | | /* flush the wallet passively (TRY_LOCK) |
122 | | ideal to be called periodically */ |
123 | | bool PeriodicFlush() override; |
124 | | |
125 | | void IncrementUpdateCounter() override; |
126 | | |
127 | | void ReloadDbEnv() override; |
128 | | |
129 | | /** Verifies the environment and database file */ |
130 | | bool Verify(bilingual_str& error); |
131 | | |
132 | | /** Return path to main database filename */ |
133 | 0 | std::string Filename() override { return fs::PathToString(env->Directory() / m_filename); } |
134 | | |
135 | 0 | std::string Format() override { return "bdb"; } |
136 | | /** |
137 | | * Pointer to shared database environment. |
138 | | * |
139 | | * Normally there is only one BerkeleyDatabase object per |
140 | | * BerkeleyEnvivonment, but in the special, backwards compatible case where |
141 | | * multiple wallet BDB data files are loaded from the same directory, this |
142 | | * will point to a shared instance that gets freed when the last data file |
143 | | * is closed. |
144 | | */ |
145 | | std::shared_ptr<BerkeleyEnvironment> env; |
146 | | |
147 | | /** Database pointer. This is initialized lazily and reset during flushes, so it can be null. */ |
148 | | std::unique_ptr<Db> m_db; |
149 | | |
150 | | // Whether to byteswap |
151 | | bool m_byteswap; |
152 | | |
153 | | fs::path m_filename; |
154 | | int64_t m_max_log_mb; |
155 | | |
156 | | /** Make a BerkeleyBatch connected to this database */ |
157 | | std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override; |
158 | | }; |
159 | | |
160 | | class BerkeleyCursor : public DatabaseCursor |
161 | | { |
162 | | private: |
163 | | Dbc* m_cursor; |
164 | | std::vector<std::byte> m_key_prefix; |
165 | | bool m_first{true}; |
166 | | |
167 | | public: |
168 | | // Constructor for cursor for records matching the prefix |
169 | | // To match all records, an empty prefix may be provided. |
170 | | explicit BerkeleyCursor(BerkeleyDatabase& database, const BerkeleyBatch& batch, std::span<const std::byte> prefix = {}); |
171 | | ~BerkeleyCursor() override; |
172 | | |
173 | | Status Next(DataStream& key, DataStream& value) override; |
174 | 0 | Dbc* dbc() const { return m_cursor; } |
175 | | }; |
176 | | |
177 | | /** RAII class that provides access to a Berkeley database */ |
178 | | class BerkeleyBatch : public DatabaseBatch |
179 | | { |
180 | | private: |
181 | | bool ReadKey(DataStream&& key, DataStream& value) override; |
182 | | bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override; |
183 | | bool EraseKey(DataStream&& key) override; |
184 | | bool HasKey(DataStream&& key) override; |
185 | | bool ErasePrefix(std::span<const std::byte> prefix) override; |
186 | | |
187 | | protected: |
188 | | Db* pdb{nullptr}; |
189 | | std::string strFile; |
190 | | DbTxn* activeTxn{nullptr}; |
191 | | bool fReadOnly; |
192 | | bool fFlushOnClose; |
193 | | BerkeleyEnvironment *env; |
194 | | BerkeleyDatabase& m_database; |
195 | | |
196 | | public: |
197 | | explicit BerkeleyBatch(BerkeleyDatabase& database, const bool fReadOnly, bool fFlushOnCloseIn=true); |
198 | | ~BerkeleyBatch() override; |
199 | | |
200 | | BerkeleyBatch(const BerkeleyBatch&) = delete; |
201 | | BerkeleyBatch& operator=(const BerkeleyBatch&) = delete; |
202 | | |
203 | | void Flush() override; |
204 | | void Close() override; |
205 | | |
206 | | std::unique_ptr<DatabaseCursor> GetNewCursor() override; |
207 | | std::unique_ptr<DatabaseCursor> GetNewPrefixCursor(std::span<const std::byte> prefix) override; |
208 | | bool TxnBegin() override; |
209 | | bool TxnCommit() override; |
210 | | bool TxnAbort() override; |
211 | 0 | bool HasActiveTxn() override { return activeTxn != nullptr; } |
212 | 0 | DbTxn* txn() const { return activeTxn; } |
213 | | }; |
214 | | |
215 | | std::string BerkeleyDatabaseVersion(); |
216 | | |
217 | | /** Perform sanity check of runtime BDB version versus linked BDB version. |
218 | | */ |
219 | | bool BerkeleyDatabaseSanityCheck(); |
220 | | |
221 | | //! Return object giving access to Berkeley database at specified path. |
222 | | std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error); |
223 | | } // namespace wallet |
224 | | |
225 | | #endif // BITCOIN_WALLET_BDB_H |