136 lines
5.6 KiB
C++
136 lines
5.6 KiB
C++
/*
|
|
* LMDB Abstraction Layer.
|
|
* Copyright (C) 2023 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/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <map>
|
|
#include <set>
|
|
#include <tuple>
|
|
|
|
#include "storage.h"
|
|
|
|
namespace LMDBAL {
|
|
|
|
template <class K, class V>
|
|
class Cache : public Storage<K, V> {
|
|
friend class Base;
|
|
enum class Mode { /**<it's a cache state when we:*/
|
|
nothing, /**< - know nothing about records in database on disk*/
|
|
size, /**< - know just an amount of records*/
|
|
full /**< - shure that our cache is equal to the database on disk*/
|
|
};
|
|
|
|
enum class Operation { /**<Operation type, used in pcrocessing cache modification after writable transaction is commited*/
|
|
add,
|
|
remove,
|
|
change,
|
|
force,
|
|
drop,
|
|
replace,
|
|
addMany
|
|
};
|
|
|
|
typedef std::pair<Operation, void*> Entry;
|
|
typedef std::list<Entry> Queue;
|
|
typedef std::map<TransactionID, Queue> TransactionCache;
|
|
|
|
protected:
|
|
Cache(Base* parent, const std::string& name, bool duplicates = false);
|
|
~Cache() override;
|
|
|
|
virtual void handleDrop() override;
|
|
virtual void transactionStarted(TransactionID txn, bool readOnly) const override;
|
|
virtual void transactionCommited(TransactionID txn) override;
|
|
virtual void transactionAborted(TransactionID txn) const override;
|
|
|
|
virtual void discoveredRecord(const K& key, const V& value) const override;
|
|
virtual void discoveredRecord(const K& key, const V& value, TransactionID txn) const override;
|
|
|
|
virtual SizeType count(TransactionID txn) const override;
|
|
virtual void addRecord(const K& key, const V& value, TransactionID txn) override;
|
|
virtual bool forceRecord(const K& key, const V& value, TransactionID txn) override;
|
|
virtual void changeRecord(const K& key, const V& value, TransactionID txn) override;
|
|
virtual void removeRecord(const K& key, TransactionID txn) override;
|
|
virtual bool checkRecord(const K& key, TransactionID txn) const override;
|
|
virtual void getRecord(const K& key, V& out, TransactionID txn) const override;
|
|
virtual V getRecord(const K& key, TransactionID txn) const override;
|
|
virtual std::map<K, V> readAll(TransactionID txn) const override;
|
|
virtual void readAll(std::map<K, V>& out, TransactionID txn) const override;
|
|
virtual void replaceAll(const std::map<K, V>& data, TransactionID txn) override;
|
|
virtual SizeType addRecords(const std::map<K, V>& data, TransactionID txn, bool overwrite = false) override;
|
|
|
|
private:
|
|
void handleMode() const;
|
|
|
|
void handleTransactionEntry(const Entry& entry);
|
|
void destroyTransactionEntry(const Entry& entry) const;
|
|
|
|
void handleAddRecord(const K& key, const V& value);
|
|
void handleRemoveRecord(const K& key);
|
|
void handleChangeRecord(const K& key, const V& value);
|
|
void handleForceRecord(const K& key, const V& value, bool added);
|
|
void handleReplaceAll(std::map<K, V>* data);
|
|
void handleAddRecords(const std::map<K, V>& data, bool overwrite, SizeType newSize);
|
|
void appendToCache(const K& key, const V& value) const;
|
|
|
|
public:
|
|
using Storage<K, V>::drop;
|
|
using Storage<K, V>::addRecord;
|
|
using Storage<K, V>::forceRecord;
|
|
using Storage<K, V>::changeRecord;
|
|
using Storage<K, V>::removeRecord;
|
|
using Storage<K, V>::checkRecord;
|
|
using Storage<K, V>::getRecord;
|
|
using Storage<K, V>::readAll;
|
|
using Storage<K, V>::replaceAll;
|
|
using Storage<K, V>::addRecords;
|
|
using Storage<K, V>::count;
|
|
virtual int drop(const WriteTransaction& transaction) override;
|
|
virtual void addRecord(const K& key, const V& value) override;
|
|
virtual bool forceRecord(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 bool checkRecord(const K& key) const override;
|
|
virtual void getRecord(const K& key, V& out) const override;
|
|
virtual V getRecord(const K& key) const override;
|
|
virtual SizeType count() const override;
|
|
|
|
virtual std::map<K, V> readAll() const override;
|
|
virtual void readAll(std::map<K, V>& out) const override;
|
|
virtual void replaceAll(const std::map<K, V>& data) override;
|
|
virtual SizeType addRecords(const std::map<K, V>& data, bool overwrite = false) override;
|
|
|
|
protected:
|
|
/**
|
|
* \brief Cache mode
|
|
*
|
|
* Sometimes we have a complete information about the content of the database,
|
|
* and we don't even need to call lmdb to fetch or check for data.
|
|
* This member actually shows what is the current state, more about them you can read in Enum descriptions
|
|
*/
|
|
mutable Mode mode;
|
|
std::map<K, V>* cache; /**<\brief Cached data*/
|
|
std::set<K>* abscent; /**<\brief Set of keys that are definitely not in the cache*/
|
|
mutable SizeType sizeDifference; /**<\brief Difference of size between cached data and amount of records in the lmdb storage*/
|
|
TransactionCache* transactionCache; /**<\brief All changes made under under uncommited transactions*/
|
|
};
|
|
|
|
}
|
|
|
|
#include "cache.hpp"
|