diff --git a/cache.h b/cache.h index 4c30fac..4f9ccbf 100644 --- a/cache.h +++ b/cache.h @@ -39,6 +39,7 @@ private: public: 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 V getRecord(const K& key) const override; diff --git a/cache.hpp b/cache.hpp index 9a509b3..98485c5 100644 --- a/cache.hpp +++ b/cache.hpp @@ -52,8 +52,35 @@ void DataBase::Cache::addRecord(const K& key, const V& value) { Table::addRecord(key, value); cache->insert(std::make_pair(key, value)); + + if (*mode != Mode::full) { + abscent->erase(key); + } } +template +bool DataBase::Cache::forceRecord(const K& key, const V& value) { + if (!DataBase::Table::db->opened) { + throw Closed("forceRecord", DataBase::Table::db->name, DataBase::Table::name); + } + + bool added = Table::forceRecord(key, value); + if (*mode == Mode::full) { + (*cache)[key] = value; + } else { + if (added) { + abscent->erase(key); + } + std::pair::iterator, bool> result = cache->insert(std::make_pair(key, value)); + if (!result.second) { + result.first->second = value; + } else if (!added) { //this way database had value but cache didn't, so, need to decrease sizeDifference + handleMode(); + } + } + + return added; +} template void DataBase::Cache::changeRecord(const K& key, const V& value) { diff --git a/table.h b/table.h index a2abe81..fa647f7 100644 --- a/table.h +++ b/table.h @@ -55,6 +55,7 @@ protected: public: virtual void addRecord(const K& key, const V& value); + virtual bool forceRecord(const K& key, const V& value); //returns true if there was addition, false if change virtual void changeRecord(const K& key, const V& value); virtual void removeRecord(const K& key); virtual V getRecord(const K& key) const; diff --git a/table.hpp b/table.hpp index db4f428..c4d0bf8 100644 --- a/table.hpp +++ b/table.hpp @@ -58,7 +58,38 @@ void DataBase::Table::addRecord(const K& key, const V& value) { } } +template +bool DataBase::Table::forceRecord(const K& key, const V& value) { + if (!db->opened) { + throw Closed("forceRecord", db->name, name); + } + bool added; + MDB_val lmdbKey = keySerializer->setData(key); + MDB_val lmdbData; + MDB_txn *txn; + mdb_txn_begin(db->environment, NULL, 0, &txn); + int rc; + rc = mdb_get(txn, dbi, &lmdbKey, &lmdbData); + if (rc == 0) { + added = false; + } else if (rc == MDB_NOTFOUND) { + added = true; + } else { + mdb_txn_abort(txn); + throw Unknown(db->name, mdb_strerror(rc), name); + } + lmdbData = valueSerializer->setData(value); + rc = mdb_put(txn, dbi, &lmdbKey, &lmdbData, 0); + if (rc != 0) { + mdb_txn_abort(txn); + throw Unknown(db->name, mdb_strerror(rc), name); + } else { + mdb_txn_commit(txn); + } + + return added; +} template void DataBase::Table::changeRecord(const K& key, const V& value) {