Bitcoin Core  29.1.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 static const size_t DBWRAPPER_MAX_FILE_SIZE = 32 << 20; // 32 MiB
26 
28 struct DBOptions {
30  bool force_compact = false;
31 };
32 
34 struct DBParams {
38  size_t cache_bytes;
40  bool memory_only = false;
42  bool wipe_data = false;
45  bool obfuscate = false;
48 };
49 
50 class dbwrapper_error : public std::runtime_error
51 {
52 public:
53  explicit dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
54 };
55 
56 class CDBWrapper;
57 
60 namespace dbwrapper_private {
61 
66 const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w);
67 
68 }; // namespace dbwrapper_private
69 
70 bool DestroyDB(const std::string& path_str);
71 
73 class CDBBatch
74 {
75  friend class CDBWrapper;
76 
77 private:
79 
81  const std::unique_ptr<WriteBatchImpl> m_impl_batch;
82 
85 
86  size_t size_estimate{0};
87 
90 
91 public:
95  explicit CDBBatch(const CDBWrapper& _parent);
96  ~CDBBatch();
97  void Clear();
98 
99  template <typename K, typename V>
100  void Write(const K& key, const V& value)
101  {
104  ssKey << key;
105  ssValue << value;
107  ssKey.clear();
108  ssValue.clear();
109  }
110 
111  template <typename K>
112  void Erase(const K& key)
113  {
115  ssKey << key;
116  EraseImpl(ssKey);
117  ssKey.clear();
118  }
119 
120  size_t SizeEstimate() const { return size_estimate; }
121 };
122 
124 {
125 public:
126  struct IteratorImpl;
127 
128 private:
129  const CDBWrapper &parent;
130  const std::unique_ptr<IteratorImpl> m_impl_iter;
131 
135 
136 public:
137 
142  CDBIterator(const CDBWrapper& _parent, std::unique_ptr<IteratorImpl> _piter);
143  ~CDBIterator();
144 
145  bool Valid() const;
146 
147  void SeekToFirst();
148 
149  template<typename K> void Seek(const K& key) {
150  DataStream ssKey{};
152  ssKey << key;
153  SeekImpl(ssKey);
154  }
155 
156  void Next();
157 
158  template<typename K> bool GetKey(K& key) {
159  try {
160  DataStream ssKey{GetKeyImpl()};
161  ssKey >> key;
162  } catch (const std::exception&) {
163  return false;
164  }
165  return true;
166  }
167 
168  template<typename V> bool GetValue(V& value) {
169  try {
170  DataStream ssValue{GetValueImpl()};
172  ssValue >> value;
173  } catch (const std::exception&) {
174  return false;
175  }
176  return true;
177  }
178 };
179 
180 struct LevelDBContext;
181 
183 {
184  friend const std::vector<unsigned char>& dbwrapper_private::GetObfuscateKey(const CDBWrapper &w);
185 private:
187  std::unique_ptr<LevelDBContext> m_db_context;
188 
190  std::string m_name;
191 
193  std::vector<unsigned char> obfuscate_key;
194 
196  static const std::string OBFUSCATE_KEY_KEY;
197 
199  static const unsigned int OBFUSCATE_KEY_NUM_BYTES;
200 
201  std::vector<unsigned char> CreateObfuscateKey() const;
202 
205 
208 
209  std::optional<std::string> ReadImpl(Span<const std::byte> key) const;
210  bool ExistsImpl(Span<const std::byte> key) const;
212  auto& DBContext() const LIFETIMEBOUND { return *Assert(m_db_context); }
213 
214 public:
215  CDBWrapper(const DBParams& params);
216  ~CDBWrapper();
217 
218  CDBWrapper(const CDBWrapper&) = delete;
219  CDBWrapper& operator=(const CDBWrapper&) = delete;
220 
221  template <typename K, typename V>
222  bool Read(const K& key, V& value) const
223  {
224  DataStream ssKey{};
226  ssKey << key;
227  std::optional<std::string> strValue{ReadImpl(ssKey)};
228  if (!strValue) {
229  return false;
230  }
231  try {
232  DataStream ssValue{MakeByteSpan(*strValue)};
233  ssValue.Xor(obfuscate_key);
234  ssValue >> value;
235  } catch (const std::exception&) {
236  return false;
237  }
238  return true;
239  }
240 
241  template <typename K, typename V>
242  bool Write(const K& key, const V& value, bool fSync = false)
243  {
244  CDBBatch batch(*this);
245  batch.Write(key, value);
246  return WriteBatch(batch, fSync);
247  }
248 
250  std::optional<fs::path> StoragePath() {
251  if (m_is_memory) {
252  return {};
253  }
254  return m_path;
255  }
256 
257  template <typename K>
258  bool Exists(const K& key) const
259  {
260  DataStream ssKey{};
262  ssKey << key;
263  return ExistsImpl(ssKey);
264  }
265 
266  template <typename K>
267  bool Erase(const K& key, bool fSync = false)
268  {
269  CDBBatch batch(*this);
270  batch.Erase(key);
271  return WriteBatch(batch, fSync);
272  }
273 
274  bool WriteBatch(CDBBatch& batch, bool fSync = false);
275 
276  // Get an estimate of LevelDB memory usage (in bytes).
277  size_t DynamicMemoryUsage() const;
278 
280 
284  bool IsEmpty();
285 
286  template<typename K>
287  size_t EstimateSize(const K& key_begin, const K& key_end) const
288  {
289  DataStream ssKey1{}, ssKey2{};
291  ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
292  ssKey1 << key_begin;
293  ssKey2 << key_end;
294  return EstimateSizeImpl(ssKey1, ssKey2);
295  }
296 };
297 
298 #endif // BITCOIN_DBWRAPPER_H
bool Exists(const K &key) const
Definition: dbwrapper.h:258
bool GetKey(K &key)
Definition: dbwrapper.h:158
dbwrapper_error(const std::string &msg)
Definition: dbwrapper.h:53
fs::path path
Location in the filesystem where leveldb data will be stored.
Definition: dbwrapper.h:36
These should be considered an implementation detail of the specific database.
Definition: dbwrapper.cpp:420
void Clear()
Definition: dbwrapper.cpp:165
void reserve(size_type n)
Definition: streams.h:184
static const size_t DBWRAPPER_MAX_FILE_SIZE
Definition: dbwrapper.h:25
void SeekToFirst()
Definition: dbwrapper.cpp:417
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:73
auto & DBContext() const LIFETIMEBOUND
Definition: dbwrapper.h:212
Span< const std::byte > GetValueImpl() const
Definition: dbwrapper.cpp:410
size_t size_estimate
Definition: dbwrapper.h:86
void Erase(const K &key)
Definition: dbwrapper.h:112
static const size_t DBWRAPPER_PREALLOC_KEY_SIZE
Definition: dbwrapper.h:23
Span< const std::byte > GetKeyImpl() const
Definition: dbwrapper.cpp:405
bool DestroyDB(const std::string &path_str)
Definition: dbwrapper.cpp:37
const std::unique_ptr< IteratorImpl > m_impl_iter
Definition: dbwrapper.h:130
DBOptions options
Passed-through options.
Definition: dbwrapper.h:47
User-controlled performance and debug options.
Definition: dbwrapper.h:28
CDBIterator(const CDBWrapper &_parent, std::unique_ptr< IteratorImpl > _piter)
Definition: dbwrapper.cpp:391
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:332
std::optional< fs::path > StoragePath()
Definition: dbwrapper.h:250
size_t EstimateSizeImpl(Span< const std::byte > key1, Span< const std::byte > key2) const
Definition: dbwrapper.cpp:368
size_t DynamicMemoryUsage() const
Definition: dbwrapper.cpp:309
const CDBWrapper & parent
Definition: dbwrapper.h:126
bool GetValue(V &value)
Definition: dbwrapper.h:168
DataStream ssValue
Definition: dbwrapper.h:84
const CDBWrapper & parent
Definition: dbwrapper.h:78
CDBWrapper & operator=(const CDBWrapper &)=delete
#define LIFETIMEBOUND
Definition: attributes.h:16
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:267
CDBWrapper(const DBParams &params)
Definition: dbwrapper.cpp:222
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:146
CDBIterator * NewIterator()
Definition: dbwrapper.cpp:394
void Write(const K &key, const V &value)
Definition: dbwrapper.h:100
size_t SizeEstimate() const
Definition: dbwrapper.h:120
void EraseImpl(Span< const std::byte > key)
Definition: dbwrapper.cpp:187
bool m_is_memory
whether or not the database resides in memory
Definition: dbwrapper.h:207
bool wipe_data
If true, remove all existing data.
Definition: dbwrapper.h:42
bool IsEmpty()
Return true if the database managed by this class contains no entries.
Definition: dbwrapper.cpp:378
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:222
const fs::path m_path
path to filesystem storage
Definition: dbwrapper.h:204
bool force_compact
Compact database on startup.
Definition: dbwrapper.h:30
bool obfuscate
If true, store data obfuscated via simple XOR.
Definition: dbwrapper.h:45
const std::vector< unsigned char > & GetObfuscateKey(const CDBWrapper &w)
Work around circular dependency, as well as for testing in dbwrapper_tests.
Definition: dbwrapper.cpp:422
void Next()
Definition: dbwrapper.cpp:418
static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE
Definition: dbwrapper.h:24
static const unsigned int OBFUSCATE_KEY_NUM_BYTES
the length of the obfuscate key in number of bytes
Definition: dbwrapper.h:199
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:242
void SeekImpl(Span< const std::byte > key)
Definition: dbwrapper.cpp:399
std::string m_name
the name of this database
Definition: dbwrapper.h:190
void clear()
Definition: streams.h:187
std::unique_ptr< LevelDBContext > m_db_context
holds all leveldb-specific fields of this class
Definition: dbwrapper.h:187
static const std::string OBFUSCATE_KEY_KEY
the key under which the obfuscation key is stored
Definition: dbwrapper.h:196
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition: span.h:269
void WriteImpl(Span< const std::byte > key, DataStream &ssValue)
Definition: dbwrapper.cpp:171
void Seek(const K &key)
Definition: dbwrapper.h:149
Application-specific storage settings.
Definition: dbwrapper.h:34
CDBBatch(const CDBWrapper &_parent)
Definition: dbwrapper.cpp:159
bool Valid() const
Definition: dbwrapper.cpp:416
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:292
bool ExistsImpl(Span< const std::byte > key) const
Definition: dbwrapper.cpp:353
size_t cache_bytes
Configures various leveldb cache settings.
Definition: dbwrapper.h:38
const std::unique_ptr< WriteBatchImpl > m_impl_batch
Definition: dbwrapper.h:80
std::vector< unsigned char > obfuscate_key
a key used for optional XOR-obfuscation of the database
Definition: dbwrapper.h:193
size_t EstimateSize(const K &key_begin, const K &key_end) const
Definition: dbwrapper.h:287
std::optional< std::string > ReadImpl(Span< const std::byte > key) const
Definition: dbwrapper.cpp:339
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:32
bool memory_only
If true, use leveldb&#39;s memory environment.
Definition: dbwrapper.h:40
#define Assert(val)
Identity function.
Definition: check.h:85
DataStream ssKey
Definition: dbwrapper.h:83