methods to bulk modify the storage, some transaction code hardening, operators to serialize std containers
This commit is contained in:
parent
6ae32e38b6
commit
a79dae8fd0
@ -56,6 +56,7 @@ set(HEADERS
|
|||||||
serializer_stdstring.hpp
|
serializer_stdstring.hpp
|
||||||
serializer_qstring.hpp
|
serializer_qstring.hpp
|
||||||
serializer_qbytearray.hpp
|
serializer_qbytearray.hpp
|
||||||
|
operators.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (BUILD_STATIC)
|
if (BUILD_STATIC)
|
||||||
|
4
cache.h
4
cache.h
@ -45,8 +45,12 @@ public:
|
|||||||
virtual bool checkRecord(const K& key) const override;
|
virtual bool checkRecord(const K& key) const override;
|
||||||
virtual V getRecord(const K& key) const override;
|
virtual V getRecord(const K& key) const override;
|
||||||
virtual uint32_t count() const override;
|
virtual uint32_t count() const override;
|
||||||
|
|
||||||
|
using DataBase::Table<K, V>::drop;
|
||||||
virtual int drop(MDB_txn * transaction) override;
|
virtual int drop(MDB_txn * transaction) override;
|
||||||
virtual std::map<K, V> readAll() const override;
|
virtual std::map<K, V> readAll() const override;
|
||||||
|
virtual void replaceAll(const std::map<K, V>& data) override;
|
||||||
|
virtual uint32_t addRecords(const std::map<K, V>& data, bool overwrite = false) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Mode* mode;
|
Mode* mode;
|
||||||
|
45
cache.hpp
45
cache.hpp
@ -102,11 +102,10 @@ void DataBase::Cache<K, V>::changeRecord(const K& key, const V& value) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Table<K, V>::changeRecord(key, value);
|
Table<K, V>::changeRecord(key, value);
|
||||||
typename std::map<K, V>::iterator itr = cache->find(key);
|
typename std::pair<typename std::map<K, V>::iterator, bool> res = cache->insert(std::make_pair(key, value));
|
||||||
if (itr != cache->end()) {
|
if (!res.second) {
|
||||||
itr->second = value;
|
res.first->second = value;
|
||||||
} else {
|
} else {
|
||||||
cache->insert(std::make_pair(key, value));
|
|
||||||
handleMode();
|
handleMode();
|
||||||
}
|
}
|
||||||
} catch (const NotFound& error) {
|
} catch (const NotFound& error) {
|
||||||
@ -188,6 +187,44 @@ std::map<K, V> DataBase::Cache<K, V>::readAll() const {
|
|||||||
return *cache;
|
return *cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class K, class V>
|
||||||
|
void DataBase::Cache<K, V>::replaceAll(const std::map<K, V>& data) {
|
||||||
|
DataBase::Table<K, V>::replaceAll(data);
|
||||||
|
*cache = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class K, class V>
|
||||||
|
uint32_t DataBase::Cache<K, V>::addRecords(const std::map<K, V>& data, bool overwrite) {
|
||||||
|
uint32_t newSize = DataBase::Table<K, V>::addRecords(data, overwrite);
|
||||||
|
|
||||||
|
Mode& m = *mode;
|
||||||
|
if (m == Mode::nothing) {
|
||||||
|
m = Mode::size;
|
||||||
|
}
|
||||||
|
std::map<K, V>& c = *cache;
|
||||||
|
std::set<K>& a = *abscent;
|
||||||
|
for (const std::pair<const K, V>& pair : data) {
|
||||||
|
std::pair<typename std::map<K, V>::iterator, bool> res = c.insert(pair);
|
||||||
|
if (!res.second) {
|
||||||
|
if (overwrite) {
|
||||||
|
res.first->second = pair.second;
|
||||||
|
}
|
||||||
|
} else if (m != Mode::full) {
|
||||||
|
a.erase(pair.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m != Mode::full) {
|
||||||
|
*sizeDifference = newSize - c.size();
|
||||||
|
if (*sizeDifference == 0) {
|
||||||
|
*mode = Mode::full;
|
||||||
|
abscent->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newSize;
|
||||||
|
}
|
||||||
|
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void DataBase::Cache<K, V>::removeRecord(const K& key) {
|
void DataBase::Cache<K, V>::removeRecord(const K& key) {
|
||||||
if (!DataBase::Table<K, V>::db->opened) {
|
if (!DataBase::Table<K, V>::db->opened) {
|
||||||
|
@ -80,6 +80,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
#include "operators.hpp"
|
||||||
|
|
||||||
template <class K, class V>
|
template <class K, class V>
|
||||||
DataBase::Table<K, V>* DataBase::addTable(const std::string& p_name) {
|
DataBase::Table<K, V>* DataBase::addTable(const std::string& p_name) {
|
||||||
|
209
operators.hpp
Normal file
209
operators.hpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef CORE_OPERATORS_HPP
|
||||||
|
#define CORE_OPERATORS_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
template <class K, class V>
|
||||||
|
QDataStream& operator << (QDataStream &out, const std::map<K, V>& container) {
|
||||||
|
uint32_t size = container.size();
|
||||||
|
out << size;
|
||||||
|
for (const std::pair<const K, V>& pair : container) {
|
||||||
|
out << pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K, class V>
|
||||||
|
QDataStream& operator >> (QDataStream &in, std::map<K, V>& container) {
|
||||||
|
uint32_t size;
|
||||||
|
in >> size;
|
||||||
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
|
std::pair<K, V> pair;
|
||||||
|
in >> pair;
|
||||||
|
container.insert(pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K, class V>
|
||||||
|
QDataStream& operator << (QDataStream &out, const std::multimap<K, V>& container) {
|
||||||
|
uint32_t size = container.size();
|
||||||
|
out << size;
|
||||||
|
for (const std::pair<const K, V>& pair : container) {
|
||||||
|
out << pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K, class V>
|
||||||
|
QDataStream& operator >> (QDataStream &in, std::multimap<K, V>& container) {
|
||||||
|
uint32_t size;
|
||||||
|
in >> size;
|
||||||
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
|
std::pair<K, V> pair;
|
||||||
|
in >> pair;
|
||||||
|
container.insert(pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K, class V>
|
||||||
|
QDataStream& operator << (QDataStream &out, const std::pair<K, V>& pair) {
|
||||||
|
out << pair.first;
|
||||||
|
out << pair.second;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K, class V>
|
||||||
|
QDataStream& operator >> (QDataStream &in, std::pair<K, V>& container) {
|
||||||
|
in >> container.first;
|
||||||
|
in >> container.second;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator << (QDataStream &out, const std::set<K>& container) {
|
||||||
|
uint32_t size = container.size();
|
||||||
|
out << size;
|
||||||
|
for (const K& value : container) {
|
||||||
|
out << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator >> (QDataStream &in, std::set<K>& container) {
|
||||||
|
uint32_t size;
|
||||||
|
in >> size;
|
||||||
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
|
K value;
|
||||||
|
in >> value;
|
||||||
|
container.insert(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator << (QDataStream &out, const std::multiset<K>& container) {
|
||||||
|
uint32_t size = container.size();
|
||||||
|
out << size;
|
||||||
|
for (const K& value : container) {
|
||||||
|
out << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator >> (QDataStream &in, std::multiset<K>& container) {
|
||||||
|
uint32_t size;
|
||||||
|
in >> size;
|
||||||
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
|
K value;
|
||||||
|
in >> value;
|
||||||
|
container.insert(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator << (QDataStream &out, const std::vector<K>& container) {
|
||||||
|
uint32_t size = container.size();
|
||||||
|
out << size;
|
||||||
|
for (const K& value : container) {
|
||||||
|
out << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator >> (QDataStream &in, std::vector<K>& container) {
|
||||||
|
uint32_t size;
|
||||||
|
in >> size;
|
||||||
|
container.resize(size);
|
||||||
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
|
in >> container[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator << (QDataStream &out, const std::deque<K>& container) {
|
||||||
|
uint32_t size = container.size();
|
||||||
|
out << size;
|
||||||
|
for (const K& value : container) {
|
||||||
|
out << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator >> (QDataStream &in, std::deque<K>& container) {
|
||||||
|
uint32_t size;
|
||||||
|
in >> size;
|
||||||
|
container.resize(size);
|
||||||
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
|
in >> container[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator << (QDataStream &out, const std::list<K>& container) {
|
||||||
|
uint32_t size = container.size();
|
||||||
|
out << size;
|
||||||
|
for (const K& value : container) {
|
||||||
|
out << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
QDataStream& operator >> (QDataStream &in, std::list<K>& container) {
|
||||||
|
uint32_t size;
|
||||||
|
in >> size;
|
||||||
|
for (uint32_t i = 0; i < size; ++i) {
|
||||||
|
typename std::list<K>::iterator itr = container.emplace(container.end());
|
||||||
|
in >> *itr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //CORE_OPERATORS_HPP
|
@ -35,10 +35,12 @@ void DataBase::_Table::drop()
|
|||||||
MDB_txn *txn;
|
MDB_txn *txn;
|
||||||
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
throw Unknown(db->name, mdb_strerror(rc), name);
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
}
|
}
|
||||||
rc = drop(txn);
|
rc = drop(txn);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
throw Unknown(db->name, mdb_strerror(rc), name);
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +63,7 @@ uint32_t DataBase::_Table::count() const
|
|||||||
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
rc = mdb_stat(txn, dbi, &stat);
|
rc = mdb_stat(txn, dbi, &stat);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
throw Unknown(db->name, mdb_strerror(rc), name);
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
}
|
}
|
||||||
uint32_t amount = stat.ms_entries;
|
uint32_t amount = stat.ms_entries;
|
||||||
|
3
table.h
3
table.h
@ -54,6 +54,7 @@ protected:
|
|||||||
~Table() override;
|
~Table() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using DataBase::_Table::drop;
|
||||||
virtual void addRecord(const K& key, const V& value);
|
virtual void addRecord(const K& key, const V& value);
|
||||||
virtual bool forceRecord(const K& key, const V& value); //returns true if there was addition, false if change
|
virtual bool forceRecord(const K& key, const V& value); //returns true if there was addition, false if change
|
||||||
virtual void changeRecord(const K& key, const V& value);
|
virtual void changeRecord(const K& key, const V& value);
|
||||||
@ -61,6 +62,8 @@ public:
|
|||||||
virtual bool checkRecord(const K& key) const; //checks if there is a record with given key
|
virtual bool checkRecord(const K& key) const; //checks if there is a record with given key
|
||||||
virtual V getRecord(const K& key) const;
|
virtual V getRecord(const K& key) const;
|
||||||
virtual std::map<K, V> readAll() const;
|
virtual std::map<K, V> readAll() const;
|
||||||
|
virtual void replaceAll(const std::map<K, V>& data);
|
||||||
|
virtual uint32_t addRecords(const std::map<K, V>& data, bool overwrite = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Serializer<K>* keySerializer;
|
Serializer<K>* keySerializer;
|
||||||
|
113
table.hpp
113
table.hpp
@ -43,8 +43,12 @@ void DataBase::Table<K, V>::addRecord(const K& key, const V& value) {
|
|||||||
MDB_val lmdbKey = keySerializer->setData(key);
|
MDB_val lmdbKey = keySerializer->setData(key);
|
||||||
MDB_val lmdbData = valueSerializer->setData(value);
|
MDB_val lmdbData = valueSerializer->setData(value);
|
||||||
MDB_txn *txn;
|
MDB_txn *txn;
|
||||||
mdb_txn_begin(db->environment, NULL, 0, &txn);
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
int rc;
|
if (rc != MDB_SUCCESS) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
|
||||||
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, MDB_NOOVERWRITE);
|
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, MDB_NOOVERWRITE);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
mdb_txn_abort(txn);
|
mdb_txn_abort(txn);
|
||||||
@ -68,8 +72,12 @@ bool DataBase::Table<K, V>::forceRecord(const K& key, const V& value) {
|
|||||||
MDB_val lmdbKey = keySerializer->setData(key);
|
MDB_val lmdbKey = keySerializer->setData(key);
|
||||||
MDB_val lmdbData;
|
MDB_val lmdbData;
|
||||||
MDB_txn *txn;
|
MDB_txn *txn;
|
||||||
mdb_txn_begin(db->environment, NULL, 0, &txn);
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
int rc;
|
if (rc != MDB_SUCCESS) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
|
||||||
rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
added = false;
|
added = false;
|
||||||
@ -100,8 +108,13 @@ void DataBase::Table<K, V>::changeRecord(const K& key, const V& value) {
|
|||||||
MDB_val lmdbKey = keySerializer->setData(key);
|
MDB_val lmdbKey = keySerializer->setData(key);
|
||||||
MDB_val lmdbData = valueSerializer->setData(value);
|
MDB_val lmdbData = valueSerializer->setData(value);
|
||||||
MDB_txn *txn;
|
MDB_txn *txn;
|
||||||
mdb_txn_begin(db->environment, NULL, 0, &txn);
|
|
||||||
int rc;
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
|
if (rc != MDB_SUCCESS) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
|
||||||
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, 0);
|
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, 0);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
mdb_txn_abort(txn);
|
mdb_txn_abort(txn);
|
||||||
@ -123,8 +136,12 @@ V DataBase::Table<K, V>::getRecord(const K& key) const {
|
|||||||
MDB_val lmdbData;
|
MDB_val lmdbData;
|
||||||
|
|
||||||
MDB_txn *txn;
|
MDB_txn *txn;
|
||||||
int rc;
|
int rc = mdb_txn_begin(db->environment, NULL, MDB_RDONLY, &txn);
|
||||||
mdb_txn_begin(db->environment, NULL, MDB_RDONLY, &txn);
|
if (rc != MDB_SUCCESS) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
|
||||||
rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
mdb_txn_abort(txn);
|
mdb_txn_abort(txn);
|
||||||
@ -151,8 +168,12 @@ bool DataBase::Table<K, V>::checkRecord(const K& key) const {
|
|||||||
MDB_val lmdbData;
|
MDB_val lmdbData;
|
||||||
|
|
||||||
MDB_txn *txn;
|
MDB_txn *txn;
|
||||||
int rc;
|
int rc = mdb_txn_begin(db->environment, NULL, MDB_RDONLY, &txn);
|
||||||
mdb_txn_begin(db->environment, NULL, MDB_RDONLY, &txn);
|
if (rc != MDB_SUCCESS) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
|
||||||
rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
|
||||||
mdb_txn_abort(txn);
|
mdb_txn_abort(txn);
|
||||||
|
|
||||||
@ -179,10 +200,12 @@ std::map<K, V> DataBase::Table<K, V>::readAll() const {
|
|||||||
MDB_val lmdbKey, lmdbData;
|
MDB_val lmdbKey, lmdbData;
|
||||||
int rc = mdb_txn_begin(db->environment, NULL, MDB_RDONLY, &txn);
|
int rc = mdb_txn_begin(db->environment, NULL, MDB_RDONLY, &txn);
|
||||||
if (rc != MDB_SUCCESS) {
|
if (rc != MDB_SUCCESS) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
throw Unknown(db->name, mdb_strerror(rc), name);
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
}
|
}
|
||||||
rc = mdb_cursor_open(txn, dbi, &cursor);
|
rc = mdb_cursor_open(txn, dbi, &cursor);
|
||||||
if (rc != MDB_SUCCESS) {
|
if (rc != MDB_SUCCESS) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
throw Unknown(db->name, mdb_strerror(rc), name);
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
}
|
}
|
||||||
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_FIRST);
|
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_FIRST);
|
||||||
@ -193,6 +216,7 @@ std::map<K, V> DataBase::Table<K, V>::readAll() const {
|
|||||||
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_NEXT);
|
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_NEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mdb_txn_abort(txn);
|
||||||
if (rc != MDB_NOTFOUND) {
|
if (rc != MDB_NOTFOUND) {
|
||||||
throw Unknown(db->name, mdb_strerror(rc), name);
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
}
|
}
|
||||||
@ -200,6 +224,75 @@ std::map<K, V> DataBase::Table<K, V>::readAll() const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class K, class V>
|
||||||
|
void DataBase::Table<K, V>::replaceAll(const std::map<K, V>& data) {
|
||||||
|
if (!db->opened) {
|
||||||
|
throw Closed("replaceAll", db->name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_txn *txn;
|
||||||
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
|
if (rc) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
rc = drop(txn);
|
||||||
|
if (rc) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_val lmdbKey, lmdbData;
|
||||||
|
for (const std::pair<const K, V>& pair : data) {
|
||||||
|
lmdbKey = keySerializer->setData(pair.first);
|
||||||
|
lmdbData = valueSerializer->setData(pair.second);
|
||||||
|
|
||||||
|
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, MDB_NOOVERWRITE);
|
||||||
|
if (rc != 0) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mdb_txn_commit(txn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class K, class V>
|
||||||
|
uint32_t DataBase::Table<K, V>::addRecords(const std::map<K, V>& data, bool overwrite) {
|
||||||
|
if (!db->opened) {
|
||||||
|
throw Closed("addRecords", db->name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_txn *txn;
|
||||||
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
|
if (rc) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_val lmdbKey, lmdbData;
|
||||||
|
for (const std::pair<const K, V>& pair : data) {
|
||||||
|
lmdbKey = keySerializer->setData(pair.first);
|
||||||
|
lmdbData = valueSerializer->setData(pair.second);
|
||||||
|
|
||||||
|
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, overwrite ? 0 : MDB_NOOVERWRITE);
|
||||||
|
if (rc != 0) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_stat stat;
|
||||||
|
rc = mdb_stat(txn, dbi, &stat);
|
||||||
|
if (rc) {
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
uint32_t amount = stat.ms_entries;
|
||||||
|
|
||||||
|
mdb_txn_commit(txn);
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
template<class K, class V>
|
template<class K, class V>
|
||||||
void DataBase::Table<K, V>::removeRecord(const K& key) {
|
void DataBase::Table<K, V>::removeRecord(const K& key) {
|
||||||
if (!db->opened) {
|
if (!db->opened) {
|
||||||
|
Loading…
Reference in New Issue
Block a user