// Squawk messenger. // Copyright (C) 2019 Yury Gubich // // 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 . #ifndef CORE_TABLE_HPP #define CORE_TABLE_HPP #include "table.h" #include "exceptions.h" template DataBase::Table::Table(const std::string& p_name, DataBase* parent): _Table(p_name, parent), keySerializer(new Serializer()), valueSerializer(new Serializer()) { } template DataBase::Table::~Table() { delete valueSerializer; delete keySerializer; } template void DataBase::Table::addRecord(const K& key, const V& value) { if (!db->opened) { throw Closed("addRecord", db->name, name); } MDB_val lmdbKey = keySerializer->setData(key); MDB_val lmdbData = valueSerializer->setData(value); MDB_txn *txn; mdb_txn_begin(db->environment, NULL, 0, &txn); int rc; rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, MDB_NOOVERWRITE); if (rc != 0) { mdb_txn_abort(txn); if (rc == MDB_KEYEXIST) { throw Exist(toString(key), db->name, name); } else { throw Unknown(db->name, mdb_strerror(rc), name); } } else { mdb_txn_commit(txn); } } template void DataBase::Table::changeRecord(const K& key, const V& value) { if (!db->opened) { throw Closed("changeRecord", db->name, name); } MDB_val lmdbKey = keySerializer->setData(key); MDB_val lmdbData = valueSerializer->setData(value); MDB_txn *txn; mdb_txn_begin(db->environment, NULL, 0, &txn); int rc; rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, 0); if (rc != 0) { mdb_txn_abort(txn); if (rc) { throw Unknown(db->name, mdb_strerror(rc), name); } } else { mdb_txn_commit(txn); } } template V DataBase::Table::getRecord(const K& key) const { if (!db->opened) { throw Closed("getRecord", db->name, name); } MDB_val lmdbKey = keySerializer->setData(key); MDB_val lmdbData; MDB_txn *txn; int rc; mdb_txn_begin(db->environment, NULL, MDB_RDONLY, &txn); rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData); if (rc) { mdb_txn_abort(txn); if (rc == MDB_NOTFOUND) { throw NotFound(toString(key), db->name, name); } else { throw Unknown(db->name, mdb_strerror(rc), name); } } else { V value = valueSerializer->deserialize(lmdbData); mdb_txn_abort(txn); return value; } } template void DataBase::Table::removeRecord(const K& key) { if (!db->opened) { throw Closed("removeRecord", db->name, name); } MDB_val lmdbKey = keySerializer->setData(key); MDB_txn *txn; int rc; mdb_txn_begin(db->environment, NULL, 0, &txn); rc = mdb_del(txn, dbi, &lmdbKey, NULL); if (rc) { mdb_txn_abort(txn); if (rc == MDB_NOTFOUND) { throw NotFound(toString(key), db->name, name); } else { throw Unknown(db->name, mdb_strerror(rc), name); } } else { mdb_txn_commit(txn); } } template int DataBase::Table::createTable(MDB_txn* transaction) { return makeTable(transaction); } template inline int DataBase::_Table::makeTable(MDB_txn* transaction) { return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE, &dbi); } template<> inline int DataBase::_Table::makeTable(MDB_txn* transaction) { return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi); } template inline std::string DataBase::_Table::toString(const T& value) { return std::to_string(value); } template<> inline std::string DataBase::_Table::toString(const QString& value) { return value.toStdString(); } #endif //CORE_TABLE_HPP