]>
git.proxmox.com Git - ceph.git/blob - ceph/src/include/lru.h
e88cedc60b2dc0cfafa988d4d971d8ddc30b9344
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
22 #include "common/config.h"
28 LRUObject
*lru_next
, *lru_prev
;
31 class LRUList
*lru_list
;
35 lru_next
= lru_prev
= NULL
;
41 // pin/unpin item in cache
44 bool lru_is_expireable() const { return !lru_pinned
; }
53 LRUObject
*head
, *tail
;
62 uint32_t get_length() const { return len
; }
64 LRUObject
*get_head() {
67 LRUObject
*get_tail() {
77 void insert_head(LRUObject
*o
) {
89 void insert_tail(LRUObject
*o
) {
102 void remove(LRUObject
*o
) {
103 assert(o
->lru_list
== this);
105 o
->lru_next
->lru_prev
= o
->lru_prev
;
109 o
->lru_prev
->lru_next
= o
->lru_next
;
112 o
->lru_next
= o
->lru_prev
= NULL
;
123 LRUList lru_top
, lru_bot
, lru_pintail
;
124 uint32_t lru_num
, lru_num_pinned
;
125 uint32_t lru_max
; // max items
128 friend class LRUObject
;
129 //friend class MDCache; // hack
139 uint32_t lru_get_size() const { return lru_num
; }
140 uint32_t lru_get_top() const { return lru_top
.get_length(); }
141 uint32_t lru_get_bot() const{ return lru_bot
.get_length(); }
142 uint32_t lru_get_pintail() const { return lru_pintail
.get_length(); }
143 uint32_t lru_get_max() const { return lru_max
; }
144 uint32_t lru_get_num_pinned() const { return lru_num_pinned
; }
146 void lru_set_max(uint32_t m
) { lru_max
= m
; }
147 void lru_set_midpoint(float f
) { lru_midpoint
= f
; }
156 // insert at top of lru
157 void lru_insert_top(LRUObject
*o
) {
158 //assert(!o->lru_in_lru);
159 //o->lru_in_lru = true;
162 lru_top
.insert_head( o
);
164 if (o
->lru_pinned
) lru_num_pinned
++;
168 // insert at mid point in lru
169 void lru_insert_mid(LRUObject
*o
) {
170 //assert(!o->lru_in_lru);
171 //o->lru_in_lru = true;
174 lru_bot
.insert_head(o
);
176 if (o
->lru_pinned
) lru_num_pinned
++;
179 // insert at bottom of lru
180 void lru_insert_bot(LRUObject
*o
) {
183 lru_bot
.insert_tail(o
);
185 if (o
->lru_pinned
) lru_num_pinned
++;
189 // insert at bottom of lru
190 void lru_insert_pintail(LRUObject *o) {
194 assert(o->lru_pinned);
196 lru_pintail.insert_head(o);
198 lru_num_pinned += o->lru_pinned;
205 // adjust top/bot balance, as necessary
207 if (!lru_max
) return;
209 unsigned toplen
= lru_top
.get_length();
210 unsigned topwant
= (unsigned)(lru_midpoint
* ((double)lru_max
- lru_num_pinned
));
213 // remove from tail of top, stick at head of bot
214 // FIXME: this could be way more efficient by moving a whole chain of items.
216 LRUObject
*o
= lru_top
.get_tail();
218 lru_bot
.insert_head(o
);
225 LRUObject
*lru_remove(LRUObject
*o
) {
227 //assert(o->lru_in_lru);
228 //if (!o->lru_in_lru) return o; // might have expired and been removed that way.
229 if (!o
->lru
) return o
;
231 assert((o
->lru_list
== &lru_pintail
) ||
232 (o
->lru_list
== &lru_top
) ||
233 (o
->lru_list
== &lru_bot
));
234 o
->lru_list
->remove(o
);
237 if (o
->lru_pinned
) lru_num_pinned
--;
242 // touch item -- move to head of lru
243 bool lru_touch(LRUObject
*o
) {
249 // touch item -- move to midpoint (unless already higher)
250 bool lru_midtouch(LRUObject
*o
) {
251 if (o
->lru_list
== &lru_top
) return false;
258 // touch item -- move to bottom
259 bool lru_bottouch(LRUObject
*o
) {
265 void lru_touch_entire_pintail() {
266 // promote entire pintail to the top lru
267 while (lru_pintail
.get_length() > 0) {
268 LRUObject
*o
= lru_pintail
.get_head();
269 lru_pintail
.remove(o
);
270 lru_top
.insert_tail(o
);
275 // expire -- expire a single item
276 LRUObject
*lru_get_next_expire() {
279 // look through tail of bot
280 while (lru_bot
.get_length()) {
281 p
= lru_bot
.get_tail();
282 if (!p
->lru_pinned
) return p
;
286 lru_pintail
.insert_head(p
);
290 while (lru_top
.get_length()) {
291 p
= lru_top
.get_tail();
292 if (!p
->lru_pinned
) return p
;
296 lru_pintail
.insert_head(p
);
303 LRUObject
*lru_expire() {
304 LRUObject
*p
= lru_get_next_expire();
306 return lru_remove(p
);
312 //generic_dout(10) << "lru: " << lru_num << " items, " << lru_top.get_length() << " top, " << lru_bot.get_length() << " bot, " << lru_pintail.get_length() << " pintail" << dendl;
318 inline void LRUObject::lru_pin() {
319 if (lru
&& !lru_pinned
) {
320 lru
->lru_num_pinned
++;
326 inline void LRUObject::lru_unpin() {
327 if (lru
&& lru_pinned
) {
328 lru
->lru_num_pinned
--;
330 // move from pintail -> bot
331 if (lru_list
== &lru
->lru_pintail
) {
332 lru
->lru_pintail
.remove(this);
333 lru
->lru_bot
.insert_tail(this);