xref: /freebsd-src/usr.sbin/nscd/cacheplcs.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
106a99fe3SHajimu UMEMOTO /*-
206a99fe3SHajimu UMEMOTO  * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
306a99fe3SHajimu UMEMOTO  * All rights reserved.
406a99fe3SHajimu UMEMOTO  *
506a99fe3SHajimu UMEMOTO  * Redistribution and use in source and binary forms, with or without
606a99fe3SHajimu UMEMOTO  * modification, are permitted provided that the following conditions
706a99fe3SHajimu UMEMOTO  * are met:
806a99fe3SHajimu UMEMOTO  * 1. Redistributions of source code must retain the above copyright
906a99fe3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer.
1006a99fe3SHajimu UMEMOTO  * 2. Redistributions in binary form must reproduce the above copyright
1106a99fe3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer in the
1206a99fe3SHajimu UMEMOTO  *    documentation and/or other materials provided with the distribution.
1306a99fe3SHajimu UMEMOTO  *
1406a99fe3SHajimu UMEMOTO  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1506a99fe3SHajimu UMEMOTO  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1606a99fe3SHajimu UMEMOTO  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1706a99fe3SHajimu UMEMOTO  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1806a99fe3SHajimu UMEMOTO  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1906a99fe3SHajimu UMEMOTO  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2006a99fe3SHajimu UMEMOTO  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2106a99fe3SHajimu UMEMOTO  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2206a99fe3SHajimu UMEMOTO  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2306a99fe3SHajimu UMEMOTO  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2406a99fe3SHajimu UMEMOTO  * SUCH DAMAGE.
2506a99fe3SHajimu UMEMOTO  *
2606a99fe3SHajimu UMEMOTO  */
2706a99fe3SHajimu UMEMOTO 
2806a99fe3SHajimu UMEMOTO #include <sys/cdefs.h>
2928f805ceSDag-Erling Smørgrav #include <sys/time.h>
3028f805ceSDag-Erling Smørgrav 
3106a99fe3SHajimu UMEMOTO #include <assert.h>
3228f805ceSDag-Erling Smørgrav #include <stdlib.h>
3306a99fe3SHajimu UMEMOTO #include <string.h>
3428f805ceSDag-Erling Smørgrav 
3506a99fe3SHajimu UMEMOTO #include "cacheplcs.h"
3606a99fe3SHajimu UMEMOTO #include "debug.h"
3706a99fe3SHajimu UMEMOTO 
3806a99fe3SHajimu UMEMOTO static void cache_fifo_policy_update_item(struct cache_policy_ *,
3906a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
4006a99fe3SHajimu UMEMOTO static void cache_lfu_policy_add_item(struct cache_policy_ *,
4106a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
4206a99fe3SHajimu UMEMOTO static struct cache_policy_item_ * cache_lfu_policy_create_item(void);
4306a99fe3SHajimu UMEMOTO static void cache_lfu_policy_destroy_item(struct cache_policy_item_ *);
4406a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *cache_lfu_policy_get_first_item(
4506a99fe3SHajimu UMEMOTO 	struct cache_policy_ *);
4606a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *cache_lfu_policy_get_last_item(
4706a99fe3SHajimu UMEMOTO 	struct cache_policy_ *);
4806a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *cache_lfu_policy_get_next_item(
4906a99fe3SHajimu UMEMOTO 	struct cache_policy_ *, struct cache_policy_item_ *);
5006a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *cache_lfu_policy_get_prev_item(
5106a99fe3SHajimu UMEMOTO 	struct cache_policy_ *, struct cache_policy_item_ *);
5206a99fe3SHajimu UMEMOTO static void cache_lfu_policy_remove_item(struct cache_policy_ *,
5306a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
5406a99fe3SHajimu UMEMOTO static void cache_lfu_policy_update_item(struct cache_policy_ *,
5506a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
5606a99fe3SHajimu UMEMOTO static void cache_lru_policy_update_item(struct cache_policy_ *,
5706a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
5806a99fe3SHajimu UMEMOTO static void cache_queue_policy_add_item(struct cache_policy_ *,
5906a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
6034ecf97aSDag-Erling Smørgrav static struct cache_policy_item_ * cache_queue_policy_create_item(void);
6106a99fe3SHajimu UMEMOTO static void cache_queue_policy_destroy_item(struct cache_policy_item_ *);
6206a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *cache_queue_policy_get_first_item(
6306a99fe3SHajimu UMEMOTO 	struct cache_policy_ *);
6406a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *cache_queue_policy_get_last_item(
6506a99fe3SHajimu UMEMOTO 	struct cache_policy_ *);
6606a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *cache_queue_policy_get_next_item(
6706a99fe3SHajimu UMEMOTO 	struct cache_policy_ *, struct cache_policy_item_ *);
6806a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *cache_queue_policy_get_prev_item(
6906a99fe3SHajimu UMEMOTO 	struct cache_policy_ *, struct cache_policy_item_ *);
7006a99fe3SHajimu UMEMOTO static void cache_queue_policy_remove_item(struct cache_policy_ *,
7106a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
7206a99fe3SHajimu UMEMOTO static void destroy_cache_queue_policy(struct cache_queue_policy_ *);
7306a99fe3SHajimu UMEMOTO static struct cache_queue_policy_ *init_cache_queue_policy(void);
7406a99fe3SHajimu UMEMOTO 
7506a99fe3SHajimu UMEMOTO /*
7606a99fe3SHajimu UMEMOTO  * All cache_queue_policy_XXX functions below will be used to fill
7706a99fe3SHajimu UMEMOTO  * the cache_queue_policy structure. They implement the most functionality of
7806a99fe3SHajimu UMEMOTO  * LRU and FIFO policies. LRU and FIFO policies are actually the
7906a99fe3SHajimu UMEMOTO  * cache_queue_policy_ with cache_update_item function changed.
8006a99fe3SHajimu UMEMOTO  */
8106a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_queue_policy_create_item(void)8234ecf97aSDag-Erling Smørgrav cache_queue_policy_create_item(void)
8306a99fe3SHajimu UMEMOTO {
8406a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_item_ *retval;
8506a99fe3SHajimu UMEMOTO 
8606a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_queue_policy_create_item);
87*8eeaaffaSDag-Erling Smørgrav 	retval = calloc(1,
88*8eeaaffaSDag-Erling Smørgrav 		sizeof(*retval));
8906a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
9006a99fe3SHajimu UMEMOTO 
9106a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_queue_policy_create_item);
9206a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)retval);
9306a99fe3SHajimu UMEMOTO }
9406a99fe3SHajimu UMEMOTO 
9506a99fe3SHajimu UMEMOTO static void
cache_queue_policy_destroy_item(struct cache_policy_item_ * item)9606a99fe3SHajimu UMEMOTO cache_queue_policy_destroy_item(struct cache_policy_item_ *item)
9706a99fe3SHajimu UMEMOTO {
9806a99fe3SHajimu UMEMOTO 
9906a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_queue_policy_destroy_item);
10006a99fe3SHajimu UMEMOTO 	assert(item != NULL);
10106a99fe3SHajimu UMEMOTO 	free(item);
10206a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_queue_policy_destroy_item);
10306a99fe3SHajimu UMEMOTO }
10406a99fe3SHajimu UMEMOTO 
10506a99fe3SHajimu UMEMOTO static void
cache_queue_policy_add_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)10606a99fe3SHajimu UMEMOTO cache_queue_policy_add_item(struct cache_policy_ *policy,
10706a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
10806a99fe3SHajimu UMEMOTO {
10906a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_ *queue_policy;
11006a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_item_ *queue_item;
11106a99fe3SHajimu UMEMOTO 
11206a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_queue_policy_add_item);
11306a99fe3SHajimu UMEMOTO 	queue_policy = (struct cache_queue_policy_ *)policy;
11406a99fe3SHajimu UMEMOTO 	queue_item = (struct cache_queue_policy_item_ *)item;
11506a99fe3SHajimu UMEMOTO 	TAILQ_INSERT_TAIL(&queue_policy->head, queue_item, entries);
11606a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_queue_policy_add_item);
11706a99fe3SHajimu UMEMOTO }
11806a99fe3SHajimu UMEMOTO 
11906a99fe3SHajimu UMEMOTO static void
cache_queue_policy_remove_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)12006a99fe3SHajimu UMEMOTO cache_queue_policy_remove_item(struct cache_policy_ *policy,
12106a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
12206a99fe3SHajimu UMEMOTO {
12306a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_ *queue_policy;
12406a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_item_	*queue_item;
12506a99fe3SHajimu UMEMOTO 
12606a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_queue_policy_remove_item);
12706a99fe3SHajimu UMEMOTO 	queue_policy = (struct cache_queue_policy_ *)policy;
12806a99fe3SHajimu UMEMOTO 	queue_item = (struct cache_queue_policy_item_ *)item;
12906a99fe3SHajimu UMEMOTO 	TAILQ_REMOVE(&queue_policy->head, queue_item, entries);
13006a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_queue_policy_remove_item);
13106a99fe3SHajimu UMEMOTO }
13206a99fe3SHajimu UMEMOTO 
13306a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_queue_policy_get_first_item(struct cache_policy_ * policy)13406a99fe3SHajimu UMEMOTO cache_queue_policy_get_first_item(struct cache_policy_ *policy)
13506a99fe3SHajimu UMEMOTO {
13606a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_ *queue_policy;
13706a99fe3SHajimu UMEMOTO 
13806a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_queue_policy_get_first_item);
13906a99fe3SHajimu UMEMOTO 	queue_policy = (struct cache_queue_policy_ *)policy;
14006a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_queue_policy_get_first_item);
14106a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)TAILQ_FIRST(&queue_policy->head));
14206a99fe3SHajimu UMEMOTO }
14306a99fe3SHajimu UMEMOTO 
14406a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_queue_policy_get_last_item(struct cache_policy_ * policy)14506a99fe3SHajimu UMEMOTO cache_queue_policy_get_last_item(struct cache_policy_ *policy)
14606a99fe3SHajimu UMEMOTO {
14706a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_ *queue_policy;
14806a99fe3SHajimu UMEMOTO 
14906a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_queue_policy_get_last_item);
15006a99fe3SHajimu UMEMOTO 	queue_policy = (struct cache_queue_policy_ *)policy;
15106a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_queue_policy_get_last_item);
15206a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)TAILQ_LAST(&queue_policy->head,
15306a99fe3SHajimu UMEMOTO 		cache_queue_policy_head_));
15406a99fe3SHajimu UMEMOTO }
15506a99fe3SHajimu UMEMOTO 
15606a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_queue_policy_get_next_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)15706a99fe3SHajimu UMEMOTO cache_queue_policy_get_next_item(struct cache_policy_ *policy,
15806a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
15906a99fe3SHajimu UMEMOTO {
16006a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_item_	*queue_item;
16106a99fe3SHajimu UMEMOTO 
16206a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_queue_policy_get_next_item);
16306a99fe3SHajimu UMEMOTO 	queue_item = (struct cache_queue_policy_item_ *)item;
16406a99fe3SHajimu UMEMOTO 
16506a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_queue_policy_get_next_item);
16606a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)TAILQ_NEXT(queue_item, entries));
16706a99fe3SHajimu UMEMOTO }
16806a99fe3SHajimu UMEMOTO 
16906a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_queue_policy_get_prev_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)17006a99fe3SHajimu UMEMOTO cache_queue_policy_get_prev_item(struct cache_policy_ *policy,
17106a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
17206a99fe3SHajimu UMEMOTO {
17306a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_item_	*queue_item;
17406a99fe3SHajimu UMEMOTO 
17506a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_queue_policy_get_prev_item);
17606a99fe3SHajimu UMEMOTO 	queue_item = (struct cache_queue_policy_item_ *)item;
17706a99fe3SHajimu UMEMOTO 
17806a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_queue_policy_get_prev_item);
17906a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)TAILQ_PREV(queue_item,
18006a99fe3SHajimu UMEMOTO 		cache_queue_policy_head_, entries));
18106a99fe3SHajimu UMEMOTO }
18206a99fe3SHajimu UMEMOTO 
18306a99fe3SHajimu UMEMOTO /*
18406a99fe3SHajimu UMEMOTO  * Initializes cache_queue_policy_ by filling the structure with the functions
18506a99fe3SHajimu UMEMOTO  * pointers, defined above
18606a99fe3SHajimu UMEMOTO  */
18706a99fe3SHajimu UMEMOTO static struct cache_queue_policy_ *
init_cache_queue_policy(void)18806a99fe3SHajimu UMEMOTO init_cache_queue_policy(void)
18906a99fe3SHajimu UMEMOTO {
19006a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_	*retval;
19106a99fe3SHajimu UMEMOTO 
19206a99fe3SHajimu UMEMOTO 	TRACE_IN(init_cache_queue_policy);
193*8eeaaffaSDag-Erling Smørgrav 	retval = calloc(1,
194*8eeaaffaSDag-Erling Smørgrav 		sizeof(*retval));
19506a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
19606a99fe3SHajimu UMEMOTO 
19706a99fe3SHajimu UMEMOTO 	retval->parent_data.create_item_func = cache_queue_policy_create_item;
19806a99fe3SHajimu UMEMOTO 	retval->parent_data.destroy_item_func = cache_queue_policy_destroy_item;
19906a99fe3SHajimu UMEMOTO 
20006a99fe3SHajimu UMEMOTO 	retval->parent_data.add_item_func = cache_queue_policy_add_item;
20106a99fe3SHajimu UMEMOTO 	retval->parent_data.remove_item_func = cache_queue_policy_remove_item;
20206a99fe3SHajimu UMEMOTO 
20306a99fe3SHajimu UMEMOTO 	retval->parent_data.get_first_item_func =
20406a99fe3SHajimu UMEMOTO 		cache_queue_policy_get_first_item;
20506a99fe3SHajimu UMEMOTO 	retval->parent_data.get_last_item_func =
20606a99fe3SHajimu UMEMOTO 		cache_queue_policy_get_last_item;
20706a99fe3SHajimu UMEMOTO 	retval->parent_data.get_next_item_func =
20806a99fe3SHajimu UMEMOTO 		cache_queue_policy_get_next_item;
20906a99fe3SHajimu UMEMOTO 	retval->parent_data.get_prev_item_func =
21006a99fe3SHajimu UMEMOTO 		cache_queue_policy_get_prev_item;
21106a99fe3SHajimu UMEMOTO 
21206a99fe3SHajimu UMEMOTO 	TAILQ_INIT(&retval->head);
21306a99fe3SHajimu UMEMOTO 	TRACE_OUT(init_cache_queue_policy);
21406a99fe3SHajimu UMEMOTO 	return (retval);
21506a99fe3SHajimu UMEMOTO }
21606a99fe3SHajimu UMEMOTO 
21706a99fe3SHajimu UMEMOTO static void
destroy_cache_queue_policy(struct cache_queue_policy_ * queue_policy)21806a99fe3SHajimu UMEMOTO destroy_cache_queue_policy(struct cache_queue_policy_ *queue_policy)
21906a99fe3SHajimu UMEMOTO {
22006a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_item_	*queue_item;
22106a99fe3SHajimu UMEMOTO 
22206a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_cache_queue_policy);
22306a99fe3SHajimu UMEMOTO 	while (!TAILQ_EMPTY(&queue_policy->head)) {
22406a99fe3SHajimu UMEMOTO 		queue_item = TAILQ_FIRST(&queue_policy->head);
22506a99fe3SHajimu UMEMOTO 		TAILQ_REMOVE(&queue_policy->head, queue_item, entries);
22606a99fe3SHajimu UMEMOTO 		cache_queue_policy_destroy_item(
22706a99fe3SHajimu UMEMOTO 			(struct cache_policy_item_ *)queue_item);
22806a99fe3SHajimu UMEMOTO 	}
22906a99fe3SHajimu UMEMOTO 	free(queue_policy);
23006a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_cache_queue_policy);
23106a99fe3SHajimu UMEMOTO }
23206a99fe3SHajimu UMEMOTO 
23306a99fe3SHajimu UMEMOTO /*
23406a99fe3SHajimu UMEMOTO  * Makes cache_queue_policy_ behave like FIFO policy - we don't do anything,
23506a99fe3SHajimu UMEMOTO  * when the cache element is updated. So it always stays in its initial
23606a99fe3SHajimu UMEMOTO  * position in the queue - that is exactly the FIFO functionality.
23706a99fe3SHajimu UMEMOTO  */
23806a99fe3SHajimu UMEMOTO static void
cache_fifo_policy_update_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)23906a99fe3SHajimu UMEMOTO cache_fifo_policy_update_item(struct cache_policy_ *policy,
24006a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
24106a99fe3SHajimu UMEMOTO {
24206a99fe3SHajimu UMEMOTO 
24306a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_fifo_policy_update_item);
24406a99fe3SHajimu UMEMOTO 	/* policy and item arguments are ignored */
24506a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_fifo_policy_update_item);
24606a99fe3SHajimu UMEMOTO }
24706a99fe3SHajimu UMEMOTO 
24806a99fe3SHajimu UMEMOTO struct cache_policy_ *
init_cache_fifo_policy(void)24934ecf97aSDag-Erling Smørgrav init_cache_fifo_policy(void)
25006a99fe3SHajimu UMEMOTO {
25106a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_ *retval;
25206a99fe3SHajimu UMEMOTO 
25306a99fe3SHajimu UMEMOTO 	TRACE_IN(init_cache_fifo_policy);
25406a99fe3SHajimu UMEMOTO 	retval = init_cache_queue_policy();
25506a99fe3SHajimu UMEMOTO 	retval->parent_data.update_item_func = cache_fifo_policy_update_item;
25606a99fe3SHajimu UMEMOTO 
25706a99fe3SHajimu UMEMOTO 	TRACE_OUT(init_cache_fifo_policy);
25806a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_ *)retval);
25906a99fe3SHajimu UMEMOTO }
26006a99fe3SHajimu UMEMOTO 
26106a99fe3SHajimu UMEMOTO void
destroy_cache_fifo_policy(struct cache_policy_ * policy)26206a99fe3SHajimu UMEMOTO destroy_cache_fifo_policy(struct cache_policy_ *policy)
26306a99fe3SHajimu UMEMOTO {
26406a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_	*queue_policy;
26506a99fe3SHajimu UMEMOTO 
26606a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_cache_fifo_policy);
26706a99fe3SHajimu UMEMOTO 	queue_policy = (struct cache_queue_policy_ *)policy;
26806a99fe3SHajimu UMEMOTO 	destroy_cache_queue_policy(queue_policy);
26906a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_cache_fifo_policy);
27006a99fe3SHajimu UMEMOTO }
27106a99fe3SHajimu UMEMOTO 
27206a99fe3SHajimu UMEMOTO /*
27306a99fe3SHajimu UMEMOTO  * Makes cache_queue_policy_ behave like LRU policy. On each update, cache
27406a99fe3SHajimu UMEMOTO  * element is moved to the end of the queue - so it would be deleted in last
27506a99fe3SHajimu UMEMOTO  * turn. That is exactly the LRU policy functionality.
27606a99fe3SHajimu UMEMOTO  */
27706a99fe3SHajimu UMEMOTO static void
cache_lru_policy_update_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)27806a99fe3SHajimu UMEMOTO cache_lru_policy_update_item(struct cache_policy_ *policy,
27906a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
28006a99fe3SHajimu UMEMOTO {
28106a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_ *queue_policy;
28206a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_item_ *queue_item;
28306a99fe3SHajimu UMEMOTO 
28406a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lru_policy_update_item);
28506a99fe3SHajimu UMEMOTO 	queue_policy = (struct cache_queue_policy_ *)policy;
28606a99fe3SHajimu UMEMOTO 	queue_item = (struct cache_queue_policy_item_ *)item;
28706a99fe3SHajimu UMEMOTO 
28806a99fe3SHajimu UMEMOTO 	TAILQ_REMOVE(&queue_policy->head, queue_item, entries);
28906a99fe3SHajimu UMEMOTO 	TAILQ_INSERT_TAIL(&queue_policy->head, queue_item, entries);
29006a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lru_policy_update_item);
29106a99fe3SHajimu UMEMOTO }
29206a99fe3SHajimu UMEMOTO 
29306a99fe3SHajimu UMEMOTO struct cache_policy_ *
init_cache_lru_policy(void)29434ecf97aSDag-Erling Smørgrav init_cache_lru_policy(void)
29506a99fe3SHajimu UMEMOTO {
29606a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_ *retval;
29706a99fe3SHajimu UMEMOTO 
29806a99fe3SHajimu UMEMOTO 	TRACE_IN(init_cache_lru_policy);
29906a99fe3SHajimu UMEMOTO 	retval = init_cache_queue_policy();
30006a99fe3SHajimu UMEMOTO 	retval->parent_data.update_item_func = cache_lru_policy_update_item;
30106a99fe3SHajimu UMEMOTO 
30206a99fe3SHajimu UMEMOTO 	TRACE_OUT(init_cache_lru_policy);
30306a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_ *)retval);
30406a99fe3SHajimu UMEMOTO }
30506a99fe3SHajimu UMEMOTO 
30606a99fe3SHajimu UMEMOTO void
destroy_cache_lru_policy(struct cache_policy_ * policy)30706a99fe3SHajimu UMEMOTO destroy_cache_lru_policy(struct cache_policy_ *policy)
30806a99fe3SHajimu UMEMOTO {
30906a99fe3SHajimu UMEMOTO 	struct cache_queue_policy_	*queue_policy;
31006a99fe3SHajimu UMEMOTO 
31106a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_cache_lru_policy);
31206a99fe3SHajimu UMEMOTO 	queue_policy = (struct cache_queue_policy_ *)policy;
31306a99fe3SHajimu UMEMOTO 	destroy_cache_queue_policy(queue_policy);
31406a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_cache_lru_policy);
31506a99fe3SHajimu UMEMOTO }
31606a99fe3SHajimu UMEMOTO 
31706a99fe3SHajimu UMEMOTO /*
31806a99fe3SHajimu UMEMOTO  * LFU (least frequently used) policy implementation differs much from the
31906a99fe3SHajimu UMEMOTO  * LRU and FIFO (both based on cache_queue_policy_). Almost all cache_policy_
32006a99fe3SHajimu UMEMOTO  * functions are implemented specifically for this policy. The idea of this
32106a99fe3SHajimu UMEMOTO  * policy is to represent frequency (real number) as the integer number and
32206a99fe3SHajimu UMEMOTO  * use it as the index in the array. Each array's element is
32306a99fe3SHajimu UMEMOTO  * the list of elements. For example, if we have the 100-elements
32406a99fe3SHajimu UMEMOTO  * array for this policy, the elements with frequency 0.1 (calls per-second)
32506a99fe3SHajimu UMEMOTO  * would be in 10th element of the array.
32606a99fe3SHajimu UMEMOTO  */
32706a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_lfu_policy_create_item(void)32806a99fe3SHajimu UMEMOTO cache_lfu_policy_create_item(void)
32906a99fe3SHajimu UMEMOTO {
33006a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *retval;
33106a99fe3SHajimu UMEMOTO 
33206a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_create_item);
333*8eeaaffaSDag-Erling Smørgrav 	retval = calloc(1,
334*8eeaaffaSDag-Erling Smørgrav 		sizeof(*retval));
33506a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
33606a99fe3SHajimu UMEMOTO 
33706a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_create_item);
33806a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)retval);
33906a99fe3SHajimu UMEMOTO }
34006a99fe3SHajimu UMEMOTO 
34106a99fe3SHajimu UMEMOTO static void
cache_lfu_policy_destroy_item(struct cache_policy_item_ * item)34206a99fe3SHajimu UMEMOTO cache_lfu_policy_destroy_item(struct cache_policy_item_ *item)
34306a99fe3SHajimu UMEMOTO {
34406a99fe3SHajimu UMEMOTO 
34506a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_destroy_item);
34606a99fe3SHajimu UMEMOTO 	assert(item != NULL);
34706a99fe3SHajimu UMEMOTO 	free(item);
34806a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_destroy_item);
34906a99fe3SHajimu UMEMOTO }
35006a99fe3SHajimu UMEMOTO 
35106a99fe3SHajimu UMEMOTO /*
35206a99fe3SHajimu UMEMOTO  * When placed in the LFU policy queue for the first time, the maximum
35306a99fe3SHajimu UMEMOTO  * frequency is assigned to the element
35406a99fe3SHajimu UMEMOTO  */
35506a99fe3SHajimu UMEMOTO static void
cache_lfu_policy_add_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)35606a99fe3SHajimu UMEMOTO cache_lfu_policy_add_item(struct cache_policy_ *policy,
35706a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
35806a99fe3SHajimu UMEMOTO {
35906a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *lfu_policy;
36006a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *lfu_item;
36106a99fe3SHajimu UMEMOTO 
36206a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_add_item);
36306a99fe3SHajimu UMEMOTO 	lfu_policy = (struct cache_lfu_policy_ *)policy;
36406a99fe3SHajimu UMEMOTO 	lfu_item = (struct cache_lfu_policy_item_ *)item;
36506a99fe3SHajimu UMEMOTO 
36606a99fe3SHajimu UMEMOTO 	lfu_item->frequency = CACHELIB_MAX_FREQUENCY - 1;
36706a99fe3SHajimu UMEMOTO 	TAILQ_INSERT_HEAD(&(lfu_policy->groups[CACHELIB_MAX_FREQUENCY - 1]),
36806a99fe3SHajimu UMEMOTO 		lfu_item, entries);
36906a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_add_item);
37006a99fe3SHajimu UMEMOTO }
37106a99fe3SHajimu UMEMOTO 
37206a99fe3SHajimu UMEMOTO /*
37306a99fe3SHajimu UMEMOTO  * On each update the frequency of the element is recalculated and, if it
37406a99fe3SHajimu UMEMOTO  * changed, the element would be moved to the another place in the array.
37506a99fe3SHajimu UMEMOTO  */
37606a99fe3SHajimu UMEMOTO static void
cache_lfu_policy_update_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)37706a99fe3SHajimu UMEMOTO cache_lfu_policy_update_item(struct cache_policy_ *policy,
37806a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
37906a99fe3SHajimu UMEMOTO {
38006a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *lfu_policy;
38106a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *lfu_item;
38206a99fe3SHajimu UMEMOTO 	int index;
38306a99fe3SHajimu UMEMOTO 
38406a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_update_item);
38506a99fe3SHajimu UMEMOTO 	lfu_policy = (struct cache_lfu_policy_ *)policy;
38606a99fe3SHajimu UMEMOTO 	lfu_item = (struct cache_lfu_policy_item_ *)item;
38706a99fe3SHajimu UMEMOTO 
38806a99fe3SHajimu UMEMOTO 	/*
38906a99fe3SHajimu UMEMOTO 	 * We calculate the square of the request_count to avoid grouping of
39006a99fe3SHajimu UMEMOTO 	 * all elements at the start of the array (for example, if array size is
39106a99fe3SHajimu UMEMOTO 	 * 100 and most of its elements has frequency below the 0.01, they
39206a99fe3SHajimu UMEMOTO 	 * all would be grouped in the first array's position). Other
39306a99fe3SHajimu UMEMOTO 	 * techniques should be used here later to ensure, that elements are
39406a99fe3SHajimu UMEMOTO 	 * equally distributed  in the array and not grouped in its beginning.
39506a99fe3SHajimu UMEMOTO 	 */
39606a99fe3SHajimu UMEMOTO 	if (lfu_item->parent_data.last_request_time.tv_sec !=
39706a99fe3SHajimu UMEMOTO 		lfu_item->parent_data.creation_time.tv_sec) {
39806a99fe3SHajimu UMEMOTO 		index = ((double)lfu_item->parent_data.request_count *
39906a99fe3SHajimu UMEMOTO 			(double)lfu_item->parent_data.request_count /
40006a99fe3SHajimu UMEMOTO 			(lfu_item->parent_data.last_request_time.tv_sec -
40106a99fe3SHajimu UMEMOTO 			    lfu_item->parent_data.creation_time.tv_sec + 1)) *
40206a99fe3SHajimu UMEMOTO 			    CACHELIB_MAX_FREQUENCY;
40306a99fe3SHajimu UMEMOTO 		if (index >= CACHELIB_MAX_FREQUENCY)
40406a99fe3SHajimu UMEMOTO 			index = CACHELIB_MAX_FREQUENCY - 1;
40506a99fe3SHajimu UMEMOTO 	} else
40606a99fe3SHajimu UMEMOTO 		index = CACHELIB_MAX_FREQUENCY - 1;
40706a99fe3SHajimu UMEMOTO 
40806a99fe3SHajimu UMEMOTO 	TAILQ_REMOVE(&(lfu_policy->groups[lfu_item->frequency]), lfu_item,
40906a99fe3SHajimu UMEMOTO 		entries);
41006a99fe3SHajimu UMEMOTO 	lfu_item->frequency = index;
41106a99fe3SHajimu UMEMOTO 	TAILQ_INSERT_HEAD(&(lfu_policy->groups[index]), lfu_item, entries);
41206a99fe3SHajimu UMEMOTO 
41306a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_update_item);
41406a99fe3SHajimu UMEMOTO }
41506a99fe3SHajimu UMEMOTO 
41606a99fe3SHajimu UMEMOTO static void
cache_lfu_policy_remove_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)41706a99fe3SHajimu UMEMOTO cache_lfu_policy_remove_item(struct cache_policy_ *policy,
41806a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
41906a99fe3SHajimu UMEMOTO {
42006a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *lfu_policy;
42106a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *lfu_item;
42206a99fe3SHajimu UMEMOTO 
42306a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_remove_item);
42406a99fe3SHajimu UMEMOTO 	lfu_policy = (struct cache_lfu_policy_ *)policy;
42506a99fe3SHajimu UMEMOTO 	lfu_item = (struct cache_lfu_policy_item_ *)item;
42606a99fe3SHajimu UMEMOTO 
42706a99fe3SHajimu UMEMOTO 	TAILQ_REMOVE(&(lfu_policy->groups[lfu_item->frequency]), lfu_item,
42806a99fe3SHajimu UMEMOTO 		entries);
42906a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_remove_item);
43006a99fe3SHajimu UMEMOTO }
43106a99fe3SHajimu UMEMOTO 
43206a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_lfu_policy_get_first_item(struct cache_policy_ * policy)43306a99fe3SHajimu UMEMOTO cache_lfu_policy_get_first_item(struct cache_policy_ *policy)
43406a99fe3SHajimu UMEMOTO {
43506a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *lfu_policy;
43606a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *lfu_item;
43706a99fe3SHajimu UMEMOTO 	int i;
43806a99fe3SHajimu UMEMOTO 
43906a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_get_first_item);
44006a99fe3SHajimu UMEMOTO 	lfu_item = NULL;
44106a99fe3SHajimu UMEMOTO 	lfu_policy = (struct cache_lfu_policy_ *)policy;
44206a99fe3SHajimu UMEMOTO 	for (i = 0; i < CACHELIB_MAX_FREQUENCY; ++i)
44306a99fe3SHajimu UMEMOTO 		if (!TAILQ_EMPTY(&(lfu_policy->groups[i]))) {
44406a99fe3SHajimu UMEMOTO 			lfu_item = TAILQ_FIRST(&(lfu_policy->groups[i]));
44506a99fe3SHajimu UMEMOTO 			break;
44606a99fe3SHajimu UMEMOTO 		}
44706a99fe3SHajimu UMEMOTO 
44806a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_get_first_item);
44906a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)lfu_item);
45006a99fe3SHajimu UMEMOTO }
45106a99fe3SHajimu UMEMOTO 
45206a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_lfu_policy_get_last_item(struct cache_policy_ * policy)45306a99fe3SHajimu UMEMOTO cache_lfu_policy_get_last_item(struct cache_policy_ *policy)
45406a99fe3SHajimu UMEMOTO {
45506a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *lfu_policy;
45606a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *lfu_item;
45706a99fe3SHajimu UMEMOTO 	int i;
45806a99fe3SHajimu UMEMOTO 
45906a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_get_last_item);
46006a99fe3SHajimu UMEMOTO 	lfu_item = NULL;
46106a99fe3SHajimu UMEMOTO 	lfu_policy = (struct cache_lfu_policy_ *)policy;
46206a99fe3SHajimu UMEMOTO 	for (i = CACHELIB_MAX_FREQUENCY - 1; i >= 0; --i)
46306a99fe3SHajimu UMEMOTO 		if (!TAILQ_EMPTY(&(lfu_policy->groups[i]))) {
46406a99fe3SHajimu UMEMOTO 			lfu_item = TAILQ_LAST(&(lfu_policy->groups[i]),
46506a99fe3SHajimu UMEMOTO 				cache_lfu_policy_group_);
46606a99fe3SHajimu UMEMOTO 			break;
46706a99fe3SHajimu UMEMOTO 		}
46806a99fe3SHajimu UMEMOTO 
46906a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_get_last_item);
47006a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)lfu_item);
47106a99fe3SHajimu UMEMOTO }
47206a99fe3SHajimu UMEMOTO 
47306a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_lfu_policy_get_next_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)47406a99fe3SHajimu UMEMOTO cache_lfu_policy_get_next_item(struct cache_policy_ *policy,
47506a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
47606a99fe3SHajimu UMEMOTO {
47706a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *lfu_policy;
47806a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *lfu_item;
47906a99fe3SHajimu UMEMOTO 	int i;
48006a99fe3SHajimu UMEMOTO 
48106a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_get_next_item);
48206a99fe3SHajimu UMEMOTO 	lfu_policy = (struct cache_lfu_policy_ *)policy;
48306a99fe3SHajimu UMEMOTO 	lfu_item = TAILQ_NEXT((struct cache_lfu_policy_item_ *)item, entries);
48406a99fe3SHajimu UMEMOTO 	if (lfu_item == NULL)
48506a99fe3SHajimu UMEMOTO 	{
48606a99fe3SHajimu UMEMOTO 		for (i = ((struct cache_lfu_policy_item_ *)item)->frequency + 1;
48706a99fe3SHajimu UMEMOTO 			i < CACHELIB_MAX_FREQUENCY; ++i) {
48806a99fe3SHajimu UMEMOTO 			if (!TAILQ_EMPTY(&(lfu_policy->groups[i]))) {
48906a99fe3SHajimu UMEMOTO 			    lfu_item = TAILQ_FIRST(&(lfu_policy->groups[i]));
49006a99fe3SHajimu UMEMOTO 			    break;
49106a99fe3SHajimu UMEMOTO 			}
49206a99fe3SHajimu UMEMOTO 		}
49306a99fe3SHajimu UMEMOTO 	}
49406a99fe3SHajimu UMEMOTO 
49506a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_get_next_item);
49606a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)lfu_item);
49706a99fe3SHajimu UMEMOTO }
49806a99fe3SHajimu UMEMOTO 
49906a99fe3SHajimu UMEMOTO static struct cache_policy_item_ *
cache_lfu_policy_get_prev_item(struct cache_policy_ * policy,struct cache_policy_item_ * item)50006a99fe3SHajimu UMEMOTO cache_lfu_policy_get_prev_item(struct cache_policy_ *policy,
50106a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
50206a99fe3SHajimu UMEMOTO {
50306a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *lfu_policy;
50406a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *lfu_item;
50506a99fe3SHajimu UMEMOTO 	int i;
50606a99fe3SHajimu UMEMOTO 
50706a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_lfu_policy_get_prev_item);
50806a99fe3SHajimu UMEMOTO 	lfu_policy = (struct cache_lfu_policy_ *)policy;
50906a99fe3SHajimu UMEMOTO 	lfu_item = TAILQ_PREV((struct cache_lfu_policy_item_ *)item,
51006a99fe3SHajimu UMEMOTO 		cache_lfu_policy_group_, entries);
51106a99fe3SHajimu UMEMOTO 	if (lfu_item == NULL)
51206a99fe3SHajimu UMEMOTO 	{
51306a99fe3SHajimu UMEMOTO 		for (i = ((struct cache_lfu_policy_item_ *)item)->frequency - 1;
51406a99fe3SHajimu UMEMOTO 			i >= 0; --i)
51506a99fe3SHajimu UMEMOTO 			if (!TAILQ_EMPTY(&(lfu_policy->groups[i]))) {
51606a99fe3SHajimu UMEMOTO 				lfu_item = TAILQ_LAST(&(lfu_policy->groups[i]),
51706a99fe3SHajimu UMEMOTO 					cache_lfu_policy_group_);
51806a99fe3SHajimu UMEMOTO 				break;
51906a99fe3SHajimu UMEMOTO 		}
52006a99fe3SHajimu UMEMOTO 	}
52106a99fe3SHajimu UMEMOTO 
52206a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_lfu_policy_get_prev_item);
52306a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_item_ *)lfu_item);
52406a99fe3SHajimu UMEMOTO }
52506a99fe3SHajimu UMEMOTO 
52606a99fe3SHajimu UMEMOTO /*
52706a99fe3SHajimu UMEMOTO  * Initializes the cache_policy_ structure by filling it with appropriate
52806a99fe3SHajimu UMEMOTO  * functions pointers
52906a99fe3SHajimu UMEMOTO  */
53006a99fe3SHajimu UMEMOTO struct cache_policy_ *
init_cache_lfu_policy(void)53134ecf97aSDag-Erling Smørgrav init_cache_lfu_policy(void)
53206a99fe3SHajimu UMEMOTO {
53306a99fe3SHajimu UMEMOTO 	int i;
53406a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *retval;
53506a99fe3SHajimu UMEMOTO 
53606a99fe3SHajimu UMEMOTO 	TRACE_IN(init_cache_lfu_policy);
537*8eeaaffaSDag-Erling Smørgrav 	retval = calloc(1,
538*8eeaaffaSDag-Erling Smørgrav 		sizeof(*retval));
53906a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
54006a99fe3SHajimu UMEMOTO 
54106a99fe3SHajimu UMEMOTO 	retval->parent_data.create_item_func = cache_lfu_policy_create_item;
54206a99fe3SHajimu UMEMOTO 	retval->parent_data.destroy_item_func = cache_lfu_policy_destroy_item;
54306a99fe3SHajimu UMEMOTO 
54406a99fe3SHajimu UMEMOTO 	retval->parent_data.add_item_func = cache_lfu_policy_add_item;
54506a99fe3SHajimu UMEMOTO 	retval->parent_data.update_item_func = cache_lfu_policy_update_item;
54606a99fe3SHajimu UMEMOTO 	retval->parent_data.remove_item_func = cache_lfu_policy_remove_item;
54706a99fe3SHajimu UMEMOTO 
54806a99fe3SHajimu UMEMOTO 	retval->parent_data.get_first_item_func =
54906a99fe3SHajimu UMEMOTO 		cache_lfu_policy_get_first_item;
55006a99fe3SHajimu UMEMOTO 	retval->parent_data.get_last_item_func =
55106a99fe3SHajimu UMEMOTO 		cache_lfu_policy_get_last_item;
55206a99fe3SHajimu UMEMOTO 	retval->parent_data.get_next_item_func =
55306a99fe3SHajimu UMEMOTO 		cache_lfu_policy_get_next_item;
55406a99fe3SHajimu UMEMOTO 	retval->parent_data.get_prev_item_func =
55506a99fe3SHajimu UMEMOTO 		cache_lfu_policy_get_prev_item;
55606a99fe3SHajimu UMEMOTO 
55706a99fe3SHajimu UMEMOTO 	for (i = 0; i < CACHELIB_MAX_FREQUENCY; ++i)
55806a99fe3SHajimu UMEMOTO 		TAILQ_INIT(&(retval->groups[i]));
55906a99fe3SHajimu UMEMOTO 
56006a99fe3SHajimu UMEMOTO 	TRACE_OUT(init_cache_lfu_policy);
56106a99fe3SHajimu UMEMOTO 	return ((struct cache_policy_ *)retval);
56206a99fe3SHajimu UMEMOTO }
56306a99fe3SHajimu UMEMOTO 
56406a99fe3SHajimu UMEMOTO void
destroy_cache_lfu_policy(struct cache_policy_ * policy)56506a99fe3SHajimu UMEMOTO destroy_cache_lfu_policy(struct cache_policy_ *policy)
56606a99fe3SHajimu UMEMOTO {
56706a99fe3SHajimu UMEMOTO 	int i;
56806a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_ *lfu_policy;
56906a99fe3SHajimu UMEMOTO 	struct cache_lfu_policy_item_ *lfu_item;
57006a99fe3SHajimu UMEMOTO 
57106a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_cache_lfu_policy);
57206a99fe3SHajimu UMEMOTO 	lfu_policy = (struct cache_lfu_policy_ *)policy;
57306a99fe3SHajimu UMEMOTO 	for (i = 0; i < CACHELIB_MAX_FREQUENCY; ++i) {
57406a99fe3SHajimu UMEMOTO 		while (!TAILQ_EMPTY(&(lfu_policy->groups[i]))) {
57506a99fe3SHajimu UMEMOTO 			lfu_item = TAILQ_FIRST(&(lfu_policy->groups[i]));
57606a99fe3SHajimu UMEMOTO 			TAILQ_REMOVE(&(lfu_policy->groups[i]), lfu_item,
57706a99fe3SHajimu UMEMOTO 				entries);
57806a99fe3SHajimu UMEMOTO 			cache_lfu_policy_destroy_item(
57906a99fe3SHajimu UMEMOTO 				(struct cache_policy_item_ *)lfu_item);
58006a99fe3SHajimu UMEMOTO 		}
58106a99fe3SHajimu UMEMOTO 	}
58206a99fe3SHajimu UMEMOTO 	free(policy);
58306a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_cache_lfu_policy);
58406a99fe3SHajimu UMEMOTO }
585