5 #ifndef PIVX_DBWRAPPER_H
6 #define PIVX_DBWRAPPER_H
17 #include <leveldb/db.h>
18 #include <leveldb/write_batch.h>
21 static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
22 static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
68 template <
typename K,
typename V>
69 void Write(
const K& key,
const V& value)
80 leveldb::Slice slKey(_ssKey.
data(), _ssKey.
size());
86 batch.Put(slKey, slValue);
95 size_estimate += 3 + (slKey.size() > 127) + slKey.size() + (slValue.size() > 127) + slValue.size();
110 leveldb::Slice slKey(_ssKey.
data(), _ssKey.
size());
143 template<
typename K>
void Seek(
const K& key)
146 ssKey.
reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
153 leveldb::Slice slKey(ssKey.
data(), ssKey.
size());
164 }
catch(
const std::exception& e) {
172 leveldb::Slice slKey =
piter->key();
178 leveldb::Slice slValue =
piter->value();
182 }
catch(
const std::exception& e) {
190 return piter->value().size();
230 CDBWrapper(
const fs::path& path,
size_t nCacheSize,
bool fMemory =
false,
bool fWipe =
false,
int nVersion = CLIENT_VERSION);
233 template <
typename K>
237 ssKey.
reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
244 leveldb::Slice slKey(ssKey.
data(), ssKey.
size());
246 std::string strValue;
249 if (status.IsNotFound())
251 LogPrintf(
"LevelDB read failure: %s\n", status.ToString());
255 ssValue = std::move(ssValueTmp);
259 template <
typename K,
typename V>
260 bool Read(
const K& key, V& value)
const
263 ssKey.
reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
265 return Read(ssKey, value);
268 template <
typename V>
277 }
catch (
const std::exception&) {
283 template <
typename K,
typename V>
284 bool Write(
const K& key,
const V& value,
bool fSync =
false)
287 batch.
Write(key, value);
291 template <
typename K>
295 ssKey.
reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
302 leveldb::Slice slKey(key.
data(), key.
size());
304 std::string strValue;
307 if (status.IsNotFound())
309 LogPrintf(
"LevelDB read failure: %s\n", status.ToString());
315 template <
typename K>
316 bool Erase(
const K& key,
bool fSync =
false)
352 ssKey1.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
353 ssKey2.
reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
356 leveldb::Slice slKey1(&ssKey1[0], ssKey1.size());
357 leveldb::Slice slKey2(&ssKey2[0], ssKey2.
size());
359 leveldb::Range range(slKey1, slKey2);
360 pdb->GetApproximateSizes(&range, 1, &size);
371 ssKey1.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
372 ssKey2.
reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
375 leveldb::Slice slKey1(ssKey1.data(), ssKey1.size());
376 leveldb::Slice slKey2(ssKey2.
data(), ssKey2.
size());
377 pdb->CompactRange(&slKey1, &slKey2);
382 pdb->CompactRange(
nullptr,
nullptr);
387 template<
typename CDBTransaction>
471 }
catch (
const std::exception&) {
531 template<
typename Parent,
typename CommitTarget>
543 return std::lexicographical_compare(
544 (
const uint8_t*)a.
data(), (
const uint8_t*)a.
data() + a.
size(),
545 (
const uint8_t*)b.
data(), (
const uint8_t*)b.
data() + b.
size());
558 template <
typename V>
571 template <
typename K>
575 ssKey.
reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
580 typedef std::map<CDataStream, ValueHolderPtr, DataStreamCmp>
WritesMap;
590 template <
typename K,
typename V>
591 void Write(
const K& key,
const V& v)
596 template <
typename V>
603 auto it =
writes.emplace(ssKey,
nullptr).first;
607 it->second = std::make_unique<ValueHolderImpl<V>>(v, valueMemoryUsage);
612 template <
typename K,
typename V>
613 bool Read(
const K& key, V& value)
618 template <
typename V>
625 auto it =
writes.find(ssKey);
629 throw std::runtime_error(
"Read called with V != previously written type");
635 return parent.Read(ssKey, value);
638 template <
typename K>
650 if (
writes.count(ssKey)) {
654 return parent.Exists(ssKey);
657 template <
typename K>
665 auto it =
writes.find(ssKey);
670 if (
deletes.emplace(ssKey).second) {
684 for (
const auto &k :
deletes) {
702 static volatile bool didPrint =
false;
704 LogPrintf(
"CDBTransaction::%s -- negative memoryUsage (%d)", __func__,
memoryUsage);
718 return std::make_unique<CDBTransactionIterator<CDBTransaction>>(*
this,
nVersion);
void reserve(size_type n)
Batch of changes queued to be written to a CDBWrapper.
void Write(const CDataStream &_ssKey, const V &value)
void Erase(const CDataStream &_ssKey)
size_t SizeEstimate() const
void Write(const K &key, const V &value)
leveldb::WriteBatch batch
unsigned int GetValueSize()
leveldb::Iterator * piter
void Seek(const CDataStream &ssKey)
CDBIterator(leveldb::Iterator *_piter, int _nVersion)
void Write(const K &key, const V &v)
std::unique_ptr< ValueHolder > ValueHolderPtr
bool Exists(const K &key)
std::map< CDataStream, ValueHolderPtr, DataStreamCmp > WritesMap
bool Read(const CDataStream &ssKey, V &value)
CommitTarget & commitTarget
CDBTransaction(Parent &_parent, CommitTarget &_commitTarget, int _nVersion)
static CDataStream KeyToDataStream(const K &key, int nVersion)
void Write(const CDataStream &ssKey, const V &v)
std::set< CDataStream, DataStreamCmp > DeletesSet
CDBTransactionIterator< CDBTransaction > * NewIterator()
void Erase(const CDataStream &ssKey)
bool Read(const K &key, V &value)
std::unique_ptr< CDBTransactionIterator< CDBTransaction > > NewIteratorUniquePtr()
bool Exists(const CDataStream &ssKey)
friend class CDBTransactionIterator< CDBTransaction >
size_t GetMemoryUsage() const
CDBTransactionIterator(CDBTransaction &_transaction, int _nVersion)
void Seek(const CDataStream &ssKey)
std::unique_ptr< ParentIterator > parentIt
CDBTransaction::WritesMap::iterator transactionIt
void SkipDeletedAndOverwritten()
CDBTransaction & transaction
std::remove_pointer< decltype(transaction.parent.NewIterator())>::type ParentIterator
CDBIterator * NewIterator()
bool Exists(const CDataStream &key) const
leveldb::Env * penv
custom environment this database is using (may be nullptr in case of default environment)
bool WriteBatch(CDBBatch &batch, bool fSync=false)
bool Read(const K &key, V &value) const
CDBWrapper(const fs::path &path, size_t nCacheSize, bool fMemory=false, bool fWipe=false, int nVersion=CLIENT_VERSION)
bool Erase(const K &key, bool fSync=false)
bool ReadDataStream(const K &key, CDataStream &ssValue) const
bool Write(const K &key, const V &value, bool fSync=false)
bool Exists(const K &key) const
bool Read(const CDataStream &ssKey, V &value) const
leveldb::Options options
database options used
bool ReadDataStream(const CDataStream &ssKey, CDataStream &ssValue) const
leveldb::WriteOptions writeoptions
options used when writing to the database
leveldb::WriteOptions syncoptions
options used when sync writing to the database
int nVersion
the version used to serialize data
leveldb::DB * pdb
the database itself
leveldb::ReadOptions iteroptions
options used when iterating over values of the database
void CompactRange(const K &key_begin, const K &key_end) const
Compact a certain range of keys in the database.
bool IsEmpty()
Return true if the database managed by this class contains no entries.
leveldb::ReadOptions readoptions
options used when reading from the database
size_t EstimateSize(const K &key_begin, const K &key_end) const
dbwrapper_error(const std::string &msg)
These should be considered an implementation detail of the specific database.
void HandleError(const leveldb::Status &status)
Handle database error by throwing dbwrapper_error exception.
unsigned int GetSerializeSize(const std::array< T, N > &item)
array
bool operator()(const CDataStream &a, const CDataStream &b) const
static bool less(const CDataStream &a, const CDataStream &b)
ValueHolder(size_t _memoryUsage)
virtual void Write(const CDataStream &ssKey, CommitTarget &parent)=0
virtual ~ValueHolder()=default
ValueHolderImpl(const V &_value, size_t _memoryUsage)
virtual void Write(const CDataStream &ssKey, CommitTarget &commitTarget)