1
0
forked from blue/lmdbal

two more methods for getting all records from cache, one more test for reading all

This commit is contained in:
Blue 2023-04-07 02:51:45 +03:00
parent 181a645efc
commit 064277fa6e
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
3 changed files with 102 additions and 24 deletions

View File

@ -93,6 +93,8 @@ public:
virtual std::map<K, V> readAll() const override; virtual std::map<K, V> readAll() const override;
virtual std::map<K, V> readAll(TransactionID txn) const override; virtual std::map<K, V> readAll(TransactionID txn) const override;
virtual void readAll(std::map<K, V>& out) const override;
virtual void readAll(std::map<K, V>& out, TransactionID txn) const override;
virtual void replaceAll(const std::map<K, V>& data) override; virtual void replaceAll(const std::map<K, V>& data) override;
virtual void replaceAll(const std::map<K, V>& data, TransactionID txn) override; virtual void replaceAll(const std::map<K, V>& data, TransactionID txn) override;
virtual SizeType addRecords(const std::map<K, V>& data, bool overwrite = false) override; virtual SizeType addRecords(const std::map<K, V>& data, bool overwrite = false) override;

View File

@ -229,7 +229,6 @@ void LMDBAL::Cache<K, V>::getRecord(const K& key, V& out) const {
} }
} }
template<class K, class V> template<class K, class V>
V LMDBAL::Cache<K, V>::getRecord(const K& key, TransactionID txn) const { V LMDBAL::Cache<K, V>::getRecord(const K& key, TransactionID txn) const {
iStorage::ensureOpened(iStorage::getRecordMethodName); iStorage::ensureOpened(iStorage::getRecordMethodName);
@ -449,41 +448,64 @@ std::map<K, V> LMDBAL::Cache<K, V>::readAll() const {
return *cache; return *cache;
} }
template<class K, class V>
void LMDBAL::Cache<K, V>::readAll(std::map<K, V>& out) const {
iStorage::ensureOpened(iStorage::readAllMethodName);
if (*mode != Mode::full) { //there is a room for optimization
*mode = Mode::full; //I can read and deserialize only those values
Storage<K, V>::readAll(out); //that are missing in the cache
*cache = out;
abscent->clear();
*sizeDifference = 0;
}
}
template<class K, class V> template<class K, class V>
std::map<K, V> LMDBAL::Cache<K, V>::readAll(TransactionID txn) const { std::map<K, V> LMDBAL::Cache<K, V>::readAll(TransactionID txn) const {
iStorage::ensureOpened(iStorage::readAllMethodName); iStorage::ensureOpened(iStorage::readAllMethodName);
std::map<K, V> out;
readAll(out, txn);
return out;
}
template<class K, class V>
void LMDBAL::Cache<K, V>::readAll(std::map<K, V>& out, TransactionID txn) const {
iStorage::ensureOpened(iStorage::readAllMethodName);
typename TransactionCache::iterator tc = transactionCache->find(txn); typename TransactionCache::iterator tc = transactionCache->find(txn);
if (tc != transactionCache->end()) { if (tc != transactionCache->end()) {
Queue& queue = tc->second; Queue& queue = tc->second;
if (*mode != Mode::full) { if (*mode != Mode::full) {
std::map<K, V> result = *cache; out = *cache;
for (typename Queue::const_iterator i = queue.begin(), end = queue.end(); i != end; ++i) { for (typename Queue::const_iterator i = queue.begin(), end = queue.end(); i != end; ++i) {
const Entry& entry = *i; const Entry& entry = *i;
switch (entry.first) { switch (entry.first) {
case Operation::add: case Operation::add:
result.insert(*static_cast<std::pair<K, V>*>(entry.second)); out.insert(*static_cast<std::pair<K, V>*>(entry.second));
break; break;
case Operation::remove: case Operation::remove:
result.erase(*static_cast<K*>(entry.second)); out.erase(*static_cast<K*>(entry.second));
break; break;
case Operation::change: { case Operation::change: {
std::pair<K, V>* pair = static_cast<std::pair<K, V>*>(entry.second); std::pair<K, V>* pair = static_cast<std::pair<K, V>*>(entry.second);
result.at(pair->first) = pair->second; out.at(pair->first) = pair->second;
} }
break; break;
case Operation::force:{ case Operation::force:{
const std::tuple<bool, K, V>& tuple = const std::tuple<bool, K, V>& tuple =
*static_cast<std::tuple<bool, K, V>*>(entry.second); *static_cast<std::tuple<bool, K, V>*>(entry.second);
result[std::get<1>(tuple)] = std::get<2>(tuple); out[std::get<1>(tuple)] = std::get<2>(tuple);
} }
break; break;
case Operation::drop: case Operation::drop:
result.clear(); out.clear();
break; break;
case Operation::replace: case Operation::replace:
result = *static_cast<std::map<K, V>*>(entry.second); out = *static_cast<std::map<K, V>*>(entry.second);
break; break;
case Operation::addMany: { case Operation::addMany: {
const std::tuple<bool, SizeType, std::map<K, V>>& t = const std::tuple<bool, SizeType, std::map<K, V>>& t =
@ -492,35 +514,28 @@ std::map<K, V> LMDBAL::Cache<K, V>::readAll(TransactionID txn) const {
bool overwrite = std::get<0>(t); bool overwrite = std::get<0>(t);
for (const std::pair<const K, V>& pair : added) { for (const std::pair<const K, V>& pair : added) {
if (overwrite) if (overwrite)
result[pair.first] = pair.second; out[pair.first] = pair.second;
else else
result.insert(pair); out.insert(pair);
} }
} }
break; break;
} }
} }
return result;
} else { } else {
std::map<K, V>* result = new std::map<K, V>(); Storage<K, V>::readAll(out, txn);
Storage<K, V>::readAll(*result, txn);
//queue.clear(); //since I'm getting a complete state of the database //queue.clear(); //since I'm getting a complete state of the database
queue.emplace_back(Operation::replace, result); //I can as well erase all previous cache entries queue.emplace_back(Operation::replace, new std::map<K, V>(out)); //I can as well erase all previous cache entries
return *result;
} }
} else { } else {
if (*mode != Mode::full) { //there is a room for optimization if (*mode != Mode::full) { //there is a room for optimization
*mode = Mode::full; //I can read and deserialize only those values *mode = Mode::full; //I can read and deserialize only those values
*cache = Storage<K, V>::readAll(txn); //that are missing in the cache Storage<K, V>::readAll(out); //that are missing in the cache
*cache = out;
abscent->clear(); abscent->clear();
*sizeDifference = 0; *sizeDifference = 0;
} }
return *cache;
} }
} }

View File

@ -301,3 +301,64 @@ TEST_F(BaseTest, ReadAll) {
EXPECT_EQ(m2.size(), 3); EXPECT_EQ(m2.size(), 3);
EXPECT_EQ(m3.size(), 4); EXPECT_EQ(m3.size(), 4);
} }
TEST_F(BaseTest, ReplaceAll) {
EXPECT_EQ(db->ready(), true);
t1->replaceAll({
{7, 48},
{194, 582},
{857, 39},
{9717, 8}
});
t2->replaceAll({
{"bringin", "keyboard"},
{"cluster", "throttle"},
{"ronin", "cheese"}
});
c1->replaceAll({});
EXPECT_EQ(t1->count(), 4);
EXPECT_EQ(t2->count(), 3);
EXPECT_EQ(c1->count(), 0);
EXPECT_FALSE(t1->checkRecord(2));
EXPECT_FALSE(t1->checkRecord(58));
EXPECT_FALSE(t1->checkRecord(68));
EXPECT_FALSE(t2->checkRecord("sdfhga"));
EXPECT_FALSE(t2->checkRecord("prophecy"));
EXPECT_FALSE(t2->checkRecord("lawfirm"));
EXPECT_FALSE(c1->checkRecord(15));
EXPECT_FALSE(c1->checkRecord(12));
EXPECT_FALSE(c1->checkRecord(89));
EXPECT_FALSE(c1->checkRecord(98));
EXPECT_EQ(t1->getRecord(7), 48);
EXPECT_EQ(t1->getRecord(194), 582);
EXPECT_EQ(t1->getRecord(857), 39);
EXPECT_EQ(t1->getRecord(9717), 8);
EXPECT_EQ(t2->getRecord("bringin"), "keyboard");
EXPECT_EQ(t2->getRecord("cluster"), "throttle");
EXPECT_EQ(t2->getRecord("ronin"), "cheese");
c1->replaceAll({
{68, "quality"},
{31, "ridgid body"},
{16, "fermentation on your kind"},
{22, "pseudo"},
{-117, "lance of Michael"},
});
EXPECT_EQ(c1->count(), 5);
EXPECT_EQ(c1->getRecord(68), "quality");
EXPECT_EQ(c1->getRecord(31), "ridgid body");
EXPECT_EQ(c1->getRecord(16), "fermentation on your kind");
EXPECT_EQ(c1->getRecord(22), "pseudo");
EXPECT_EQ(c1->getRecord(-117), "lance of Michael");
}