common: Enforces the methods lru_pin() and lru_unpin()

If lru_*pin() is called twice, the counter will be incr/decr
incorrectly since it will count more/less pinned objects than
there is and so corrupts the balancing (lru_adjust()).

Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@cloudwatt.com>
This commit is contained in:
Sahid Orentino Ferdjaoui 2014-06-11 15:40:38 +02:00
parent d48ed68a70
commit d93e74e7e7
2 changed files with 41 additions and 5 deletions

View File

@ -315,14 +315,16 @@ class LRU {
};
inline void LRUObject::lru_pin()
{
inline void LRUObject::lru_pin() {
if (lru && !lru_pinned) {
lru->lru_num_pinned++;
lru->lru_adjust();
}
lru_pinned = true;
if (lru) lru->lru_num_pinned++;
}
inline void LRUObject::lru_unpin() {
lru_pinned = false;
if (lru) {
if (lru && lru_pinned) {
lru->lru_num_pinned--;
// move from pintail -> bot
@ -330,7 +332,9 @@ inline void LRUObject::lru_unpin() {
lru->lru_pintail.remove(this);
lru->lru_bot.insert_tail(this);
}
lru->lru_adjust();
}
lru_pinned = false;
}
#endif

View File

@ -89,6 +89,38 @@ TEST(lru, Adjust) {
ASSERT_EQ(100, lru.lru_get_size());
}
TEST(lru, Pinning) {
LRU lru = LRU();
Item *ob0 = new Item(0);
Item *ob1 = new Item(1);
// test before ob1 are in a LRU
ob1->lru_pin();
ASSERT_FALSE(ob1->lru_is_expireable());
ob1->lru_unpin();
ASSERT_TRUE(ob1->lru_is_expireable());
// test when ob1 are in a LRU
lru.lru_touch(ob0);
lru.lru_touch(ob1);
ob1->lru_pin();
ob1->lru_pin(); // Verify that, one incr.
ASSERT_EQ(1, lru.lru_get_num_pinned());
ASSERT_FALSE(ob1->lru_is_expireable());
ob1->lru_unpin();
ob1->lru_unpin(); // Verify that, one decr.
ASSERT_EQ(0, lru.lru_get_num_pinned());
ASSERT_TRUE(ob1->lru_is_expireable());
ASSERT_EQ(0, (static_cast<Item*>(lru.lru_expire()))->id);
ob0->lru_pin();
ASSERT_EQ(1, (static_cast<Item*>(lru.lru_expire()))->id);
}
/*
* Local Variables: