]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common: Enforces the methods lru_pin() and lru_unpin() 1951/head
authorSahid Orentino Ferdjaoui <sahid.ferdjaoui@cloudwatt.com>
Wed, 11 Jun 2014 13:40:38 +0000 (15:40 +0200)
committerSahid Orentino Ferdjaoui <sahid.ferdjaoui@cloudwatt.com>
Mon, 16 Jun 2014 13:54:57 +0000 (15:54 +0200)
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>
src/include/lru.h
src/test/common/test_lru.cc

index 7024042e1602701e60ea9ce5c11c0a02543c478c..6a9427420e736fde6ce3e099533d0b3e5802e994 100644 (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
index 7a0a1413cf1a3389df37fb8dac3b4ccaf9db96d8..fb6f6529949f0b289e0c4d9b6dae41846b788a46 100644 (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: