#include "include/config.h"
-#define LRU_POS_NONE 0
-#define LRU_POS_TOP 1
-#define LRU_POS_BOT 2
-#define LRU_POS_PINTAIL 3
-
class LRUObject {
private:
LRUObject *lru_next, *lru_prev;
- char lru_pos;
bool lru_expireable;
class LRU *lru;
+ class LRUList *lru_list;
public:
LRUObject() {
lru_next = lru_prev = NULL;
- lru_pos = LRU_POS_NONE;
+ lru_list = 0;
lru_expireable = true;
lru = 0;
}
- bool lru_get_pos() { return lru_pos; }
- void lru_set_pos(char p) { lru_pos = p; }
-
// pin/unpin item in cache
void lru_pin();
void lru_unpin();
bool lru_is_expireable() { return lru_expireable; }
friend class LRU;
- //friend class MDCache;
+ friend class LRUList;
};
+class LRUList {
+ private:
+ LRUObject *head, *tail;
+ __uint32_t len;
+
+ public:
+ LRUList() {
+ head = tail = 0;
+ len = 0;
+ }
+
+ __uint32_t get_length() { return len; }
+
+ LRUObject *get_head() {
+ return head;
+ }
+ LRUObject *get_tail() {
+ return tail;
+ }
+
+ void insert_head(LRUObject *o) {
+ o->lru_next = head;
+ o->lru_prev = NULL;
+ if (head) {
+ head->lru_prev = o;
+ } else {
+ tail = o;
+ }
+ head = o;
+ o->lru_list = this;
+ len++;
+ }
+ void insert_tail(LRUObject *o) {
+ o->lru_next = NULL;
+ o->lru_prev = tail;
+ if (tail) {
+ tail->lru_next = o;
+ } else {
+ head = o;
+ }
+ tail = o;
+ o->lru_list = this;
+ len++;
+ }
+
+ void remove(LRUObject *o) {
+ assert(o->lru_list == this);
+ if (o->lru_next)
+ o->lru_next->lru_prev = o->lru_prev;
+ else
+ tail = o->lru_prev;
+ if (o->lru_prev)
+ o->lru_prev->lru_next = o->lru_next;
+ else
+ head = o->lru_next;
+ o->lru_next = o->lru_prev = NULL;
+ o->lru_list = 0;
+ assert(len>0);
+ len--;
+ }
+
+};
+
class LRU {
protected:
- LRUObject *lru_tophead, *lru_toptail, *lru_bothead, *lru_bottail;
- LRUObject *lru_pintailhead, *lru_pintailtail;
- __uint32_t lru_ntop, lru_nbot, lru_num, lru_num_pinned;
- double lru_midpoint;
+ LRUList lru_top, lru_bot, lru_pintail;
+ __uint32_t lru_num, lru_num_pinned;
__uint32_t lru_max; // max items
+ double lru_midpoint;
friend class LRUObject;
//friend class MDCache; // hack
+
public:
LRU() {
- lru_ntop = lru_nbot = lru_num = 0;
+ lru_num = 0;
lru_num_pinned = 0;
- lru_tophead = lru_toptail = NULL;
- lru_bothead = lru_bottail = NULL;
- lru_pintailhead = lru_pintailtail = NULL;
lru_midpoint = .9;
lru_max = 0;
}
//o->lru_in_lru = true;
assert(!o->lru);
o->lru = this;
-
- o->lru_set_pos( LRU_POS_TOP );
- o->lru_next = lru_tophead;
- o->lru_prev = NULL;
- if (lru_tophead) {
- lru_tophead->lru_prev = o;
- } else {
- lru_toptail = o;
- }
- lru_tophead = o;
- lru_ntop++;
+ lru_top.insert_head( o );
lru_num++;
lru_num_pinned += !o->lru_expireable;
lru_adjust();
//o->lru_in_lru = true;
assert(!o->lru);
o->lru = this;
-
- o->lru_set_pos( LRU_POS_BOT );
- o->lru_next = lru_bothead;
- o->lru_prev = NULL;
- if (lru_bothead) {
- lru_bothead->lru_prev = o;
- } else {
- lru_bottail = o;
- }
- lru_bothead = o;
- lru_nbot++;
+ lru_bot.insert_head(o);
lru_num++;
lru_num_pinned += !o->lru_expireable;
}
void lru_insert_bot(LRUObject *o) {
assert(!o->lru);
o->lru = this;
+ lru_bot.insert_tail(o);
+ lru_num++;
+ lru_num_pinned += !o->lru_expireable;
+ }
- o->lru_set_pos( LRU_POS_BOT );
- o->lru_next = NULL;
- o->lru_prev = lru_bottail;
- if (lru_bottail) {
- lru_bottail->lru_next = o;
- } else {
- lru_bothead = o;
- }
- lru_bottail = o;
- lru_nbot++;
+ // insert at bottom of lru
+ void lru_insert_pintail(LRUObject *o) {
+ assert(!o->lru);
+ o->lru = this;
+
+ assert(!o->lru_is_expireable());
+
+ lru_pintail.insert_head(o);
lru_num++;
lru_num_pinned += !o->lru_expireable;
}
if (!lru_max) return;
__uint32_t topwant = (__uint32_t)(lru_midpoint * (double)lru_max);
- while (lru_ntop > topwant && lru_toptail) {
+ while (0 && lru_top.get_length() > 0 &&
+ lru_top.get_length() > topwant) {
// remove from tail of top, stick at head of bot
// FIXME: this could be way more efficient by moving a whole chain of items.
- lru_insert_mid( lru_remove( lru_toptail) );
+
+ LRUObject *o = lru_top.get_tail();
+ lru_top.remove(o);
+ lru_bot.insert_head(o);
}
}
if (!o->lru) return o;
- if (o->lru_get_pos() == LRU_POS_TOP) {
- //cout << "removing " << o << " from top" << endl;
- // top
- if (o->lru_next)
- o->lru_next->lru_prev = o->lru_prev;
- else
- lru_toptail = o->lru_prev;
- if (o->lru_prev)
- o->lru_prev->lru_next = o->lru_next;
- else
- lru_tophead = o->lru_next;
- lru_ntop--;
- }
- else if (o->lru_get_pos() == LRU_POS_BOT) {
- //cout << "removing " << o << " from bot" << endl;
- // bot
- if (o->lru_next)
- o->lru_next->lru_prev = o->lru_prev;
- else
- lru_bottail = o->lru_prev;
- if (o->lru_prev)
- o->lru_prev->lru_next = o->lru_next;
- else
- lru_bothead = o->lru_next;
- lru_nbot--;
- }
- else {
- assert(o->lru_get_pos() == LRU_POS_PINTAIL);
- if (o->lru_next)
- o->lru_next->lru_prev = o->lru_prev;
- else
- lru_pintailtail = o->lru_prev;
- if (o->lru_prev)
- o->lru_prev->lru_next = o->lru_next;
- else
- lru_pintailhead = o->lru_next;
- lru_nbot--;
- }
+ if (o->lru_list == &lru_top)
+ lru_top.remove(o);
+ else if (o->lru_list == &lru_bot)
+ lru_bot.remove(o);
+ else if (o->lru_list == &lru_pintail)
+ lru_pintail.remove(o);
+ else
+ assert(0);
+
lru_num--;
lru_num_pinned -= !o->lru_expireable;
- o->lru_next = o->lru_prev = NULL;
- o->lru_set_pos(LRU_POS_NONE);
o->lru = 0;
return o;
}
// touch item -- move to midpoint (unless already higher)
bool lru_midtouch(LRUObject *o) {
- if (o->lru_get_pos() == LRU_POS_TOP) return false;
+ if (o->lru_list == &lru_top) return false;
lru_remove(o);
lru_insert_mid(o);
LRUObject *p;
// look through tail of bot
- while (lru_bottail) {
- p = lru_remove( lru_bottail );
+ while (lru_bot.get_length()) {
+ p = lru_bot.get_tail();
+
if (p->lru_expireable)
- return p; // yay.
-
- // pinned, move to pintail
- p->lru_next = lru_pintailhead;
- p->lru_prev = NULL;
- if (lru_pintailhead) {
- lru_pintailhead->lru_prev = p;
- } else {
- lru_pintailtail = p;
- }
- lru_pintailhead = p;
-
- p->lru_set_pos( LRU_POS_PINTAIL );
+ return lru_remove(p); // yay.
+
+ // move to pintail
+ lru_pintail.insert_head(p);
}
// ok, try head then
- p = lru_toptail;
- while (p) {
+ while (lru_top.get_length()) {
+ p = lru_top.get_tail();
if (p->lru_expireable)
return lru_remove( p );
- //cout << "p " << p << " no expireable" << endl;
- p = p->lru_prev;
+
+ // move to pintail
+ lru_pintail.insert_head(p);
}
// no luck!
void lru_status() {
- dout(10) << "lru: " << lru_num << " items, " << lru_ntop << " top, " << lru_nbot << " bot" << endl;
+ dout(10) << "lru: " << lru_num << " items, " << lru_top.get_length() << " top, " << lru_bot.get_length() << " bot, " << lru_pintail.get_length() << " pintail" << endl;
}
};
lru->lru_num_pinned--;
// move out of tail?
- if (lru_get_pos() == LRU_POS_PINTAIL) {
- lru->lru_remove(this);
- lru->lru_insert_bot(this);
+ if (lru_list == &lru->lru_pintail) {
+ lru->lru_pintail.remove(this);
+ lru->lru_bot.insert_tail(this);
}
}
}