1
0
forked from blue/lmdbal

Temp ideas

This commit is contained in:
Blue 2022-09-05 23:25:39 +03:00
parent a3f58bd3c3
commit c3139974f1
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
7 changed files with 404 additions and 0 deletions

View File

@ -25,6 +25,8 @@ endif ()
add_executable(storage add_executable(storage
main.cpp main.cpp
exception.cpp exception.cpp
table.cpp
database.cpp
) )

98
database.cpp Normal file
View File

@ -0,0 +1,98 @@
// 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/>.
#include "database.h"
#include "exceptions.h"
#include "table.h"
Core::DataBase::DataBase(const QString& p_name, uint16_t mapSize):
name(p_name.toStdString()),
opened(false),
size(mapSize),
environment(),
tables()
{
}
Core::DataBase::~DataBase()
{
close();
for (const std::pair<const std::string, _Table*>& pair : tables) {
delete pair.second;
}
}
void Core::DataBase::close()
{
if (opened) {
for (const std::pair<const std::string, _Table*>& pair : tables) {
_Table* table = pair.second;
mdb_dbi_close(environment, table->dbi);
}
mdb_env_close(environment);
opened = false;
}
}
void Core::DataBase::open()
{
if (!opened) {
mdb_env_create(&environment);
QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
path += "/" + getName();
QDir cache(path);
if (!cache.exists()) {
bool res = cache.mkpath(path);
if (!res) {
throw Directory(path.toStdString());
}
}
mdb_env_set_maxdbs(environment, tables.size());
mdb_env_set_mapsize(environment, size * 1024UL * 1024UL);
mdb_env_open(environment, path.toStdString().c_str(), 0, 0664);
MDB_txn *txn;
mdb_txn_begin(environment, NULL, 0, &txn);
for (const std::pair<const std::string, _Table*>& pair : tables) {
_Table* table = pair.second;
int rc = mdb_dbi_open(txn, pair.first.c_str(), MDB_CREATE, &table->dbi);
if (rc) {
throw Unknown(name, mdb_strerror(rc));
}
}
mdb_txn_commit(txn);
opened = true;
}
}
QString Core::DataBase::getName() const
{
return QString::fromStdString(name);
}
template <class K, class V>
Core::DataBase::Table<K, V>* Core::DataBase::addTable(const QString& p_name) {
if (opened) {
throw Core::DataBase::Opened(name);
}
Core::DataBase::Table<K, V>* table = new Core::DataBase::Table<K, V>();
tables.insert(std::make_pair(p_name.toStdString(), table));
return table;
}

68
database.h Normal file
View File

@ -0,0 +1,68 @@
// 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_DATABASE_H
#define CORE_DATABASE_H
#include <map>
#include <string>
#include <QString>
#include <QStandardPaths>
#include <QDir>
#include <lmdb.h>
namespace Core {
class DataBase
{
class _Table;
public:
template <class K, class V>
class Table;
DataBase(const QString& name, uint16_t mapSize = 10);
~DataBase();
void open();
void close();
QString getName() const;
template <class K, class V>
Table<K, V>* addTable(const QString& name);
public:
//exceptions
class Directory;
class Closed;
class Opened;
class NotFound;
class Empty;
class Exist;
class NoAvatar;
class Unknown;
private:
std::string name;
bool opened;
uint16_t size;
MDB_env* environment;
std::map<std::string, _Table*> tables;
};
}
#endif // CORE_DATABASE_H

106
exceptions.h Normal file
View File

@ -0,0 +1,106 @@
// 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_DATABASE_EXCEPTIONS_H
#define CORE_DATABASE_EXCEPTIONS_H
#include "exception.h"
#include "database.h"
namespace Core {
class DataBase::Directory: public Utils::Exception {
public:
Directory(const std::string& p_path):Exception(), path(p_path){}
std::string getMessage() const{return "Can't create directory for database at " + path;}
private:
std::string path;
};
class DataBase::Closed : public Utils::Exception {
public:
Closed(const std::string& op, const std::string& acc):Exception(), operation(op), account(acc){}
std::string getMessage() const{return "An attempt to perform operation " + operation + " on closed archive for " + account;}
private:
std::string operation;
std::string account;
};
class DataBase::Opened : public Utils::Exception {
public:
Opened(const std::string& tn):Exception(), tableName(tn){}
std::string getMessage() const{return "An attempt to add table " + tableName + " but it's impossible to do if the DataBase is already opened";}
private:
std::string tableName;
};
class DataBase::NotFound : public Utils::Exception {
public:
NotFound(const std::string& k, const std::string& acc):Exception(), key(k), account(acc){}
std::string getMessage() const{return "Element for id " + key + " wasn't found in database " + account;}
private:
std::string key;
std::string account;
};
class DataBase::Empty : public Utils::Exception {
public:
Empty(const std::string& acc):Exception(), account(acc){}
std::string getMessage() const{return "An attempt to read ordered elements from database " + account + " but it's empty";}
private:
std::string account;
};
class DataBase::Exist : public Utils::Exception {
public:
Exist(const std::string& acc, const std::string& p_key):Exception(), account(acc), key(p_key){}
std::string getMessage() const{return "An attempt to insert element " + key + " to database " + account + " but it already has an element with given id";}
private:
std::string account;
std::string key;
};
class DataBase::NoAvatar : public Utils::Exception {
public:
NoAvatar(const std::string& el, const std::string& res):Exception(), element(el), resource(res){
if (resource.size() == 0) {
resource = "for himself";
}
}
std::string getMessage() const{return "Element " + element + " has no avatar for " + resource ;}
private:
std::string element;
std::string resource;
};
class DataBase::Unknown : public Utils::Exception {
public:
Unknown(const std::string& acc, const std::string& message):Exception(), account(acc), msg(message){}
std::string getMessage() const{return "Unknown error on database " + account + ": " + msg;}
private:
std::string account;
std::string msg;
};
}
#endif //CORE_DATABASE_EXCEPTIONS_H

25
table.cpp Normal file
View File

@ -0,0 +1,25 @@
// 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/>.
#include "table.h"
Core::DataBase::_Table::_Table(DataBase* parent):
dbi(),
db(parent)
{
}
Core::DataBase::_Table::~_Table() {}

52
table.h Normal file
View File

@ -0,0 +1,52 @@
// 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_TABLE_H
#define CORE_TABLE_H
#include "database.h"
namespace Core {
class DataBase::_Table {
public:
_Table(DataBase* parent);
virtual ~_Table();
public:
MDB_dbi dbi;
DataBase* db;
};
template <class K, class V>
class DataBase::Table : private DataBase::_Table {
friend class DataBase;
private:
Table(DataBase* parent);
~Table() override;
public:
void addRecord(const K& key, const V& value);
void changeRecord(const K& key, const V& value);
void removeRecord(const K& key);
V getRecord(const K& key) const;
};
}
#include "table.hpp"
#endif // CORE_TABLE_H

53
table.hpp Normal file
View File

@ -0,0 +1,53 @@
// 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_TABLE_HPP
#define CORE_TABLE_HPP
#include "table.h"
template<typename K, typename V>
void Core::DataBase::Table<K, V>::addRecord(const K& key, const V& value) {
if (!db->opened) {
throw Closed("addRecord", db->name);
}
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << value;
MDB_val lmdbKey, lmdbData;
lmdbKey << key;
lmdbData.mv_size = ba.size();
lmdbData.mv_data = (uint8_t*)ba.data();
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(db->name, std::to_string(key));
} else {
throw Unknown(db->name, mdb_strerror(rc));
}
} else {
mdb_txn_commit(txn);
}
}
#endif //CORE_TABLE_HPP