external transaction methods for storage

This commit is contained in:
Blue 2023-03-28 23:45:35 +03:00
parent f39d44890a
commit e2dbea21d1
Signed by: blue
GPG Key ID: 9B203B252A63EE38
19 changed files with 273 additions and 58 deletions

View File

@ -10,7 +10,7 @@ depends=( 'lmdb' 'qt5-base')
makedepends=('cmake>=3.16')
optdepends=()
source=("$pkgname-$pkgver.tar.gz")
source=("$pkgname-$pkgver.tar.gz::https://git.macaw.me/blue/lmdbal/archive/$pkgver.tar.gz")
sha256sums=('SKIP')
build() {
cd "$srcdir/$pkgname"

View File

@ -37,6 +37,7 @@ public:
~Serializer();
T deserialize(const MDB_val& value);
void deserialize(const MDB_val& value, T& result);
MDB_val setData(const T& value);
MDB_val getData();
void clear();

View File

@ -54,14 +54,19 @@ MDB_val LMDBAL::Serializer<T>::setData(const T& value) {
template<class T>
T LMDBAL::Serializer<T>::deserialize(const MDB_val& value) {
clear();
bytes.setRawData((char*)value.mv_data, value.mv_size);
T result;
stream >> result;
deserialize(value, result);
return result;
}
template<class T>
void LMDBAL::Serializer<T>::deserialize(const MDB_val& value, T& result) {
clear();
bytes.setRawData((char*)value.mv_data, value.mv_size);
stream >> result;
}
template<class T>
void LMDBAL::Serializer<T>::_setData(const T& value) {
stream << value;

View File

@ -29,9 +29,12 @@ public:
~Serializer() {};
double deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 8);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, double& result) {
std::memcpy(&result, data.mv_data, 8);
}
MDB_val setData(const double& data) {
value = data;
return getData();

View File

@ -29,9 +29,12 @@ public:
~Serializer() {};
float deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 4);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, float& result) {
std::memcpy(&result, data.mv_data, 4);
}
MDB_val setData(const float& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
int16_t deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 2);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, int16_t& result) {
std::memcpy(&result, data.mv_data, 2);
}
MDB_val setData(const int16_t& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
int32_t deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 4);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, int32_t& result) {
std::memcpy(&result, data.mv_data, 4);
}
MDB_val setData(const int32_t& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
int64_t deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 8);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, int64_t& result) {
std::memcpy(&result, data.mv_data, 8);
}
MDB_val setData(const int64_t& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
int8_t deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 1);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, int8_t& result) {
std::memcpy(&result, data.mv_data, 1);
}
MDB_val setData(const int8_t& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
QByteArray deserialize(const MDB_val& data) {
value.setRawData((char*)data.mv_data, data.mv_size);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, QByteArray& result) {
result.setRawData((char*)data.mv_data, data.mv_size);
}
MDB_val setData(const QByteArray& data) {
value = data;
return getData();

View File

@ -35,6 +35,10 @@ public:
value = QByteArray((char*)data.mv_data, data.mv_size);
return QString::fromUtf8(value);
};
void deserialize(const MDB_val& data, QString& result) {
value = QByteArray((char*)data.mv_data, data.mv_size);
result = QString::fromUtf8(value);
}
MDB_val setData(const QString& data) {
value = data.toUtf8();
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
std::string deserialize(const MDB_val& data) {
value = std::string((char*)data.mv_data, data.mv_size);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, std::string& result) {
result.assign((char*)data.mv_data, data.mv_size);
}
MDB_val setData(const std::string& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
uint16_t deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 2);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, uint16_t& result) {
std::memcpy(&result, data.mv_data, 2);
}
MDB_val setData(const uint16_t& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
uint32_t deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 4);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, uint32_t& result) {
std::memcpy(&result, data.mv_data, 4);
}
MDB_val setData(const uint32_t& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
uint64_t deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 8);
deserialize(data, value);
return value;
};
void deserialize(const MDB_val& data, uint64_t& result) {
std::memcpy(&result, data.mv_data, 8);
}
MDB_val setData(const uint64_t& data) {
value = data;
return getData();

View File

@ -31,9 +31,12 @@ public:
~Serializer() {};
uint8_t deserialize(const MDB_val& data) {
std::memcpy(&value, data.mv_data, 1);
deserialzie(data, value);
return value;
};
void deserialzie(const MDB_val& data, uint8_t& result) {
std::memcpy(&result, data.mv_data, 1);
}
MDB_val setData(const uint8_t& data) {
value = data;
return getData();

View File

@ -82,14 +82,22 @@ uint32_t LMDBAL::iStorage::count() const {
void LMDBAL::iStorage::throwDuplicateOrUnknown(int rc, TransactionID txn, const std::string& key) const {
abortTransaction(txn);
throwDuplicateOrUnknown(rc, key);
}
void LMDBAL::iStorage::throwNotFoundOrUnknown(int rc, LMDBAL::TransactionID txn, const std::string& key) const {
abortTransaction(txn);
throwNotFoundOrUnknown(rc, key);
}
void LMDBAL::iStorage::throwDuplicateOrUnknown(int rc, const std::string& key) const {
if (rc == MDB_KEYEXIST)
throwDuplicate(key);
else
throwUnknown(rc);
}
void LMDBAL::iStorage::throwNotFoundOrUnknown(int rc, LMDBAL::TransactionID txn, const std::string& key) const {
abortTransaction(txn);
void LMDBAL::iStorage::throwNotFoundOrUnknown(int rc, const std::string& key) const {
if (rc == MDB_NOTFOUND)
throwNotFound(key);
else

View File

@ -37,7 +37,9 @@ protected:
const std::string& dbName() const;
void ensureOpened(const std::string& methodName) const;
void throwDuplicateOrUnknown(int rc, const std::string& key) const;
void throwDuplicateOrUnknown(int rc, TransactionID txn, const std::string& key) const;
void throwNotFoundOrUnknown(int rc, const std::string& key) const;
void throwNotFoundOrUnknown(int rc, TransactionID txn, const std::string& key) const;
void throwUnknown(int rc, TransactionID txn) const;
void throwUnknown(int rc) const;
@ -89,14 +91,27 @@ protected:
public:
using iStorage::drop;
virtual void addRecord(const K& key, const V& value);
virtual void addRecord(const K& key, const V& value, TransactionID txn);
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, TransactionID txn);
virtual void changeRecord(const K& key, const V& value);
virtual void changeRecord(const K& key, const V& value, TransactionID txn);
virtual void removeRecord(const K& key);
virtual void removeRecord(const K& key, TransactionID txn);
virtual bool checkRecord(const K& key) const; //checks if there is a record with given key
virtual bool checkRecord(const K& key, TransactionID txn) const;
virtual void getRecord(const K& key, V& value) const;
virtual void getRecord(const K& key, V& value, TransactionID txn) const;
virtual V getRecord(const K& key) const;
virtual V getRecord(const K& key, TransactionID txn) const;
virtual std::map<K, V> readAll() const;
virtual std::map<K, V> readAll(TransactionID txn) const;
virtual void readAll(std::map<K, V>& result) const;
virtual void readAll(std::map<K, V>& result, TransactionID txn) const;
virtual void replaceAll(const std::map<K, V>& data);
virtual void replaceAll(const std::map<K, V>& data, TransactionID txn);
virtual uint32_t addRecords(const std::map<K, V>& data, bool overwrite = false);
virtual uint32_t addRecords(const std::map<K, V>& data, TransactionID txn, bool overwrite = false);
protected:
Serializer<K>* keySerializer;

View File

@ -38,24 +38,51 @@ LMDBAL::Storage<K, V>::~Storage() {
template<class K, class V>
void LMDBAL::Storage<K, V>::addRecord(const K& key, const V& value) {
ensureOpened(addRecordMethodName);
TransactionID txn = beginTransaction();
try {
addRecord(key, value, txn);
} catch (...) {
abortTransaction(txn);
throw;
}
commitTransaction(txn);
}
template<class K, class V>
void LMDBAL::Storage<K, V>::addRecord(const K& key, const V& value, TransactionID txn) {
ensureOpened(addRecordMethodName);
MDB_val lmdbKey = keySerializer->setData(key);
MDB_val lmdbData = valueSerializer->setData(value);
int rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, MDB_NOOVERWRITE);
if (rc != MDB_SUCCESS)
throwDuplicateOrUnknown(rc, txn, toString(key));
commitTransaction(txn);
throwDuplicateOrUnknown(rc, toString(key));
}
template<class K, class V>
bool LMDBAL::Storage<K, V>::forceRecord(const K& key, const V& value) {
ensureOpened(forceRecordMethodName);
bool added;
TransactionID txn = beginTransaction();
bool added;
try {
added = forceRecord(key, value, txn);
} catch (...) {
abortTransaction(txn);
throw;
}
commitTransaction(txn);
return added;
}
template<class K, class V>
bool LMDBAL::Storage<K, V>::forceRecord(const K& key, const V& value, TransactionID txn) {
ensureOpened(forceRecordMethodName);
bool added;
MDB_val lmdbKey = keySerializer->setData(key);
MDB_val lmdbData;
@ -69,15 +96,13 @@ bool LMDBAL::Storage<K, V>::forceRecord(const K& key, const V& value) {
break;
default:
added = false;
throwUnknown(rc, txn);
throwUnknown(rc);
}
lmdbData = valueSerializer->setData(value);
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, 0);
if (rc != MDB_SUCCESS)
throwUnknown(rc, txn);
commitTransaction(txn);
throwUnknown(rc);
return added;
}
@ -87,32 +112,73 @@ void LMDBAL::Storage<K, V>::changeRecord(const K& key, const V& value) {
ensureOpened(changeRecordMethodName);
TransactionID txn = beginTransaction();
try {
changeRecord(key, value, txn);
} catch (...) {
abortTransaction(txn);
throw;
}
commitTransaction(txn);
}
template<class K, class V>
void LMDBAL::Storage<K, V>::changeRecord(const K& key, const V& value, TransactionID txn) {
ensureOpened(changeRecordMethodName);
MDB_val lmdbKey = keySerializer->setData(key);
MDB_val lmdbData = valueSerializer->setData(value);
int rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, 0);
if (rc != MDB_SUCCESS)
throwUnknown(rc, txn);
commitTransaction(txn);
throwUnknown(rc);
}
template<class K, class V>
V LMDBAL::Storage<K, V>::getRecord(const K& key) const {
ensureOpened(getRecordMethodName);
V value;
getRecord(key, value);
return value;
}
template<class K, class V>
void LMDBAL::Storage<K, V>::getRecord(const K& key, V& value) const {
ensureOpened(getRecordMethodName);
TransactionID txn = beginReadOnlyTransaction();
try {
getRecord(key, value, txn);
} catch (...) {
abortTransaction(txn);
throw;
}
abortTransaction(txn);
}
template<class K, class V>
V LMDBAL::Storage<K, V>::getRecord(const K& key, TransactionID txn) const {
ensureOpened(getRecordMethodName);
V value;
getRecord(key, value, txn);
return value;
}
template<class K, class V>
void LMDBAL::Storage<K, V>::getRecord(const K& key, V& value, TransactionID txn) const {
ensureOpened(getRecordMethodName);
MDB_val lmdbKey = keySerializer->setData(key);
MDB_val lmdbData;
int rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
if (rc != MDB_SUCCESS)
throwNotFoundOrUnknown(rc, txn, toString(key));
throwNotFoundOrUnknown(rc, toString(key));
V value = valueSerializer->deserialize(lmdbData);
abortTransaction(txn);
return value;
valueSerializer->deserialize(lmdbData, value);
}
template<class K, class V>
@ -120,12 +186,26 @@ bool LMDBAL::Storage<K, V>::checkRecord(const K& key) const {
ensureOpened(checkRecordMethodName);
TransactionID txn = beginReadOnlyTransaction();
bool result;
try {
result = checkRecord(key, txn);
} catch (...) {
abortTransaction(txn);
throw;
}
abortTransaction(txn);
return result;
}
template<class K, class V>
bool LMDBAL::Storage<K, V>::checkRecord(const K& key, TransactionID txn) const {
ensureOpened(checkRecordMethodName);
MDB_val lmdbKey = keySerializer->setData(key);
MDB_val lmdbData;
int rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData);
abortTransaction(txn);
if (rc == MDB_SUCCESS)
return true;
@ -139,28 +219,57 @@ template<class K, class V>
std::map<K, V> LMDBAL::Storage<K, V>::readAll() const {
ensureOpened(readAllMethodName);
TransactionID txn = beginReadOnlyTransaction();
std::map<K, V> result;
readAll(result);
return result;
}
template<class K, class V>
void LMDBAL::Storage<K, V>::readAll(std::map<K, V>& result) const {
ensureOpened(readAllMethodName);
TransactionID txn = beginReadOnlyTransaction();
try {
readAll(result, txn);
} catch (...) {
abortTransaction(txn);
throw;
}
abortTransaction(txn);
}
template<class K, class V>
std::map<K, V> LMDBAL::Storage<K, V>::readAll(TransactionID txn) const {
ensureOpened(readAllMethodName);
std::map<K, V> result;
readAll(result, txn);
return result;
}
template<class K, class V>
void LMDBAL::Storage<K, V>::readAll(std::map<K, V>& result, TransactionID txn) const {
ensureOpened(readAllMethodName);
MDB_cursor* cursor;
MDB_val lmdbKey, lmdbData;
int rc = mdb_cursor_open(txn, dbi, &cursor);
if (rc != MDB_SUCCESS)
throwUnknown(rc, txn);
throwUnknown(rc);
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_FIRST);
while (rc == MDB_SUCCESS) {
K key = keySerializer->deserialize(lmdbKey);
V value = valueSerializer->deserialize(lmdbData);
result.insert(std::make_pair(key, value));
K key;
keySerializer->deserialize(lmdbKey, key);
V& value = result[key];
valueSerializer->deserialize(lmdbData, value);
rc = mdb_cursor_get(cursor, &lmdbKey, &lmdbData, MDB_NEXT);
}
abortTransaction(txn);
if (rc != MDB_NOTFOUND)
throwUnknown(rc);
return result;
}
template<class K, class V>
@ -168,9 +277,23 @@ void LMDBAL::Storage<K, V>::replaceAll(const std::map<K, V>& data) {
ensureOpened(replaceAllMethodName);
TransactionID txn = beginTransaction();
try {
replaceAll(data, txn);
} catch (...) {
abortTransaction(txn);
throw;
}
commitTransaction(txn);
}
template<class K, class V>
void LMDBAL::Storage<K, V>::replaceAll(const std::map<K, V>& data, TransactionID txn) {
ensureOpened(replaceAllMethodName);
int rc = drop(txn);
if (rc != MDB_SUCCESS)
throwUnknown(rc, txn);
throwUnknown(rc);
MDB_val lmdbKey, lmdbData;
for (const std::pair<const K, V>& pair : data) {
@ -179,9 +302,8 @@ void LMDBAL::Storage<K, V>::replaceAll(const std::map<K, V>& data) {
rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, MDB_NOOVERWRITE);
if (rc != MDB_SUCCESS)
throwUnknown(rc, txn);
throwUnknown(rc);
}
commitTransaction(txn);
}
template<class K, class V>
@ -189,27 +311,39 @@ uint32_t LMDBAL::Storage<K, V>::addRecords(const std::map<K, V>& data, bool over
ensureOpened(addRecordsMethodName);
TransactionID txn = beginTransaction();
uint32_t amount;
try {
amount = addRecords(data, txn, overwrite);
} catch (...) {
abortTransaction(txn);
throw;
}
commitTransaction(txn);
return amount;
}
template<class K, class V>
uint32_t LMDBAL::Storage<K, V>::addRecords(const std::map<K, V>& data, TransactionID txn, bool overwrite) {
ensureOpened(addRecordsMethodName);
MDB_val lmdbKey, lmdbData;
int rc;
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 != MDB_SUCCESS)
throwUnknown(rc, txn);
throwUnknown(rc);
}
MDB_stat stat;
rc = mdb_stat(txn, dbi, &stat);
if (rc != MDB_SUCCESS)
throwUnknown(rc, txn);
throwUnknown(rc);
uint32_t amount = stat.ms_entries;
commitTransaction(txn);
return amount;
return stat.ms_entries;
}
template<class K, class V>
@ -217,12 +351,24 @@ void LMDBAL::Storage<K, V>::removeRecord(const K& key) {
ensureOpened(removeRecordMethodName);
TransactionID txn = beginTransaction();
try {
removeRecord(key, txn);
} catch (...) {
abortTransaction(txn);
throw;
}
commitTransaction(txn);
}
template<class K, class V>
void LMDBAL::Storage<K, V>::removeRecord(const K& key, TransactionID txn) {
ensureOpened(removeRecordMethodName);
MDB_val lmdbKey = keySerializer->setData(key);
int rc = mdb_del(txn, dbi, &lmdbKey, NULL);
if (rc != MDB_SUCCESS)
throwNotFoundOrUnknown(rc, txn, toString(key));
commitTransaction(txn);
throwNotFoundOrUnknown(rc, toString(key));
}
template<class K, class V>