From 0b4714688f121648e1126ac4c5f26e8e825684aa Mon Sep 17 00:00:00 2001 From: blue Date: Tue, 16 Apr 2019 01:35:09 +0300 Subject: [PATCH] not working lmdb --- core/CMakeLists.txt | 3 + core/archive.cpp | 212 ++++++++++++++++++++++++++++++++++++++++---- core/archive.h | 65 ++++++++++++-- core/lmdb++.h | 2 +- global.cpp | 35 +++++++- global.h | 4 + main.cpp | 27 ++++++ 7 files changed, 323 insertions(+), 25 deletions(-) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 4f99ee0..0284081 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.0) project(squawkCORE) # Instruct CMake to run moc automatically when needed. +set (CMAKE_CXX_STANDARD 17) set(CMAKE_AUTOMOC ON) find_package(Qt5Widgets CONFIG REQUIRED) @@ -10,6 +11,7 @@ find_package(Qt5Network CONFIG REQUIRED) set(squawkCORE_SRC squawk.cpp account.cpp + archive.cpp ) # Tell CMake to create the helloworld executable @@ -19,6 +21,7 @@ add_library(squawkCORE ${squawkCORE_SRC}) target_link_libraries(squawkCORE Qt5::Core) target_link_libraries(squawkCORE Qt5::Network) target_link_libraries(squawkCORE qxmpp) +target_link_libraries(squawkCORE lmdb) # Install the executable install(TARGETS squawkCORE DESTINATION lib) diff --git a/core/archive.cpp b/core/archive.cpp index c468e9e..e5e6881 100644 --- a/core/archive.cpp +++ b/core/archive.cpp @@ -21,13 +21,16 @@ #include #include #include +#include +#include Core::Archive::Archive(const QString& p_jid, QObject* parent): QObject(parent), jid(p_jid), opened(false), environment(lmdb::env::create()), - dbi(0) + dbi(0), + order(0) { } @@ -40,32 +43,211 @@ void Core::Archive::open(const QString& account) { if (!opened) { QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); - path += "/" + account; - int state1 = mkdir(path.toStdString().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (state1 != 0 && errno != EEXIST) { - qDebug() << "Failed to create account " << account << " database folder"; - throw 1; - } + path += "/" + account + "/" + jid; + QDir cache(path); - path += "/" + jid; - - int state2 = mkdir(path.toStdString().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (state2 != 0 && errno != EEXIST) { - qDebug() << "Failed to create " << jid.toStdString().c_str() << " database folder in account" << account; - throw 1; + if (!cache.exists()) { + bool res = cache.mkpath(path); + if (!res) { + throw Directory(path.toStdString()); + } } environment.set_mapsize(1UL * 1024UL * 1024UL * 1024UL); - environment.set_max_dbs(10); + environment.set_max_dbs(2); environment.open(path.toStdString().c_str(), 0, 0664); lmdb::txn wTrans = lmdb::txn::begin(environment); dbi = lmdb::dbi::open(wTrans, "main", MDB_CREATE); + order = lmdb::dbi::open(wTrans, "order", MDB_CREATE | MDB_INTEGERKEY); wTrans.commit(); + opened = true; } } -QString Core::Archive::addElement(const Shared::Message& message) +void Core::Archive::addElement(const Shared::Message& message) { + if (!opened) { + throw Closed("addElement", jid.toStdString()); + } + QByteArray ba; + QDataStream ds(&ba, QIODevice::WriteOnly); + message.serialize(ds); + quint64 stamp = message.getTime().toMSecsSinceEpoch(); + const std::string& id = message.getId().toStdString(); + qDebug() << "inserting element with id " << id.c_str(); + + lmdb::val key((quint8*)id.c_str(), 36); + lmdb::val value(ba.data(), ba.size()); + lmdb::txn wTrans = lmdb::txn::begin(environment); + bool result = dbi.put(wTrans, key, value); + if (result) { + lmdb::val oKey((quint8*) &stamp, 8); + bool oResult = order.put(wTrans, oKey, key); + if (!oResult) { + qDebug() << "An element couldn't be inserted into the index"; + } + } else { + qDebug() << "An element couldn't been added to the archive, skipping"; + } + wTrans.commit(); +} + +void Core::Archive::clear() +{ + if (!opened) { + throw Closed("clear", jid.toStdString()); + } + + lmdb::txn transaction = lmdb::txn::begin(environment); + dbi.drop(transaction); + order.drop(transaction); + transaction.commit(); +} + +Shared::Message Core::Archive::getElement(const QString& id) +{ + if (!opened) { + throw Closed("getElement", jid.toStdString()); + } + + qDebug() << "getting an element with id " << id.toStdString().c_str(); + lmdb::txn rtxn = lmdb::txn::begin(environment); + lmdb::val key((quint8*)id.toStdString().c_str(), 36); + lmdb::val value; + + + int rc = 0; + char *c_key=(char *)id.toStdString().c_str(); + MDB_val d_key, data; + data.mv_data = nullptr; + data.mv_size = 0; + MDB_txn *txn = nullptr; + rc = mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn); + d_key.mv_size = key.size(); + d_key.mv_data = c_key; + rc= mdb_get(txn,dbi ,&d_key, &data); + if (rc) { + qDebug() <<"Data Can't be Found, Error: "< #include "../global.h" #include "lmdb++.h" +#include "../exception.h" namespace Core { @@ -29,27 +30,75 @@ class Archive : public QObject { Q_OBJECT public: - Archive(const QString& jid, QObject* parent); + Archive(const QString& jid, QObject* parent = 0); ~Archive(); void open(const QString& account); - QString addElement(const Shared::Message& message); - Shared::Message getElement(const QString& id) const; - Shared::Message oldest() const; - Shared::Message newest() const; - void removeElement(const QString& id); + void addElement(const Shared::Message& message); + Shared::Message getElement(const QString& id); + Shared::Message oldest(); + QString oldestId(); + Shared::Message newest(); + QString newestId(); void clear(); - void modifyElement(const QString& id, const Shared::Message& newValue); - unsigned int size() const; + long unsigned int size() const; public: const QString jid; +public: + class 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 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 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 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; + }; + private: bool opened; lmdb::env environment; lmdb::dbi dbi; + lmdb::dbi order; }; } diff --git a/core/lmdb++.h b/core/lmdb++.h index ab75f8c..abd6d4f 100644 --- a/core/lmdb++.h +++ b/core/lmdb++.h @@ -1558,7 +1558,7 @@ public: lmdb::val v{}; const bool result = lmdb::dbi_get(txn, handle(), k, v); if (result) { - val = *v.data(); + val = std::move(*v.data()); } return result; } diff --git a/global.cpp b/global.cpp index 4520b4d..ce5556a 100644 --- a/global.cpp +++ b/global.cpp @@ -179,7 +179,7 @@ void Shared::Message::generateRandomId() uuid_t uuid; uuid_generate(uuid); - char uuid_str[37]; + char uuid_str[36]; uuid_unparse_lower(uuid, uuid_str); id = uuid_str; } @@ -208,3 +208,36 @@ void Shared::Message::setType(Shared::Message::Type t) { type = t; } + +void Shared::Message::serialize(QDataStream& data) const +{ + data << jFrom; + data << rFrom; + data << jTo; + data << rTo; + data << id; + data << body; + data << time; + data << thread; + quint8 t = type; + data << t; + data << outgoing; + data << forwarded; +} + +void Shared::Message::deserialize(QDataStream& data) +{ + data >> jFrom; + data >> rFrom; + data >> jTo; + data >> rTo; + data >> id; + data >> body; + data >> time; + data >> thread; + quint8 t; + data >> t; + type = static_cast(t); + data >> outgoing; + data >> forwarded; +} diff --git a/global.h b/global.h index e4fa761..922c242 100644 --- a/global.h +++ b/global.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Shared { @@ -96,6 +97,9 @@ public: QString getPenPalResource() const; void generateRandomId(); + void serialize(QDataStream& data) const; + void deserialize(QDataStream& data); + private: QString jFrom; QString rFrom; diff --git a/main.cpp b/main.cpp index 7d0dae2..17175ee 100644 --- a/main.cpp +++ b/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "core/archive.h" int main(int argc, char *argv[]) { @@ -56,6 +57,32 @@ int main(int argc, char *argv[]) //qDebug() << QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + Core::Archive ar("test1@macaw.me"); + ar.open("Test"); + Shared::Message msg1; + msg1.generateRandomId(); + msg1.setBody("oldest"); + msg1.setTime(QDateTime::currentDateTime().addDays(-7)); + Shared::Message msg2; + msg2.generateRandomId(); + msg2.setBody("Middle"); + msg2.setTime(QDateTime::currentDateTime().addDays(-4)); + Shared::Message msg3; + msg3.generateRandomId(); + msg3.setBody("newest"); + msg3.setTime(QDateTime::currentDateTime()); + + ar.addElement(msg2); + ar.addElement(msg3); + ar.addElement(msg1); + + Shared::Message d0 = ar.getElement(msg1.getId()); + + Shared::Message d1 = ar.newest(); + Shared::Message d2 = ar.oldest(); + + qDebug() << d1.getBody() << ", " << d2.getBody(); + coreThread->start(); int result = app.exec();