forked from blue/lmdbal
some more transaction thought on cache
This commit is contained in:
parent
f0779ae2aa
commit
8be63d7551
6 changed files with 241 additions and 58 deletions
180
src/cache.hpp
180
src/cache.hpp
|
@ -28,7 +28,8 @@ LMDBAL::Cache<K, V>::Cache(const std::string& p_name, Base* parent):
|
|||
mode(new Mode),
|
||||
cache(new std::map<K, V>()),
|
||||
abscent(new std::set<K>()),
|
||||
sizeDifference(new uint32_t)
|
||||
sizeDifference(new uint32_t),
|
||||
transactionCache(new TransactionCache)
|
||||
{
|
||||
*mode = Mode::nothing;
|
||||
*sizeDifference = 0;
|
||||
|
@ -36,6 +37,7 @@ LMDBAL::Cache<K, V>::Cache(const std::string& p_name, Base* parent):
|
|||
|
||||
template<class K, class V>
|
||||
LMDBAL::Cache<K, V>::~Cache() {
|
||||
delete transactionCache;
|
||||
delete sizeDifference;
|
||||
delete mode;
|
||||
delete cache;
|
||||
|
@ -50,6 +52,11 @@ void LMDBAL::Cache<K, V>::addRecord(const K& key, const V& value) {
|
|||
iStorage::throwDuplicate(iStorage::toString(key));
|
||||
|
||||
Storage<K, V>::addRecord(key, value);
|
||||
handleAddRecord(key, value);
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::handleAddRecord(const K& key, const V& value) {
|
||||
cache->insert(std::make_pair(key, value));
|
||||
|
||||
if (*mode != Mode::full)
|
||||
|
@ -61,6 +68,13 @@ bool LMDBAL::Cache<K, V>::forceRecord(const K& key, const V& value) {
|
|||
iStorage::ensureOpened(iStorage::forceRecordMethodName);
|
||||
|
||||
bool added = Storage<K, V>::forceRecord(key, value);
|
||||
handleForceRecord(key, value, added);
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::handleForceRecord(const K& key, const V& value, bool added) {
|
||||
if (*mode == Mode::full) {
|
||||
(*cache)[key] = value;
|
||||
} else {
|
||||
|
@ -73,8 +87,6 @@ bool LMDBAL::Cache<K, V>::forceRecord(const K& key, const V& value) {
|
|||
else if (!added) //this way database had value but cache didn't, so, need to decrease sizeDifference
|
||||
handleMode();
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
|
@ -106,6 +118,19 @@ void LMDBAL::Cache<K, V>::changeRecord(const K& key, const V& value) {
|
|||
}
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::handleChangeRecord(const K& key, const V& value) {
|
||||
if (*mode == Mode::full) {
|
||||
cache->at(key) = value;
|
||||
} else {
|
||||
typename std::pair<typename std::map<K, V>::iterator, bool> res = cache->insert(std::make_pair(key, value));
|
||||
if (!res.second)
|
||||
res.first->second = value;
|
||||
else
|
||||
handleMode();
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
V LMDBAL::Cache<K, V>::getRecord(const K& key) const {
|
||||
iStorage::ensureOpened(iStorage::getRecordMethodName);
|
||||
|
@ -181,9 +206,27 @@ void LMDBAL::Cache<K, V>::replaceAll(const std::map<K, V>& data) {
|
|||
}
|
||||
|
||||
template<class K, class V>
|
||||
uint32_t LMDBAL::Cache<K, V>::addRecords(const std::map<K, V>& data, bool overwrite) {
|
||||
uint32_t newSize = Storage<K, V>::addRecords(data, overwrite);
|
||||
void LMDBAL::Cache<K, V>::handleReplaceAll(std::map<K, V>* data) {
|
||||
delete cache;
|
||||
cache = data;
|
||||
|
||||
if (*mode != Mode::full) {
|
||||
*mode = Mode::full;
|
||||
abscent->clear();
|
||||
*sizeDifference = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
LMDBAL::SizeType LMDBAL::Cache<K, V>::addRecords(const std::map<K, V>& data, bool overwrite) {
|
||||
SizeType newSize = Storage<K, V>::addRecords(data, overwrite);
|
||||
handleAddRecords(data, overwrite, newSize);
|
||||
|
||||
return newSize;
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::handleAddRecords(const std::map<K, V>& data, bool overwrite, SizeType newSize) {
|
||||
Mode& m = *mode;
|
||||
if (m == Mode::nothing)
|
||||
m = Mode::size;
|
||||
|
@ -207,19 +250,27 @@ uint32_t LMDBAL::Cache<K, V>::addRecords(const std::map<K, V>& data, bool overwr
|
|||
abscent->clear();
|
||||
}
|
||||
}
|
||||
|
||||
return newSize;
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::removeRecord(const K& key) {
|
||||
iStorage::ensureOpened(iStorage::removeRecordMethodName);
|
||||
|
||||
typename std::pair<typename std::set<K>::const_iterator, bool> pair = abscent->insert(key);
|
||||
if (!pair.second)
|
||||
bool noKey = false;
|
||||
if (*mode != Mode::full)
|
||||
noKey = cache->count(key) == 0;
|
||||
else
|
||||
noKey = abscent->count(key) > 0;
|
||||
|
||||
if (noKey)
|
||||
iStorage::throwNotFound(iStorage::toString(key));
|
||||
|
||||
Storage<K, V>::removeRecord(key);
|
||||
handleRemoveRecord(key);
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::handleRemoveRecord(const K& key) {
|
||||
if (cache->erase(key) == 0) //if it was not cached and we are now in size mode then the sizeDifference would decrease
|
||||
handleMode();
|
||||
|
||||
|
@ -263,13 +314,120 @@ void LMDBAL::Cache<K, V>::handleMode() const {
|
|||
}
|
||||
|
||||
template<class K, class V>
|
||||
int LMDBAL::Cache<K, V>::drop(MDB_txn * transaction) {
|
||||
int LMDBAL::Cache<K, V>::drop(TransactionID transaction) {
|
||||
int res = Storage<K, V>::drop(transaction);
|
||||
|
||||
transactionCache->at(transaction).emplace_back(Operation::drop, nullptr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::handleDrop() {
|
||||
cache->clear();
|
||||
abscent->clear();
|
||||
*mode = Mode::full;
|
||||
*sizeDifference = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::transactionStarted(TransactionID txn, bool readOnly) const {
|
||||
if (!readOnly)
|
||||
transactionCache->emplace(txn, Queue());
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::transactionCommited(TransactionID txn) {
|
||||
typename TransactionCache::iterator itr = transactionCache->find(txn);
|
||||
if (itr != transactionCache->end()) {
|
||||
Queue& queue = itr->second;
|
||||
for (const Entry& entry : queue)
|
||||
handleTransactionEntry(entry);
|
||||
|
||||
transactionCache->erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::transactionAborted(TransactionID txn) const {
|
||||
typename TransactionCache::iterator itr = transactionCache->find(txn);
|
||||
if (itr != transactionCache->end()) {
|
||||
Queue& queue = itr->second;
|
||||
for (const Entry& entry : queue)
|
||||
destroyTransactionEntry(entry);
|
||||
|
||||
transactionCache->erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::handleTransactionEntry(const Entry& entry) {
|
||||
switch (entry.first) {
|
||||
case Operation::add: {
|
||||
std::pair<K, V>* pair = static_cast<std::pair<K, V>*>(entry.second);
|
||||
handleAddRecord(pair->first, pair->second);
|
||||
delete pair;
|
||||
}
|
||||
break;
|
||||
case Operation::remove: {
|
||||
K* key = static_cast<K*>(entry.second);
|
||||
handleRemoveRecord(*key);
|
||||
delete key;
|
||||
}
|
||||
|
||||
break;
|
||||
case Operation::change: {
|
||||
std::pair<K, V>* pair = static_cast<std::pair<K, V>*>(entry.second);
|
||||
handleChangeRecord(pair->first, pair->second);
|
||||
delete pair;
|
||||
}
|
||||
case Operation::force: {
|
||||
std::tuple<bool, K, V>* tuple = static_cast<std::tuple<bool, K, V>*>(entry.second);
|
||||
const std::tuple<bool, K, V>& t = *tuple;
|
||||
handleForceRecord(std::get<1>(t), std::get<2>(t), std::get<0>(t));
|
||||
delete tuple;
|
||||
}
|
||||
break;
|
||||
case Operation::drop:
|
||||
handleDrop();
|
||||
break;
|
||||
case Operation::replace:
|
||||
handleReplaceAll(static_cast<std::map<K, V>*>(entry.second)); //I take ownership, no need to delete
|
||||
break;
|
||||
case Operation::addMany: {
|
||||
std::tuple<bool, SizeType, std::map<K, V>>* tuple = static_cast<std::tuple<bool, SizeType, std::map<K, V>>*>(entry.second);
|
||||
const std::tuple<bool, SizeType, std::map<K, V>>& t = * tuple;
|
||||
handleAddRecords(std::get<2>(t), std::get<0>(t), std::get<1>(t));
|
||||
delete tuple;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class V>
|
||||
void LMDBAL::Cache<K, V>::destroyTransactionEntry(const Entry& entry) const {
|
||||
switch (entry.first) {
|
||||
case Operation::add:
|
||||
delete static_cast<std::pair<K, V>*>(entry.second);
|
||||
break;
|
||||
case Operation::remove:
|
||||
delete static_cast<K*>(entry.second);
|
||||
break;
|
||||
case Operation::change:
|
||||
delete static_cast<std::pair<K, V>*>(entry.second);
|
||||
break;
|
||||
case Operation::force:
|
||||
delete static_cast<std::tuple<bool, K, V>*>(entry.second);
|
||||
break;
|
||||
case Operation::drop:
|
||||
break;
|
||||
case Operation::replace:
|
||||
delete static_cast<std::map<K, V>*>(entry.second);
|
||||
break;
|
||||
case Operation::addMany:
|
||||
delete static_cast<std::tuple<bool, SizeType, std::map<K, V>>*>(entry.second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //LMDBAL_CACHE_HPP
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue