22#include "exceptions.h"
24#define UNUSED(x) (void)(x)
47template<
class K,
class V>
58template<
class K,
class V>
60 for (
const std::pair<
const uint32_t,
Cursor<K, V>*>& pair : cursors)
61 pair.second->dropped();
78template<
class K,
class V>
80 ensureOpened(addRecordMethodName);
81 TransactionID txn = beginTransaction();
85 abortTransaction(txn);
89 commitTransaction(txn);
106template<
class K,
class V>
108 MDB_val lmdbKey = keySerializer.setData(key);
109 MDB_val lmdbData = valueSerializer.setData(value);
111 unsigned int flags = 0;
113 flags |= MDB_NODUPDATA;
115 flags |= MDB_NOOVERWRITE;
117 int rc = _mdbPut(txn, lmdbKey, lmdbData, flags);
118 if (rc != MDB_SUCCESS)
119 throwDuplicateOrUnknown(rc, toString(key));
141template<
class K,
class V>
143 ensureOpened(addRecordMethodName);
144 addRecord(key, value, extractTransactionId(txn, addRecordMethodName));
163template<
class K,
class V>
165 ensureOpened(forceRecordMethodName);
167 TransactionID txn = beginTransaction();
172 abortTransaction(txn);
176 commitTransaction(txn);
197template<
class K,
class V>
202 addRecord(key, value, txn);
208 MDB_val lmdbKey = keySerializer.setData(key);
211 int rc = _mdbGet(txn, lmdbKey, lmdbData);
224 lmdbData = valueSerializer.setData(value);
225 rc = _mdbPut(txn, lmdbKey, lmdbData);
226 if (rc != MDB_SUCCESS)
253template<
class K,
class V>
255 ensureOpened(forceRecordMethodName);
256 return forceRecord(key, value, extractTransactionId(txn, forceRecordMethodName));
278template<
class K,
class V>
280 ensureOpened(changeRecordMethodName);
282 TransactionID txn = beginTransaction();
286 abortTransaction(txn);
290 commitTransaction(txn);
313template<
class K,
class V>
316 int rc = _mdbCursorOpen(txn, &cursor);
317 if (rc != MDB_SUCCESS)
320 MDB_val lmdbKey = keySerializer.setData(key);
322 rc = _mdbCursorGet(cursor, lmdbKey, lmdbData, MDB_SET);
323 if (rc != MDB_SUCCESS)
324 throwNotFoundOrUnknown(rc, toString(key));
326 MDB_val lmdbNewData = valueSerializer.setData(value);
327 bool sameSize = lmdbData.mv_size == lmdbNewData.mv_size;
328 int firstDifferentByte = 0;
330 firstDifferentByte = memcmp(lmdbData.mv_data, lmdbNewData.mv_data, lmdbData.mv_size);
331 if (firstDifferentByte == 0) {
332 _mdbCursorClose(cursor);
337 unsigned int flags = MDB_CURRENT;
338 if (duplicates && (!sameSize || firstDifferentByte < 0)) {
339 rc = _mdbCursorDel(cursor);
340 flags = MDB_NODUPDATA;
343 if (rc == MDB_SUCCESS)
344 rc = _mdbCursorPut(cursor, lmdbKey, lmdbNewData, flags);
346 _mdbCursorClose(cursor);
347 if (rc != MDB_SUCCESS)
348 throwDuplicateOrUnknown(rc, toString(key));
376template<
class K,
class V>
378 ensureOpened(changeRecordMethodName);
379 changeRecord(key, value, extractTransactionId(txn, changeRecordMethodName));
400template<
class K,
class V>
402 ensureOpened(getRecordMethodName);
427template<
class K,
class V>
429 ensureOpened(getRecordMethodName);
431 TransactionID txn = beginReadOnlyTransaction();
435 abortTransaction(txn);
439 abortTransaction(txn);
460template<
class K,
class V>
490template<
class K,
class V>
492 ensureOpened(getRecordMethodName);
493 return getRecord(key, extractTransactionId(txn, getRecordMethodName));
514template<
class K,
class V>
516 MDB_val lmdbKey = keySerializer.setData(key);
519 int rc = _mdbGet(txn, lmdbKey, lmdbData);
520 if (rc != MDB_SUCCESS)
521 throwNotFoundOrUnknown(rc, toString(key));
523 valueSerializer.deserialize(lmdbData, value);
550template<
class K,
class V>
552 ensureOpened(getRecordMethodName);
553 getRecord(key, value, extractTransactionId(txn, getRecordMethodName));
565template<
class K,
class V>
567 ensureOpened(checkRecordMethodName);
569 TransactionID txn = beginReadOnlyTransaction();
574 abortTransaction(txn);
578 abortTransaction(txn);
591template<
class K,
class V>
593 MDB_val lmdbKey = keySerializer.setData(key);
596 int rc = _mdbGet(txn, lmdbKey, lmdbData);
597 if (rc == MDB_SUCCESS)
600 if (rc != MDB_NOTFOUND)
620template<
class K,
class V>
622 ensureOpened(checkRecordMethodName);
623 return checkRecord(key, extractTransactionId(txn, checkRecordMethodName));
637template<
class K,
class V>
639 ensureOpened(readAllMethodName);
641 std::map<K, V> result;
659template<
class K,
class V>
661 ensureOpened(readAllMethodName);
663 TransactionID txn = beginReadOnlyTransaction();
667 abortTransaction(txn);
671 abortTransaction(txn);
685template<
class K,
class V>
687 std::map<K, V> result;
708template<
class K,
class V>
710 ensureOpened(readAllMethodName);
711 return readAll(extractTransactionId(txn, readAllMethodName));
726template<
class K,
class V>
729 MDB_val lmdbKey, lmdbData;
731 int rc = _mdbCursorOpen(txn, &cursor);
732 if (rc != MDB_SUCCESS)
735 rc = _mdbCursorGet(cursor, lmdbKey, lmdbData, MDB_FIRST);
736 while (rc == MDB_SUCCESS) {
738 keySerializer.deserialize(lmdbKey, key);
739 std::pair<typename std::map<K, V>::iterator,
bool> probe = result.emplace(key, V{});
741 valueSerializer.deserialize(lmdbData, probe.first->second);
743 rc = _mdbCursorGet(cursor, lmdbKey, lmdbData, MDB_NEXT);
745 _mdbCursorClose(cursor);
746 if (rc != MDB_NOTFOUND)
767template<
class K,
class V>
769 ensureOpened(readAllMethodName);
770 readAll(result, extractTransactionId(txn, readAllMethodName));
783template<
class K,
class V>
785 ensureOpened(replaceAllMethodName);
787 TransactionID txn = beginTransaction();
791 abortTransaction(txn);
795 commitTransaction(txn);
808template<
class K,
class V>
811 if (rc != MDB_SUCCESS)
814 MDB_val lmdbKey, lmdbData;
815 for (
const std::pair<const K, V>& pair : data) {
816 lmdbKey = keySerializer.setData(pair.first);
817 lmdbData = valueSerializer.setData(pair.second);
819 rc = _mdbPut(txn, lmdbKey, lmdbData, MDB_NOOVERWRITE);
820 if (rc != MDB_SUCCESS)
839template<
class K,
class V>
841 ensureOpened(replaceAllMethodName);
842 replaceAll(data, extractTransactionId(txn, replaceAllMethodName));
856template<
class K,
class V>
858 ensureOpened(addRecordsMethodName);
860 TransactionID txn = beginTransaction();
865 abortTransaction(txn);
869 commitTransaction(txn);
886template<
class K,
class V>
888 MDB_val lmdbKey, lmdbData;
890 for (
const std::pair<const K, V>& pair : data) {
891 lmdbKey = keySerializer.setData(pair.first);
892 lmdbData = valueSerializer.setData(pair.second);
894 rc = _mdbPut(txn, lmdbKey, lmdbData, overwrite ? 0 : MDB_NOOVERWRITE);
895 if (rc == MDB_KEYEXIST)
896 throwDuplicate(toString(pair.first));
898 if (rc != MDB_SUCCESS)
903 rc = _mdbStat(txn, stat);
904 if (rc != MDB_SUCCESS)
907 return stat.ms_entries;
926template<
class K,
class V>
928 ensureOpened(addRecordsMethodName);
929 return addRecords(data, extractTransactionId(txn, addRecordsMethodName), overwrite);
943template<
class K,
class V>
945 ensureOpened(removeRecordMethodName);
947 TransactionID txn = beginTransaction();
951 abortTransaction(txn);
955 commitTransaction(txn);
970template<
class K,
class V>
972 MDB_val lmdbKey = keySerializer.setData(key);
973 int rc = _mdbDel(txn, lmdbKey);
974 if (rc != MDB_SUCCESS)
975 throwNotFoundOrUnknown(rc, toString(key));
993template<
class K,
class V>
995 ensureOpened(removeRecordMethodName);
996 removeRecord(key, extractTransactionId(txn, removeRecordMethodName));
1005template<
class K,
class V>
1007 return makeStorage<K, V>(transaction, duplicates);
1013template<
class K,
class V>
1015 for (
const std::pair<
const uint32_t,
Cursor<K, V>*>& pair : cursors)
1016 pair.second->terminated();
1029template<
class K,
class V>
1046template<
class K,
class V>
1048 typename std::map<uint32_t, Cursor<K, V>*>::iterator itr = cursors.find(cursor.id);
1049 if (itr == cursors.end())
1050 throwUnknown(
"An attempt to destroy a cursor the storage doesn't own");
1067template<
class K,
class V>
1069 ensureOpened(flagsMethodName);
1071 TransactionID txn = beginReadOnlyTransaction();
1073 int res = _mdbFlags(txn, result);
1074 abortTransaction(txn);
1075 if (res != MDB_SUCCESS)
1087template<
class K,
class V>
1100template<
class K,
class V>
1121template<
class K,
class V>
1123 unsigned int flags = MDB_CREATE;
1124 if constexpr (std::is_integral<K>::value)
1125 flags |= MDB_INTEGERKEY;
1128 flags |= MDB_DUPSORT;
1130 if constexpr (std::is_scalar<V>::value)
1131 flags |= MDB_DUPFIXED;
1134 std::is_same<V, uint32_t>::value ||
1135 std::is_same<V, int32_t>::value ||
1136 std::is_same<V, uint64_t>::value ||
1137 std::is_same<V, int64_t>::value
1139 flags |= MDB_INTEGERDUP;
1142 return _mdbOpen(transaction, flags);
1156 return std::to_string(value);
1169 return value.toStdString();
Database abstraction.
Definition base.h:53
An object to iterate storages.
Definition cursor.h:31
void close()
Termiates a sequence of operations with the cursor.
Definition cursor.hpp:361
Thrown if there was a key conflict in one of the storages.
Definition exceptions.h:178
virtual bool checkRecord(const K &key, TransactionID txn) const
Chechs if storage has value (private transaction variant)
Definition storage.hpp:592
virtual void addRecord(const K &key, const V &value, TransactionID txn)
Adds a key-value record to the storage (private transaction variant)
Definition storage.hpp:107
virtual std::map< K, V > readAll() const
Reads whole storage into a map.
Definition storage.hpp:638
~Storage() override
Destroys a storage.
Definition storage.hpp:59
virtual void discoveredRecord(const K &key, const V &value) const
A private virtual method that cursor calls when he reads a record, does nothing here but populates th...
Definition storage.hpp:1088
virtual void replaceAll(const std::map< K, V > &data, TransactionID txn)
Replaces the content of the whole storage with the given (private transaction variant)
Definition storage.hpp:809
void destroyCursor(Cursor< K, V > &cursor)
Frees cursor.
Definition storage.hpp:1047
uint32_t flags() const
Reads current storage flags it was opened with.
Definition storage.hpp:1068
virtual void removeRecord(const K &key, TransactionID txn)
Removes one of the records (private transaction variant)
Definition storage.hpp:971
void close() override
A private virtual method I need to close each storage in the database.
Definition storage.hpp:1014
Cursor< K, V > createCursor()
Creates cursor.
Definition storage.hpp:1030
virtual bool forceRecord(const K &key, const V &value, TransactionID txn)
Adds a key-value record to the storage, overwrites if it already exists (private transaction variant)
Definition storage.hpp:198
virtual void changeRecord(const K &key, const V &value, TransactionID txn)
Changes key-value record to the storage (private transaction variant)
Definition storage.hpp:314
virtual void getRecord(const K &key, V &value, TransactionID txn) const
Gets the record from the database (private transaction, reference variant)
Definition storage.hpp:515
Storage(Base *parent, const std::string &name, bool duplicates=false)
Creates a storage.
Definition storage.hpp:48
virtual uint32_t addRecords(const std::map< K, V > &data, TransactionID txn, bool overwrite=false)
Adds records in bulk (private transaction variant)
Definition storage.hpp:887
int open(MDB_txn *transaction) override
A private virtual method I need to open each storage in the database.
Definition storage.hpp:1006
Public read only transaction.
Definition transaction.h:26
Public writable transaction.
Definition transaction.h:50
Storage interface.
Definition storage.h:36
int makeStorage(MDB_txn *transaction, bool duplicates=false)
A functiion to actually open MDB_dbi storage.
Definition storage.hpp:1122
virtual void close()
A private virtual function I need to close each storage in the database.
Definition storage.cpp:55
static std::string toString(const T &value)
A method to cast a value (which can be a value or a key) to string.
Definition storage.hpp:1155