1
0
forked from blue/lmdbal

some debug, some idea how to utilize home hints of data by cache

This commit is contained in:
Blue 2022-10-08 19:45:07 +03:00
parent a613eaed27
commit c23dae2a25
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
2 changed files with 91 additions and 21 deletions

18
cache.h
View File

@ -25,27 +25,31 @@
template <class K, class V> template <class K, class V>
class DataBase::Cache : public DataBase::Table<K, V> { class DataBase::Cache : public DataBase::Table<K, V> {
friend class DataBase; friend class DataBase;
enum class Mode { enum class Mode { //it's a cache state when we:
nothing, nothing, // - know nothing about records in database on disk
size, size, // - know just an amount of records
full full // - shure that our cache is equal to the database on disk
}; };
protected: protected:
Cache(const std::string& name, DataBase* parent); Cache(const std::string& name, DataBase* parent);
~Cache() override; ~Cache() override;
private:
void handleMode() const;
public: public:
virtual void addRecord(const K& key, const V& value) override; virtual void addRecord(const K& key, const V& value) override;
virtual void changeRecord(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 void removeRecord(const K& key) override;
virtual V getRecord(const K& key) const override; virtual V getRecord(const K& key) const override;
//virtual uint32_t count() const; virtual uint32_t count() const override;
//virtual void drop(); virtual void drop() override;
protected: protected:
Mode mode; Mode* mode;
std::map<K, V>* cache; std::map<K, V>* cache;
std::set<K>* abscent; std::set<K>* abscent;
uint32_t* sizeDifference;
}; };
#include "cache.hpp" #include "cache.hpp"

View File

@ -23,14 +23,19 @@
template<class K, class V> template<class K, class V>
DataBase::Cache<K, V>::Cache(const std::string& p_name, DataBase* parent): DataBase::Cache<K, V>::Cache(const std::string& p_name, DataBase* parent):
DataBase::Table<K, V>(p_name, parent), DataBase::Table<K, V>(p_name, parent),
mode(Mode::nothing), mode(new Mode),
cache(new std::map<K, V>()), cache(new std::map<K, V>()),
abscent(new std::set<K>()) abscent(new std::set<K>()),
sizeDifference(new uint32_t)
{ {
*mode = Mode::nothing;
*sizeDifference = 0;
} }
template<class K, class V> template<class K, class V>
DataBase::Cache<K, V>::~Cache() { DataBase::Cache<K, V>::~Cache() {
delete sizeDifference;
delete mode;
delete cache; delete cache;
delete abscent; delete abscent;
} }
@ -50,25 +55,38 @@ void DataBase::Cache<K, V>::addRecord(const K& key, const V& value) {
} }
template<class K, class V> template<class K, class V>
void DataBase::Cache<K, V>::changeRecord(const K& key, const V& value) { void DataBase::Cache<K, V>::changeRecord(const K& key, const V& value) {
if (!DataBase::Table<K, V>::db->opened) { if (!DataBase::Table<K, V>::db->opened) {
throw Closed("changeRecord", DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name); throw Closed("changeRecord", DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
} }
if (*mode == Mode::full) {
typename std::map<K, V>::iterator itr = cache->find(key); typename std::map<K, V>::iterator itr = cache->find(key);
if (itr == cache->end() || abscent->count(key) > 0) { if (itr != cache->end()) {
throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
}
Table<K, V>::changeRecord(key, value);
itr->second = value;
} else {
if (abscent->count(key) > 0) {
throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name); throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
} }
try { try {
Table<K, V>::changeRecord(key, value); Table<K, V>::changeRecord(key, value);
typename std::map<K, V>::iterator itr = cache->find(key);
if (itr != cache->end()) {
itr->second = value; itr->second = value;
} else {
cache->insert(std::make_pair(key, value));
handleMode();
}
} catch (const NotFound& error) { } catch (const NotFound& error) {
abscent->insert(key); abscent->insert(key);
throw error; throw error;
} }
}
} }
template<class K, class V> template<class K, class V>
@ -82,13 +100,14 @@ V DataBase::Cache<K, V>::getRecord(const K& key) const {
return itr->second; return itr->second;
} }
if (abscent->count(key) == 0) { if (*mode == Mode::full || abscent->count(key) == 0) {
throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name); throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name);
} }
try { try {
V value = Table<K, V>::getRecord(key); V value = Table<K, V>::getRecord(key);
cache->insert(std::make_pair(key, value)); cache->insert(std::make_pair(key, value));
handleMode();
return value; return value;
} catch (const NotFound& error) { } catch (const NotFound& error) {
abscent->insert(key); abscent->insert(key);
@ -107,8 +126,55 @@ void DataBase::Cache<K, V>::removeRecord(const K& key) {
throw NotFound(DataBase::_Table::toString(key), DataBase::Table<K, V>::db->name, DataBase::Table<K, V>::name); 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); Table<K, V>::removeRecord(key);
if (cache->erase(key) == 0) { //if it was not cached and we are now in size mode then the sizeDifference would decrease
handleMode();
}
if (*mode != Mode::full) {
abscent->insert(key);
}
}
template<class K, class V>
uint32_t DataBase::Cache<K, V>::count() const {
switch (*mode) {
case Mode::nothing:
{
uint32_t sz = DataBase::Table<K, V>::count();
*sizeDifference = sz - cache->size();
if (sz == 0) {
*mode = Mode::full;
abscent->clear();
} else {
*mode = Mode::size;
}
return sz;
}
case Mode::size:
return cache->size() + *sizeDifference;
case Mode::full:
return cache->size();
}
}
template<class K, class V>
void DataBase::Cache<K, V>::handleMode() const {
if (*mode == Mode::size) {
--(*sizeDifference);
if (*sizeDifference == 0) {
*mode = Mode::full;
abscent->clear();
}
}
}
template<class K, class V>
void DataBase::Cache<K, V>::drop() {
DataBase::Table<K, V>::drop();
cache->clear();
abscent->clear();
*mode = Mode::full;
*sizeDifference = 0;
} }
#endif //DATABASE_CACHE_HPP #endif //DATABASE_CACHE_HPP