Bitcoin Core  27.99.0
P2P Digital Currency
dbwrapper.h
Go to the documentation of this file.
1 // Copyright (c) 2012-2022 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef BITCOIN_DBWRAPPER_H
6 #define BITCOIN_DBWRAPPER_H
7 
8 #include <attributes.h>
9 #include <serialize.h>
10 #include <span.h>
11 #include <streams.h>
12 #include <util/check.h>
13 #include <util/fs.h>
14 
15 #include <cstddef>
16 #include <exception>
17 #include <memory>
18 #include <optional>
19 #include <stdexcept>
20 #include <string>
21 #include <vector>
22 
23 static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
24 static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
25 
27 struct DBOptions {
29  bool force_compact = false;
30 };
31 
33 struct DBParams {
37  size_t cache_bytes;
39  bool memory_only = false;
41  bool wipe_data = false;
44  bool obfuscate = false;
47 };
48 
49 class dbwrapper_error : public std::runtime_error
50 {
51 public:
52  explicit dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
53 };
54 
55 class CDBWrapper;
56 
59 namespace dbwrapper_private {
60 
65 const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w);
66 
67 }; // namespace dbwrapper_private
68 
69 bool DestroyDB(const std::string& path_str);
70 
72 class CDBBatch
73 {
74  friend class CDBWrapper;
75 
76 private:
78 
79  struct WriteBatchImpl;
80  const std::unique_ptr<WriteBatchImpl> m_impl_batch;
81 
84 
85  size_t size_estimate{0};
86 
89 
90 public:
94  explicit CDBBatch(const CDBWrapper& _parent);
96  void Clear();
97 
98  template <typename K, typename V>
99  void Write(const K& key, const V& value)
100  {
103  ssKey << key;
104  ssValue << value;
106  ssKey.clear();
107  ssValue.clear();
108  }
109 
110  template <typename K>
111  void Erase(const K& key)
112  {
114  ssKey << key;
115  EraseImpl(ssKey);
116  ssKey.clear();
117  }
118 
119  size_t SizeEstimate() const { return size_estimate; }
120 };
121 
123 {
124 public:
125  struct IteratorImpl;
126 
127 private:
129  const std::unique_ptr<IteratorImpl> m_impl_iter;
130 
134 
135 public:
136 
141  CDBIterator(const CDBWrapper& _parent, std::unique_ptr<IteratorImpl> _piter);
143 
144  bool Valid() const;
145 
146  void SeekToFirst();
147 
148  template<typename K> void Seek(const K& key) {
149  DataStream ssKey{};
151  ssKey << key;
152  SeekImpl(ssKey);
153  }
154 
155  void Next();
156 
157  template<typename K> bool GetKey(K& key) {
158  try {
159  DataStream ssKey{GetKeyImpl()};
160  ssKey >> key;
161  } catch (const std::exception&) {
162  return false;
163  }
164  return true;
165  }
166 
167  template<typename V> bool GetValue(V& value) {
168  try {
169  DataStream ssValue{GetValueImpl()};
171  ssValue >> value;
172  } catch (const std::exception&) {
173  return false;
174  }
175  return true;
176  }
177 };
178 
179 struct LevelDBContext;
180 
182 {
183  friend const std::vector<unsigned char>& dbwrapper_private::GetObfuscateKey(const CDBWrapper &w);
184 private:
186  std::unique_ptr<LevelDBContext> m_db_context;
187 
189  std::string m_name;
190 
192  std::vector<unsigned char> obfuscate_key;
193 
195  static const std::string OBFUSCATE_KEY_KEY;
196 
198  static const unsigned int OBFUSCATE_KEY_NUM_BYTES;
199 
200  std::vector<unsigned char> CreateObfuscateKey() const;
201 
204 
207 
208  std::optional<std::string> ReadImpl(Span<const std::byte> key) const;
209  bool ExistsImpl(Span<const std::byte> key) const;
211  auto& DBContext() const LIFETIMEBOUND { return *Assert(m_db_context); }
212 
213 public:
214  CDBWrapper(const DBParams& params);
215  ~CDBWrapper();
216 
217  CDBWrapper(const CDBWrapper&) = delete;
218  CDBWrapper& operator=(const CDBWrapper&) = delete;
219 
220  template <typename K, typename V>
221  bool Read(const K& key, V& value) const
222  {
223  DataStream ssKey{};
225  ssKey << key;
226  std::optional<std::string> strValue{ReadImpl(ssKey)};
227  if (!strValue) {
228  return false;
229  }
230  try {
231  DataStream ssValue{MakeByteSpan(*strValue)};
232  ssValue.Xor(obfuscate_key);
233  ssValue >> value;
234  } catch (const std::exception&) {
235  return false;
236  }
237  return true;
238  }
239 
240  template <typename K, typename V>
241  bool Write(const K& key, const V& value, bool fSync = false)
242  {
243  CDBBatch batch(*this);
244  batch.Write(key, value);
245  return WriteBatch(batch, fSync);
246  }
247 
249  std::optional<fs::path> StoragePath() {
250  if (m_is_memory) {
251  return {};
252  }
253  return m_path;
254  }
255 
256  template <typename K>
257  bool Exists(const K& key) const
258  {
259  DataStream ssKey{};
261  ssKey << key;
262  return ExistsImpl(ssKey);
263  }
264 
265  template <typename K>
266  bool Erase(const K& key, bool fSync = false)
267  {
268  CDBBatch batch(*this);
269  batch.Erase(key);
270  return WriteBatch(batch, fSync);
271  }
272 
273  bool WriteBatch(CDBBatch& batch, bool fSync = false);
274 
275  // Get an estimate of LevelDB memory usage (in bytes).
276  size_t DynamicMemoryUsage() const;
277 
279 
283  bool IsEmpty();
284 
285  template<typename K>
286  size_t EstimateSize(const K& key_begin, const K& key_end) const
287  {
288  DataStream ssKey1{}, ssKey2{};
290  ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
291  ssKey1 << key_begin;
292  ssKey2 << key_end;
293  return EstimateSizeImpl(ssKey1, ssKey2);
294  }
295 };
296 
297 #endif // BITCOIN_DBWRAPPER_H
#define LIFETIMEBOUND
Definition: attributes.h:16
#define Assert(val)
Identity function.
Definition: check.h:77
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:73
void Erase(const K &key)
Definition: dbwrapper.h:111
size_t SizeEstimate() const
Definition: dbwrapper.h:119
const std::unique_ptr< WriteBatchImpl > m_impl_batch
Definition: dbwrapper.h:79
DataStream ssKey
Definition: dbwrapper.h:82
size_t size_estimate
Definition: dbwrapper.h:85
void Write(const K &key, const V &value)
Definition: dbwrapper.h:99
DataStream ssValue
Definition: dbwrapper.h:83
void Clear()
Definition: dbwrapper.cpp:164
CDBBatch(const CDBWrapper &_parent)
Definition: dbwrapper.cpp:158
void WriteImpl(Span< const std::byte > key, DataStream &ssValue)
Definition: dbwrapper.cpp:170
const CDBWrapper & parent
Definition: dbwrapper.h:77
void EraseImpl(Span< const std::byte > key)
Definition: dbwrapper.cpp:186
Span< const std::byte > GetKeyImpl() const
Definition: dbwrapper.cpp:404
CDBIterator(const CDBWrapper &_parent, std::unique_ptr< IteratorImpl > _piter)
Definition: dbwrapper.cpp:390
bool GetValue(V &value)
Definition: dbwrapper.h:167
const std::unique_ptr< IteratorImpl > m_impl_iter
Definition: dbwrapper.h:129
bool GetKey(K &key)
Definition: dbwrapper.h:157
void Seek(const K &key)
Definition: dbwrapper.h:148
const CDBWrapper & parent
Definition: dbwrapper.h:125
bool Valid() const
Definition: dbwrapper.cpp:415
void SeekToFirst()
Definition: dbwrapper.cpp:416
Span< const std::byte > GetValueImpl() const
Definition: dbwrapper.cpp:409
void Next()
Definition: dbwrapper.cpp:417
void SeekImpl(Span< const std::byte > key)
Definition: dbwrapper.cpp:398
CDBWrapper(const CDBWrapper &)=delete
auto & DBContext() const LIFETIMEBOUND
Definition: dbwrapper.h:211
size_t DynamicMemoryUsage() const
Definition: dbwrapper.cpp:308
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:291
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:221
CDBIterator * NewIterator()
Definition: dbwrapper.cpp:393
std::string m_name
the name of this database
Definition: dbwrapper.h:189
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:266
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:241
bool Exists(const K &key) const
Definition: dbwrapper.h:257
std::vector< unsigned char > obfuscate_key
a key used for optional XOR-obfuscation of the database
Definition: dbwrapper.h:192
CDBWrapper & operator=(const CDBWrapper &)=delete
CDBWrapper(const DBParams &params)
Definition: dbwrapper.cpp:221
std::optional< fs::path > StoragePath()
Definition: dbwrapper.h:249
static const unsigned int OBFUSCATE_KEY_NUM_BYTES
the length of the obfuscate key in number of bytes
Definition: dbwrapper.h:198
static const std::string OBFUSCATE_KEY_KEY
the key under which the obfuscation key is stored
Definition: dbwrapper.h:195
const fs::path m_path
path to filesystem storage
Definition: dbwrapper.h:203
std::optional< std::string > ReadImpl(Span< const std::byte > key) const
Definition: dbwrapper.cpp:338
std::unique_ptr< LevelDBContext > m_db_context
holds all leveldb-specific fields of this class
Definition: dbwrapper.h:186
bool m_is_memory
whether or not the database resides in memory
Definition: dbwrapper.h:206
std::vector< unsigned char > CreateObfuscateKey() const
Returns a string (consisting of 8 random bytes) suitable for use as an obfuscating XOR key.
Definition: dbwrapper.cpp:331
bool ExistsImpl(Span< const std::byte > key) const
Definition: dbwrapper.cpp:352
bool IsEmpty()
Return true if the database managed by this class contains no entries.
Definition: dbwrapper.cpp:377
size_t EstimateSizeImpl(Span< const std::byte > key1, Span< const std::byte > key2) const
Definition: dbwrapper.cpp:367
size_t EstimateSize(const K &key_begin, const K &key_end) const
Definition: dbwrapper.h:286
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:147
void reserve(size_type n)
Definition: streams.h:184
void clear()
Definition: streams.h:187
dbwrapper_error(const std::string &msg)
Definition: dbwrapper.h:52
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:33
static const size_t DBWRAPPER_PREALLOC_KEY_SIZE
Definition: dbwrapper.h:23
bool DestroyDB(const std::string &path_str)
Definition: dbwrapper.cpp:37
static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE
Definition: dbwrapper.h:24
These should be considered an implementation detail of the specific database.
Definition: dbwrapper.cpp:419
const std::vector< unsigned char > & GetObfuscateKey(const CDBWrapper &w)
Work around circular dependency, as well as for testing in dbwrapper_tests.
Definition: dbwrapper.cpp:421
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition: span.h:277
User-controlled performance and debug options.
Definition: dbwrapper.h:27
bool force_compact
Compact database on startup.
Definition: dbwrapper.h:29
Application-specific storage settings.
Definition: dbwrapper.h:33
DBOptions options
Passed-through options.
Definition: dbwrapper.h:46
bool obfuscate
If true, store data obfuscated via simple XOR.
Definition: dbwrapper.h:44
bool wipe_data
If true, remove all existing data.
Definition: dbwrapper.h:41
size_t cache_bytes
Configures various leveldb cache settings.
Definition: dbwrapper.h:37
fs::path path
Location in the filesystem where leveldb data will be stored.
Definition: dbwrapper.h:35
bool memory_only
If true, use leveldb's memory environment.
Definition: dbwrapper.h:39