1
0
forked from blue/lmdbal

first thoughts about cache

This commit is contained in:
Blue 2022-09-20 20:16:48 +03:00
parent 2f34fa69e8
commit a613eaed27
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
6 changed files with 205 additions and 7 deletions

View File

@ -38,6 +38,8 @@ set(HEADERS
exceptions.h exceptions.h
table.h table.h
table.hpp table.hpp
cache.h
cache.hpp
serializer.h serializer.h
serializer.hpp serializer.hpp
serializer_uint8.hpp serializer_uint8.hpp

53
cache.h 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 DATABASE_CACHE_H
#define DATABASE_CACHE_H
#include "database.h"
#include "table.h"
#include <map>
#include <set>
template <class K, class V>
class DataBase::Cache : public DataBase::Table<K, V> {
friend class DataBase;
enum class Mode {
nothing,
size,
full
};
protected:
Cache(const std::string& name, DataBase* parent);
~Cache() override;
public:
virtual void addRecord(const K& key, const V& value) override;
virtual void changeRecord(const K& key, const V& value) override;
virtual void removeRecord(const K& key) override;
virtual V getRecord(const K& key) const override;
//virtual uint32_t count() const;
//virtual void drop();
protected:
Mode mode;
std::map<K, V>* cache;
std::set<K>* abscent;
};
#include "cache.hpp"
#endif // DATABASE_CACHE_H

114
cache.hpp Normal file
View File

@ -0,0 +1,114 @@
// 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 DATABASE_CACHE_HPP
#define DATABASE_CACHE_HPP
#include "cache.h"
#include "exceptions.h"
template<class K, class V>
DataBase::Cache<K, V>::Cache(const std::string& p_name, DataBase* parent):
DataBase::Table<K, V>(p_name, parent),
mode(Mode::nothing),
cache(new std::map<K, V>()),
abscent(new std::set<K>())
{
}
template<class K, class V>
DataBase::Cache<K, V>::~Cache() {
delete cache;
delete abscent;
}
template<class K, class V>
void DataBase::Cache<K, V>::addRecord(const K& key, const V& value) {
if (!DataBase::Table<K, V>::db->opened) {
throw Closed("addRecord", DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
if (cache->count(key) > 0) {
throw Exist(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
Table<K, V>::addRecord(key, value);
cache->insert(std::make_pair(key, value));
}
template<class K, class V>
void DataBase::Cache<K, V>::changeRecord(const K& key, const V& value) {
if (!DataBase::Table<K, V>::db->opened) {
throw Closed("changeRecord", DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
typename std::map<K, V>::iterator itr = cache->find(key);
if (itr == cache->end() || abscent->count(key) > 0) {
throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
try {
Table<K, V>::changeRecord(key, value);
itr->second = value;
} catch (const NotFound& error) {
abscent->insert(key);
throw error;
}
}
template<class K, class V>
V DataBase::Cache<K, V>::getRecord(const K& key) const {
if (!DataBase::Table<K, V>::db->opened) {
throw Closed("getRecord", DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
typename std::map<K, V>::const_iterator itr = cache->find(key);
if (itr != cache->end()) {
return itr->second;
}
if (abscent->count(key) == 0) {
throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
try {
V value = Table<K, V>::getRecord(key);
cache->insert(std::make_pair(key, value));
return value;
} catch (const NotFound& error) {
abscent->insert(key);
throw error;
}
}
template<class K, class V>
void DataBase::Cache<K, V>::removeRecord(const K& key) {
if (!DataBase::Table<K, V>::db->opened) {
throw Closed("removeRecord", DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
typename std::pair<typename std::set<K>::const_iterator, bool> pair = abscent->insert(key);
if (!pair.second) {
throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
cache->erase(key);
Table<K, V>::removeRecord(key);
}
#endif //DATABASE_CACHE_HPP

View File

@ -33,6 +33,8 @@ class DataBase
public: public:
template <class K, class V> template <class K, class V>
class Table; class Table;
template <class K, class V>
class Cache;
DataBase(const QString& name, uint16_t mapSize = 10); DataBase(const QString& name, uint16_t mapSize = 10);
~DataBase(); ~DataBase();
@ -47,9 +49,15 @@ public:
template <class K, class V> template <class K, class V>
Table<K, V>* addTable(const std::string& name); Table<K, V>* addTable(const std::string& name);
template <class K, class V>
Cache<K, V>* addCache(const std::string& name);
template <class K, class V> template <class K, class V>
Table<K, V>* getTable(const std::string& name); Table<K, V>* getTable(const std::string& name);
template <class K, class V>
Cache<K, V>* getCache(const std::string& name);
public: public:
//exceptions //exceptions
class Exception; class Exception;
@ -80,9 +88,25 @@ DataBase::Table<K, V>* DataBase::addTable(const std::string& p_name) {
return table; return table;
} }
template<class K, class V>
DataBase::Cache<K, V> * DataBase::addCache(const std::string& p_name) {
if (opened) {
throw Opened(name, "add cache " + p_name);
}
DataBase::Cache<K, V>* cache = new DataBase::Cache<K, V>(p_name, this);
tables.insert(std::make_pair(p_name, (_Table*)cache));
return cache;
}
template <class K, class V> template <class K, class V>
DataBase::Table<K, V>* DataBase::getTable(const std::string& p_name) { DataBase::Table<K, V>* DataBase::getTable(const std::string& p_name) {
return static_cast<DataBase::Table<K, V>*>(tables.at(p_name)); return static_cast<DataBase::Table<K, V>*>(tables.at(p_name));
} }
template <class K, class V>
DataBase::Cache<K, V>* DataBase::getCache(const std::string& p_name) {
return static_cast<DataBase::Cache<K, V>*>(tables.at(p_name));
}
#endif // CORE_DATABASE_H #endif // CORE_DATABASE_H

12
table.h
View File

@ -49,17 +49,17 @@ protected:
template <class K, class V> template <class K, class V>
class DataBase::Table : public DataBase::_Table { class DataBase::Table : public DataBase::_Table {
friend class DataBase; friend class DataBase;
private: protected:
Table(const std::string& name, DataBase* parent); Table(const std::string& name, DataBase* parent);
~Table() override; ~Table() override;
public: public:
void addRecord(const K& key, const V& value); virtual void addRecord(const K& key, const V& value);
void changeRecord(const K& key, const V& value); virtual void changeRecord(const K& key, const V& value);
void removeRecord(const K& key); virtual void removeRecord(const K& key);
V getRecord(const K& key) const; virtual V getRecord(const K& key) const;
private: protected:
Serializer<K>* keySerializer; Serializer<K>* keySerializer;
Serializer<V>* valueSerializer; Serializer<V>* valueSerializer;

View File

@ -2,6 +2,7 @@
#include "database.h" #include "database.h"
#include "table.h" #include "table.h"
#include "cache.h"
#include <QString> #include <QString>
@ -10,7 +11,8 @@ protected:
DataBaseTest(): DataBaseTest():
::testing::Test(), ::testing::Test(),
t1(db->getTable<uint32_t, uint32_t>("table1")), t1(db->getTable<uint32_t, uint32_t>("table1")),
t2(db->getTable<QString, QString>("table2")) {} t2(db->getTable<QString, QString>("table2")),
c1(db->getCache<int8_t, std::string>("cache1")) {}
~DataBaseTest() {} ~DataBaseTest() {}
@ -19,6 +21,7 @@ protected:
db = new DataBase("testBase"); db = new DataBase("testBase");
db->addTable<uint32_t, uint32_t>("table1"); db->addTable<uint32_t, uint32_t>("table1");
db->addTable<QString, QString>("table2"); db->addTable<QString, QString>("table2");
db->addCache<int8_t, std::string>("cache1");
} }
} }
@ -33,6 +36,7 @@ protected:
DataBase::Table<uint32_t, uint32_t>* t1; DataBase::Table<uint32_t, uint32_t>* t1;
DataBase::Table<QString, QString>* t2; DataBase::Table<QString, QString>* t2;
DataBase::Cache<int8_t, std::string>* c1;
}; };
@ -120,6 +124,7 @@ TEST_F(DataBaseTest, Persistence) {
db = new DataBase("testBase"); db = new DataBase("testBase");
t1 = db->addTable<uint32_t, uint32_t>("table1"); t1 = db->addTable<uint32_t, uint32_t>("table1");
t2 = db->addTable<QString, QString>("table2"); t2 = db->addTable<QString, QString>("table2");
c1 = db->addCache<int8_t, std::string>("cache1");
db->open(); db->open();
EXPECT_EQ(t1->getRecord(3), 15); EXPECT_EQ(t1->getRecord(3), 15);