xref: /freebsd-src/usr.sbin/nscd/cachelib.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>
2906a99fe3SHajimu UMEMOTO #include <sys/time.h>
30a5a5d924SDag-Erling Smørgrav 
3106a99fe3SHajimu UMEMOTO #include <assert.h>
3206a99fe3SHajimu UMEMOTO #include <stdlib.h>
3306a99fe3SHajimu UMEMOTO #include <string.h>
34a5a5d924SDag-Erling Smørgrav 
3506a99fe3SHajimu UMEMOTO #include "cachelib.h"
3606a99fe3SHajimu UMEMOTO #include "debug.h"
3706a99fe3SHajimu UMEMOTO 
3806a99fe3SHajimu UMEMOTO #define INITIAL_ENTRIES_CAPACITY 32
3906a99fe3SHajimu UMEMOTO #define ENTRIES_CAPACITY_STEP 32
4006a99fe3SHajimu UMEMOTO 
4106a99fe3SHajimu UMEMOTO #define STRING_SIMPLE_HASH_BODY(in_var, var, a, M)		\
4206a99fe3SHajimu UMEMOTO 	for ((var) = 0; *(in_var) != '\0'; ++(in_var))		\
4306a99fe3SHajimu UMEMOTO 		(var) = ((a)*(var) + *(in_var)) % (M)
4406a99fe3SHajimu UMEMOTO 
4506a99fe3SHajimu UMEMOTO #define STRING_SIMPLE_MP2_HASH_BODY(in_var, var, a, M)		\
4606a99fe3SHajimu UMEMOTO 	for ((var) = 0; *(in_var) != 0; ++(in_var))		\
4706a99fe3SHajimu UMEMOTO 		(var) = ((a)*(var) + *(in_var)) & (M - 1)
4806a99fe3SHajimu UMEMOTO 
4906a99fe3SHajimu UMEMOTO static int cache_elemsize_common_continue_func(struct cache_common_entry_ *,
5006a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
5106a99fe3SHajimu UMEMOTO static int cache_lifetime_common_continue_func(struct cache_common_entry_ *,
5206a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *);
5306a99fe3SHajimu UMEMOTO static void clear_cache_entry(struct cache_entry_ *);
5406a99fe3SHajimu UMEMOTO static void destroy_cache_entry(struct cache_entry_ *);
5506a99fe3SHajimu UMEMOTO static void destroy_cache_mp_read_session(struct cache_mp_read_session_ *);
5606a99fe3SHajimu UMEMOTO static void destroy_cache_mp_write_session(struct cache_mp_write_session_ *);
5706a99fe3SHajimu UMEMOTO static int entries_bsearch_cmp_func(const void *, const void *);
5806a99fe3SHajimu UMEMOTO static int entries_qsort_cmp_func(const void *, const void *);
5906a99fe3SHajimu UMEMOTO static struct cache_entry_ ** find_cache_entry_p(struct cache_ *,
6006a99fe3SHajimu UMEMOTO 	const char *);
6106a99fe3SHajimu UMEMOTO static void flush_cache_entry(struct cache_entry_ *);
6206a99fe3SHajimu UMEMOTO static void flush_cache_policy(struct cache_common_entry_ *,
6306a99fe3SHajimu UMEMOTO 	struct cache_policy_ *, struct cache_policy_ *,
6406a99fe3SHajimu UMEMOTO 		int (*)(struct cache_common_entry_ *,
6506a99fe3SHajimu UMEMOTO 		struct cache_policy_item_ *));
6606a99fe3SHajimu UMEMOTO static int ht_items_cmp_func(const void *, const void *);
6706a99fe3SHajimu UMEMOTO static int ht_items_fixed_size_left_cmp_func(const void *, const void *);
6806a99fe3SHajimu UMEMOTO static hashtable_index_t ht_item_hash_func(const void *, size_t);
6906a99fe3SHajimu UMEMOTO 
7006a99fe3SHajimu UMEMOTO /*
7106a99fe3SHajimu UMEMOTO  * Hashing and comparing routines, that are used with the hash tables
7206a99fe3SHajimu UMEMOTO  */
7306a99fe3SHajimu UMEMOTO static int
ht_items_cmp_func(const void * p1,const void * p2)7406a99fe3SHajimu UMEMOTO ht_items_cmp_func(const void *p1, const void *p2)
7506a99fe3SHajimu UMEMOTO {
7606a99fe3SHajimu UMEMOTO     	struct cache_ht_item_data_ *hp1, *hp2;
7706a99fe3SHajimu UMEMOTO 	size_t min_size;
7806a99fe3SHajimu UMEMOTO 	int result;
7906a99fe3SHajimu UMEMOTO 
8006a99fe3SHajimu UMEMOTO 	hp1 = (struct cache_ht_item_data_ *)p1;
8106a99fe3SHajimu UMEMOTO 	hp2 = (struct cache_ht_item_data_ *)p2;
8206a99fe3SHajimu UMEMOTO 
8306a99fe3SHajimu UMEMOTO 	assert(hp1->key != NULL);
8406a99fe3SHajimu UMEMOTO 	assert(hp2->key != NULL);
8506a99fe3SHajimu UMEMOTO 
8606a99fe3SHajimu UMEMOTO 	if (hp1->key_size != hp2->key_size) {
8706a99fe3SHajimu UMEMOTO 		min_size = (hp1->key_size < hp2->key_size) ? hp1->key_size :
8806a99fe3SHajimu UMEMOTO 			hp2->key_size;
8906a99fe3SHajimu UMEMOTO 		result = memcmp(hp1->key, hp2->key, min_size);
9006a99fe3SHajimu UMEMOTO 
9106a99fe3SHajimu UMEMOTO 		if (result == 0)
9206a99fe3SHajimu UMEMOTO 			return ((hp1->key_size < hp2->key_size) ? -1 : 1);
9306a99fe3SHajimu UMEMOTO 		else
9406a99fe3SHajimu UMEMOTO 			return (result);
9506a99fe3SHajimu UMEMOTO 	} else
9606a99fe3SHajimu UMEMOTO 		return (memcmp(hp1->key, hp2->key, hp1->key_size));
9706a99fe3SHajimu UMEMOTO }
9806a99fe3SHajimu UMEMOTO 
9906a99fe3SHajimu UMEMOTO static int
ht_items_fixed_size_left_cmp_func(const void * p1,const void * p2)10006a99fe3SHajimu UMEMOTO ht_items_fixed_size_left_cmp_func(const void *p1, const void *p2)
10106a99fe3SHajimu UMEMOTO {
10206a99fe3SHajimu UMEMOTO     	struct cache_ht_item_data_ *hp1, *hp2;
10306a99fe3SHajimu UMEMOTO 	size_t min_size;
10406a99fe3SHajimu UMEMOTO 	int result;
10506a99fe3SHajimu UMEMOTO 
10606a99fe3SHajimu UMEMOTO 	hp1 = (struct cache_ht_item_data_ *)p1;
10706a99fe3SHajimu UMEMOTO 	hp2 = (struct cache_ht_item_data_ *)p2;
10806a99fe3SHajimu UMEMOTO 
10906a99fe3SHajimu UMEMOTO 	assert(hp1->key != NULL);
11006a99fe3SHajimu UMEMOTO 	assert(hp2->key != NULL);
11106a99fe3SHajimu UMEMOTO 
11206a99fe3SHajimu UMEMOTO 	if (hp1->key_size != hp2->key_size) {
11306a99fe3SHajimu UMEMOTO 		min_size = (hp1->key_size < hp2->key_size) ? hp1->key_size :
11406a99fe3SHajimu UMEMOTO 			hp2->key_size;
11506a99fe3SHajimu UMEMOTO 		result = memcmp(hp1->key, hp2->key, min_size);
11606a99fe3SHajimu UMEMOTO 
11706a99fe3SHajimu UMEMOTO 		if (result == 0)
11806a99fe3SHajimu UMEMOTO 			if (min_size == hp1->key_size)
11906a99fe3SHajimu UMEMOTO 			    return (0);
12006a99fe3SHajimu UMEMOTO 			else
12106a99fe3SHajimu UMEMOTO 			    return ((hp1->key_size < hp2->key_size) ? -1 : 1);
12206a99fe3SHajimu UMEMOTO 		else
12306a99fe3SHajimu UMEMOTO 			return (result);
12406a99fe3SHajimu UMEMOTO 	} else
12506a99fe3SHajimu UMEMOTO 		return (memcmp(hp1->key, hp2->key, hp1->key_size));
12606a99fe3SHajimu UMEMOTO }
12706a99fe3SHajimu UMEMOTO 
12806a99fe3SHajimu UMEMOTO static hashtable_index_t
ht_item_hash_func(const void * p,size_t cache_entries_size)12906a99fe3SHajimu UMEMOTO ht_item_hash_func(const void *p, size_t cache_entries_size)
13006a99fe3SHajimu UMEMOTO {
13106a99fe3SHajimu UMEMOTO     	struct cache_ht_item_data_ *hp;
13206a99fe3SHajimu UMEMOTO 	size_t i;
13306a99fe3SHajimu UMEMOTO 
13406a99fe3SHajimu UMEMOTO 	hashtable_index_t retval;
13506a99fe3SHajimu UMEMOTO 
13606a99fe3SHajimu UMEMOTO 	hp = (struct cache_ht_item_data_ *)p;
13706a99fe3SHajimu UMEMOTO 	assert(hp->key != NULL);
13806a99fe3SHajimu UMEMOTO 
13906a99fe3SHajimu UMEMOTO 	retval = 0;
14006a99fe3SHajimu UMEMOTO 	for (i = 0; i < hp->key_size; ++i)
14106a99fe3SHajimu UMEMOTO 	    retval = (127 * retval + (unsigned char)hp->key[i]) %
14206a99fe3SHajimu UMEMOTO 		cache_entries_size;
14306a99fe3SHajimu UMEMOTO 
14406a99fe3SHajimu UMEMOTO 	return retval;
14506a99fe3SHajimu UMEMOTO }
14606a99fe3SHajimu UMEMOTO 
1472bdde973SDag-Erling Smørgrav HASHTABLE_PROTOTYPE(cache_ht_, cache_ht_item_, struct cache_ht_item_data_);
14806a99fe3SHajimu UMEMOTO HASHTABLE_GENERATE(cache_ht_, cache_ht_item_, struct cache_ht_item_data_, data,
14906a99fe3SHajimu UMEMOTO 	ht_item_hash_func, ht_items_cmp_func);
15006a99fe3SHajimu UMEMOTO 
15106a99fe3SHajimu UMEMOTO /*
15206a99fe3SHajimu UMEMOTO  * Routines to sort and search the entries by name
15306a99fe3SHajimu UMEMOTO  */
15406a99fe3SHajimu UMEMOTO static int
entries_bsearch_cmp_func(const void * key,const void * ent)15506a99fe3SHajimu UMEMOTO entries_bsearch_cmp_func(const void *key, const void *ent)
15606a99fe3SHajimu UMEMOTO {
15706a99fe3SHajimu UMEMOTO 
15806a99fe3SHajimu UMEMOTO 	assert(key != NULL);
15906a99fe3SHajimu UMEMOTO 	assert(ent != NULL);
16006a99fe3SHajimu UMEMOTO 
16106a99fe3SHajimu UMEMOTO 	return (strcmp((char const *)key,
16206a99fe3SHajimu UMEMOTO 		(*(struct cache_entry_ const **)ent)->name));
16306a99fe3SHajimu UMEMOTO }
16406a99fe3SHajimu UMEMOTO 
16506a99fe3SHajimu UMEMOTO static int
entries_qsort_cmp_func(const void * e1,const void * e2)16606a99fe3SHajimu UMEMOTO entries_qsort_cmp_func(const void *e1, const void *e2)
16706a99fe3SHajimu UMEMOTO {
16806a99fe3SHajimu UMEMOTO 
16906a99fe3SHajimu UMEMOTO 	assert(e1 != NULL);
17006a99fe3SHajimu UMEMOTO 	assert(e2 != NULL);
17106a99fe3SHajimu UMEMOTO 
17206a99fe3SHajimu UMEMOTO 	return (strcmp((*(struct cache_entry_ const **)e1)->name,
17306a99fe3SHajimu UMEMOTO 		(*(struct cache_entry_ const **)e2)->name));
17406a99fe3SHajimu UMEMOTO }
17506a99fe3SHajimu UMEMOTO 
17606a99fe3SHajimu UMEMOTO static struct cache_entry_ **
find_cache_entry_p(struct cache_ * the_cache,const char * entry_name)17706a99fe3SHajimu UMEMOTO find_cache_entry_p(struct cache_ *the_cache, const char *entry_name)
17806a99fe3SHajimu UMEMOTO {
17906a99fe3SHajimu UMEMOTO 
18006a99fe3SHajimu UMEMOTO 	return ((struct cache_entry_ **)(bsearch(entry_name, the_cache->entries,
18106a99fe3SHajimu UMEMOTO 		the_cache->entries_size, sizeof(struct cache_entry_ *),
18206a99fe3SHajimu UMEMOTO 		entries_bsearch_cmp_func)));
18306a99fe3SHajimu UMEMOTO }
18406a99fe3SHajimu UMEMOTO 
18506a99fe3SHajimu UMEMOTO static void
destroy_cache_mp_write_session(struct cache_mp_write_session_ * ws)18606a99fe3SHajimu UMEMOTO destroy_cache_mp_write_session(struct cache_mp_write_session_ *ws)
18706a99fe3SHajimu UMEMOTO {
18806a99fe3SHajimu UMEMOTO 
18906a99fe3SHajimu UMEMOTO 	struct cache_mp_data_item_	*data_item;
19006a99fe3SHajimu UMEMOTO 
19106a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_cache_mp_write_session);
19206a99fe3SHajimu UMEMOTO 	assert(ws != NULL);
19306a99fe3SHajimu UMEMOTO 	while (!TAILQ_EMPTY(&ws->items)) {
19406a99fe3SHajimu UMEMOTO 		data_item = TAILQ_FIRST(&ws->items);
19506a99fe3SHajimu UMEMOTO 		TAILQ_REMOVE(&ws->items, data_item, entries);
19606a99fe3SHajimu UMEMOTO 		free(data_item->value);
19706a99fe3SHajimu UMEMOTO 		free(data_item);
19806a99fe3SHajimu UMEMOTO 	}
19906a99fe3SHajimu UMEMOTO 
20006a99fe3SHajimu UMEMOTO 	free(ws);
20106a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_cache_mp_write_session);
20206a99fe3SHajimu UMEMOTO }
20306a99fe3SHajimu UMEMOTO 
20406a99fe3SHajimu UMEMOTO static void
destroy_cache_mp_read_session(struct cache_mp_read_session_ * rs)20506a99fe3SHajimu UMEMOTO destroy_cache_mp_read_session(struct cache_mp_read_session_ *rs)
20606a99fe3SHajimu UMEMOTO {
20706a99fe3SHajimu UMEMOTO 
20806a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_cache_mp_read_session);
20906a99fe3SHajimu UMEMOTO 	assert(rs != NULL);
21006a99fe3SHajimu UMEMOTO 	free(rs);
21106a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_cache_mp_read_session);
21206a99fe3SHajimu UMEMOTO }
21306a99fe3SHajimu UMEMOTO 
21406a99fe3SHajimu UMEMOTO static void
destroy_cache_entry(struct cache_entry_ * entry)21506a99fe3SHajimu UMEMOTO destroy_cache_entry(struct cache_entry_ *entry)
21606a99fe3SHajimu UMEMOTO {
21706a99fe3SHajimu UMEMOTO 	struct cache_common_entry_	*common_entry;
21806a99fe3SHajimu UMEMOTO 	struct cache_mp_entry_		*mp_entry;
21906a99fe3SHajimu UMEMOTO 	struct cache_mp_read_session_	*rs;
22006a99fe3SHajimu UMEMOTO 	struct cache_mp_write_session_	*ws;
22106a99fe3SHajimu UMEMOTO 	struct cache_ht_item_ *ht_item;
22206a99fe3SHajimu UMEMOTO 	struct cache_ht_item_data_ *ht_item_data;
22306a99fe3SHajimu UMEMOTO 
22406a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_cache_entry);
22506a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
22606a99fe3SHajimu UMEMOTO 
22706a99fe3SHajimu UMEMOTO 	if (entry->params->entry_type == CET_COMMON) {
22806a99fe3SHajimu UMEMOTO 		common_entry = (struct cache_common_entry_ *)entry;
22906a99fe3SHajimu UMEMOTO 
23006a99fe3SHajimu UMEMOTO 		HASHTABLE_FOREACH(&(common_entry->items), ht_item) {
23106a99fe3SHajimu UMEMOTO 			HASHTABLE_ENTRY_FOREACH(ht_item, data, ht_item_data)
23206a99fe3SHajimu UMEMOTO 			{
23306a99fe3SHajimu UMEMOTO 				free(ht_item_data->key);
23406a99fe3SHajimu UMEMOTO 				free(ht_item_data->value);
23506a99fe3SHajimu UMEMOTO 			}
23606a99fe3SHajimu UMEMOTO 			HASHTABLE_ENTRY_CLEAR(ht_item, data);
23706a99fe3SHajimu UMEMOTO 		}
23806a99fe3SHajimu UMEMOTO 
23906a99fe3SHajimu UMEMOTO 		HASHTABLE_DESTROY(&(common_entry->items), data);
24006a99fe3SHajimu UMEMOTO 
24106a99fe3SHajimu UMEMOTO 		/* FIFO policy is always first */
24206a99fe3SHajimu UMEMOTO 		destroy_cache_fifo_policy(common_entry->policies[0]);
24306a99fe3SHajimu UMEMOTO 		switch (common_entry->common_params.policy) {
24406a99fe3SHajimu UMEMOTO 		case CPT_LRU:
24506a99fe3SHajimu UMEMOTO 			destroy_cache_lru_policy(common_entry->policies[1]);
24606a99fe3SHajimu UMEMOTO 			break;
24706a99fe3SHajimu UMEMOTO 		case CPT_LFU:
24806a99fe3SHajimu UMEMOTO 			destroy_cache_lfu_policy(common_entry->policies[1]);
24906a99fe3SHajimu UMEMOTO 			break;
25006a99fe3SHajimu UMEMOTO 		default:
25106a99fe3SHajimu UMEMOTO 		break;
25206a99fe3SHajimu UMEMOTO 		}
25306a99fe3SHajimu UMEMOTO 		free(common_entry->policies);
25406a99fe3SHajimu UMEMOTO 	} else {
25506a99fe3SHajimu UMEMOTO 		mp_entry = (struct cache_mp_entry_ *)entry;
25606a99fe3SHajimu UMEMOTO 
25706a99fe3SHajimu UMEMOTO 		while (!TAILQ_EMPTY(&mp_entry->ws_head)) {
25806a99fe3SHajimu UMEMOTO 			ws = TAILQ_FIRST(&mp_entry->ws_head);
25906a99fe3SHajimu UMEMOTO 			TAILQ_REMOVE(&mp_entry->ws_head, ws, entries);
26006a99fe3SHajimu UMEMOTO 			destroy_cache_mp_write_session(ws);
26106a99fe3SHajimu UMEMOTO 		}
26206a99fe3SHajimu UMEMOTO 
26306a99fe3SHajimu UMEMOTO 		while (!TAILQ_EMPTY(&mp_entry->rs_head)) {
26406a99fe3SHajimu UMEMOTO 			rs = TAILQ_FIRST(&mp_entry->rs_head);
26506a99fe3SHajimu UMEMOTO 			TAILQ_REMOVE(&mp_entry->rs_head, rs, entries);
26606a99fe3SHajimu UMEMOTO 			destroy_cache_mp_read_session(rs);
26706a99fe3SHajimu UMEMOTO 		}
26806a99fe3SHajimu UMEMOTO 
26906a99fe3SHajimu UMEMOTO 		if (mp_entry->completed_write_session != NULL)
27006a99fe3SHajimu UMEMOTO 			destroy_cache_mp_write_session(
27106a99fe3SHajimu UMEMOTO 				mp_entry->completed_write_session);
27206a99fe3SHajimu UMEMOTO 
27306a99fe3SHajimu UMEMOTO 		if (mp_entry->pending_write_session != NULL)
27406a99fe3SHajimu UMEMOTO 			destroy_cache_mp_write_session(
27506a99fe3SHajimu UMEMOTO 				mp_entry->pending_write_session);
27606a99fe3SHajimu UMEMOTO 	}
27706a99fe3SHajimu UMEMOTO 
27806a99fe3SHajimu UMEMOTO 	free(entry->name);
27906a99fe3SHajimu UMEMOTO 	free(entry);
28006a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_cache_entry);
28106a99fe3SHajimu UMEMOTO }
28206a99fe3SHajimu UMEMOTO 
28306a99fe3SHajimu UMEMOTO static void
clear_cache_entry(struct cache_entry_ * entry)28406a99fe3SHajimu UMEMOTO clear_cache_entry(struct cache_entry_ *entry)
28506a99fe3SHajimu UMEMOTO {
28606a99fe3SHajimu UMEMOTO 	struct cache_mp_entry_		*mp_entry;
28706a99fe3SHajimu UMEMOTO 	struct cache_common_entry_	*common_entry;
28806a99fe3SHajimu UMEMOTO 	struct cache_ht_item_ *ht_item;
28906a99fe3SHajimu UMEMOTO 	struct cache_ht_item_data_ *ht_item_data;
29006a99fe3SHajimu UMEMOTO 	struct cache_policy_ *policy;
29106a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item, *next_item;
29206a99fe3SHajimu UMEMOTO 	size_t entry_size;
2932bdde973SDag-Erling Smørgrav 	unsigned int i;
29406a99fe3SHajimu UMEMOTO 
29506a99fe3SHajimu UMEMOTO 	if (entry->params->entry_type == CET_COMMON) {
29606a99fe3SHajimu UMEMOTO 		common_entry = (struct cache_common_entry_ *)entry;
29706a99fe3SHajimu UMEMOTO 
29806a99fe3SHajimu UMEMOTO 		entry_size = 0;
29906a99fe3SHajimu UMEMOTO 		HASHTABLE_FOREACH(&(common_entry->items), ht_item) {
30006a99fe3SHajimu UMEMOTO 			HASHTABLE_ENTRY_FOREACH(ht_item, data, ht_item_data)
30106a99fe3SHajimu UMEMOTO 			{
30206a99fe3SHajimu UMEMOTO 				free(ht_item_data->key);
30306a99fe3SHajimu UMEMOTO 				free(ht_item_data->value);
30406a99fe3SHajimu UMEMOTO 			}
30506a99fe3SHajimu UMEMOTO 			entry_size += HASHTABLE_ENTRY_SIZE(ht_item, data);
30606a99fe3SHajimu UMEMOTO 			HASHTABLE_ENTRY_CLEAR(ht_item, data);
30706a99fe3SHajimu UMEMOTO 		}
30806a99fe3SHajimu UMEMOTO 
30906a99fe3SHajimu UMEMOTO 		common_entry->items_size -= entry_size;
31006a99fe3SHajimu UMEMOTO 		for (i = 0; i < common_entry->policies_size; ++i) {
31106a99fe3SHajimu UMEMOTO 			policy = common_entry->policies[i];
31206a99fe3SHajimu UMEMOTO 
31306a99fe3SHajimu UMEMOTO 			next_item = NULL;
31406a99fe3SHajimu UMEMOTO 			item = policy->get_first_item_func(policy);
31506a99fe3SHajimu UMEMOTO 			while (item != NULL) {
31606a99fe3SHajimu UMEMOTO 				next_item = policy->get_next_item_func(policy,
31706a99fe3SHajimu UMEMOTO 			    		item);
31806a99fe3SHajimu UMEMOTO 				policy->remove_item_func(policy, item);
31906a99fe3SHajimu UMEMOTO 				policy->destroy_item_func(item);
32006a99fe3SHajimu UMEMOTO 				item = next_item;
32106a99fe3SHajimu UMEMOTO 			}
32206a99fe3SHajimu UMEMOTO 		}
32306a99fe3SHajimu UMEMOTO 	} else {
32406a99fe3SHajimu UMEMOTO 		mp_entry = (struct cache_mp_entry_ *)entry;
32506a99fe3SHajimu UMEMOTO 
32606a99fe3SHajimu UMEMOTO 		if (mp_entry->rs_size == 0) {
32706a99fe3SHajimu UMEMOTO 			if (mp_entry->completed_write_session != NULL) {
32806a99fe3SHajimu UMEMOTO 				destroy_cache_mp_write_session(
32906a99fe3SHajimu UMEMOTO 					mp_entry->completed_write_session);
33006a99fe3SHajimu UMEMOTO 				mp_entry->completed_write_session = NULL;
33106a99fe3SHajimu UMEMOTO 			}
33206a99fe3SHajimu UMEMOTO 
33306a99fe3SHajimu UMEMOTO 			memset(&mp_entry->creation_time, 0,
33406a99fe3SHajimu UMEMOTO 				sizeof(struct timeval));
33506a99fe3SHajimu UMEMOTO 			memset(&mp_entry->last_request_time, 0,
33606a99fe3SHajimu UMEMOTO 				sizeof(struct timeval));
33706a99fe3SHajimu UMEMOTO 		}
33806a99fe3SHajimu UMEMOTO 	}
33906a99fe3SHajimu UMEMOTO }
34006a99fe3SHajimu UMEMOTO 
34106a99fe3SHajimu UMEMOTO /*
34206a99fe3SHajimu UMEMOTO  * When passed to the flush_cache_policy, ensures that all old elements are
34306a99fe3SHajimu UMEMOTO  * deleted.
34406a99fe3SHajimu UMEMOTO  */
34506a99fe3SHajimu UMEMOTO static int
cache_lifetime_common_continue_func(struct cache_common_entry_ * entry,struct cache_policy_item_ * item)34606a99fe3SHajimu UMEMOTO cache_lifetime_common_continue_func(struct cache_common_entry_ *entry,
34706a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
34806a99fe3SHajimu UMEMOTO {
34906a99fe3SHajimu UMEMOTO 
35006a99fe3SHajimu UMEMOTO 	return ((item->last_request_time.tv_sec - item->creation_time.tv_sec >
35106a99fe3SHajimu UMEMOTO 		entry->common_params.max_lifetime.tv_sec) ? 1: 0);
35206a99fe3SHajimu UMEMOTO }
35306a99fe3SHajimu UMEMOTO 
35406a99fe3SHajimu UMEMOTO /*
35506a99fe3SHajimu UMEMOTO  * When passed to the flush_cache_policy, ensures that all elements, that
35606a99fe3SHajimu UMEMOTO  * exceed the size limit, are deleted.
35706a99fe3SHajimu UMEMOTO  */
35806a99fe3SHajimu UMEMOTO static int
cache_elemsize_common_continue_func(struct cache_common_entry_ * entry,struct cache_policy_item_ * item)35906a99fe3SHajimu UMEMOTO cache_elemsize_common_continue_func(struct cache_common_entry_ *entry,
36006a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item)
36106a99fe3SHajimu UMEMOTO {
36206a99fe3SHajimu UMEMOTO 
36306a99fe3SHajimu UMEMOTO 	return ((entry->items_size > entry->common_params.satisf_elemsize) ? 1
36406a99fe3SHajimu UMEMOTO     		: 0);
36506a99fe3SHajimu UMEMOTO }
36606a99fe3SHajimu UMEMOTO 
36706a99fe3SHajimu UMEMOTO /*
36806a99fe3SHajimu UMEMOTO  * Removes the elements from the cache entry, while the continue_func returns 1.
36906a99fe3SHajimu UMEMOTO  */
37006a99fe3SHajimu UMEMOTO static void
flush_cache_policy(struct cache_common_entry_ * entry,struct cache_policy_ * policy,struct cache_policy_ * connected_policy,int (* continue_func)(struct cache_common_entry_ *,struct cache_policy_item_ *))37106a99fe3SHajimu UMEMOTO flush_cache_policy(struct cache_common_entry_ *entry,
37206a99fe3SHajimu UMEMOTO 	struct cache_policy_ *policy,
37306a99fe3SHajimu UMEMOTO 	struct cache_policy_ *connected_policy,
37406a99fe3SHajimu UMEMOTO 	int (*continue_func)(struct cache_common_entry_ *,
37506a99fe3SHajimu UMEMOTO 		struct cache_policy_item_ *))
37606a99fe3SHajimu UMEMOTO {
37706a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item, *next_item, *connected_item;
37806a99fe3SHajimu UMEMOTO 	struct cache_ht_item_ *ht_item;
37906a99fe3SHajimu UMEMOTO 	struct cache_ht_item_data_ *ht_item_data, ht_key;
38006a99fe3SHajimu UMEMOTO 	hashtable_index_t hash;
38106a99fe3SHajimu UMEMOTO 
38206a99fe3SHajimu UMEMOTO 	assert(policy != NULL);
38306a99fe3SHajimu UMEMOTO 
38406a99fe3SHajimu UMEMOTO 	next_item = NULL;
38506a99fe3SHajimu UMEMOTO 	item = policy->get_first_item_func(policy);
38606a99fe3SHajimu UMEMOTO 	while ((item != NULL) && (continue_func(entry, item) == 1)) {
38706a99fe3SHajimu UMEMOTO 		next_item = policy->get_next_item_func(policy, item);
38806a99fe3SHajimu UMEMOTO 
38906a99fe3SHajimu UMEMOTO 		connected_item = item->connected_item;
39006a99fe3SHajimu UMEMOTO 		policy->remove_item_func(policy, item);
39106a99fe3SHajimu UMEMOTO 
39206a99fe3SHajimu UMEMOTO 		memset(&ht_key, 0, sizeof(struct cache_ht_item_data_));
39306a99fe3SHajimu UMEMOTO 		ht_key.key = item->key;
39406a99fe3SHajimu UMEMOTO 		ht_key.key_size = item->key_size;
39506a99fe3SHajimu UMEMOTO 
39606a99fe3SHajimu UMEMOTO 		hash = HASHTABLE_CALCULATE_HASH(cache_ht_, &entry->items,
39706a99fe3SHajimu UMEMOTO 			&ht_key);
39806a99fe3SHajimu UMEMOTO 		assert(hash < HASHTABLE_ENTRIES_COUNT(&entry->items));
39906a99fe3SHajimu UMEMOTO 
40006a99fe3SHajimu UMEMOTO 		ht_item = HASHTABLE_GET_ENTRY(&(entry->items), hash);
40106a99fe3SHajimu UMEMOTO 		ht_item_data = HASHTABLE_ENTRY_FIND(cache_ht_, ht_item,
40206a99fe3SHajimu UMEMOTO 			&ht_key);
40306a99fe3SHajimu UMEMOTO 		assert(ht_item_data != NULL);
40406a99fe3SHajimu UMEMOTO 		free(ht_item_data->key);
40506a99fe3SHajimu UMEMOTO 		free(ht_item_data->value);
40606a99fe3SHajimu UMEMOTO 		HASHTABLE_ENTRY_REMOVE(cache_ht_, ht_item, ht_item_data);
40706a99fe3SHajimu UMEMOTO 		--entry->items_size;
40806a99fe3SHajimu UMEMOTO 
40906a99fe3SHajimu UMEMOTO 		policy->destroy_item_func(item);
41006a99fe3SHajimu UMEMOTO 
41106a99fe3SHajimu UMEMOTO 		if (connected_item != NULL) {
41206a99fe3SHajimu UMEMOTO 			connected_policy->remove_item_func(connected_policy,
41306a99fe3SHajimu UMEMOTO 				connected_item);
41406a99fe3SHajimu UMEMOTO 			connected_policy->destroy_item_func(connected_item);
41506a99fe3SHajimu UMEMOTO 		}
41606a99fe3SHajimu UMEMOTO 
41706a99fe3SHajimu UMEMOTO 		item = next_item;
41806a99fe3SHajimu UMEMOTO 	}
41906a99fe3SHajimu UMEMOTO }
42006a99fe3SHajimu UMEMOTO 
42106a99fe3SHajimu UMEMOTO static void
flush_cache_entry(struct cache_entry_ * entry)42206a99fe3SHajimu UMEMOTO flush_cache_entry(struct cache_entry_ *entry)
42306a99fe3SHajimu UMEMOTO {
42406a99fe3SHajimu UMEMOTO 	struct cache_mp_entry_		*mp_entry;
42506a99fe3SHajimu UMEMOTO 	struct cache_common_entry_	*common_entry;
42606a99fe3SHajimu UMEMOTO 	struct cache_policy_ *policy, *connected_policy;
42706a99fe3SHajimu UMEMOTO 
42806a99fe3SHajimu UMEMOTO 	connected_policy = NULL;
42906a99fe3SHajimu UMEMOTO 	if (entry->params->entry_type == CET_COMMON) {
43006a99fe3SHajimu UMEMOTO 		common_entry = (struct cache_common_entry_ *)entry;
43106a99fe3SHajimu UMEMOTO 		if ((common_entry->common_params.max_lifetime.tv_sec != 0) ||
43206a99fe3SHajimu UMEMOTO 		    (common_entry->common_params.max_lifetime.tv_usec != 0)) {
43306a99fe3SHajimu UMEMOTO 
43406a99fe3SHajimu UMEMOTO 			policy = common_entry->policies[0];
43506a99fe3SHajimu UMEMOTO 			if (common_entry->policies_size > 1)
43606a99fe3SHajimu UMEMOTO 				connected_policy = common_entry->policies[1];
43706a99fe3SHajimu UMEMOTO 
43806a99fe3SHajimu UMEMOTO 			flush_cache_policy(common_entry, policy,
43906a99fe3SHajimu UMEMOTO 				connected_policy,
44006a99fe3SHajimu UMEMOTO 				cache_lifetime_common_continue_func);
44106a99fe3SHajimu UMEMOTO 		}
44206a99fe3SHajimu UMEMOTO 
44306a99fe3SHajimu UMEMOTO 
44406a99fe3SHajimu UMEMOTO 		if ((common_entry->common_params.max_elemsize != 0) &&
44506a99fe3SHajimu UMEMOTO 			common_entry->items_size >
44606a99fe3SHajimu UMEMOTO 			common_entry->common_params.max_elemsize) {
44706a99fe3SHajimu UMEMOTO 
44806a99fe3SHajimu UMEMOTO 			if (common_entry->policies_size > 1) {
44906a99fe3SHajimu UMEMOTO 				policy = common_entry->policies[1];
45006a99fe3SHajimu UMEMOTO 				connected_policy = common_entry->policies[0];
45106a99fe3SHajimu UMEMOTO 			} else {
45206a99fe3SHajimu UMEMOTO 				policy = common_entry->policies[0];
45306a99fe3SHajimu UMEMOTO 				connected_policy = NULL;
45406a99fe3SHajimu UMEMOTO 			}
45506a99fe3SHajimu UMEMOTO 
45606a99fe3SHajimu UMEMOTO 			flush_cache_policy(common_entry, policy,
45706a99fe3SHajimu UMEMOTO 				connected_policy,
45806a99fe3SHajimu UMEMOTO 				cache_elemsize_common_continue_func);
45906a99fe3SHajimu UMEMOTO 		}
46006a99fe3SHajimu UMEMOTO 	} else {
46106a99fe3SHajimu UMEMOTO 		mp_entry = (struct cache_mp_entry_ *)entry;
46206a99fe3SHajimu UMEMOTO 
46306a99fe3SHajimu UMEMOTO 		if ((mp_entry->mp_params.max_lifetime.tv_sec != 0)
46406a99fe3SHajimu UMEMOTO 			|| (mp_entry->mp_params.max_lifetime.tv_usec != 0)) {
46506a99fe3SHajimu UMEMOTO 
46606a99fe3SHajimu UMEMOTO 			if (mp_entry->last_request_time.tv_sec -
46706a99fe3SHajimu UMEMOTO 				mp_entry->last_request_time.tv_sec >
46806a99fe3SHajimu UMEMOTO 				mp_entry->mp_params.max_lifetime.tv_sec)
46906a99fe3SHajimu UMEMOTO 				clear_cache_entry(entry);
47006a99fe3SHajimu UMEMOTO 		}
47106a99fe3SHajimu UMEMOTO 	}
47206a99fe3SHajimu UMEMOTO }
47306a99fe3SHajimu UMEMOTO 
47406a99fe3SHajimu UMEMOTO struct cache_ *
init_cache(struct cache_params const * params)47506a99fe3SHajimu UMEMOTO init_cache(struct cache_params const *params)
47606a99fe3SHajimu UMEMOTO {
47706a99fe3SHajimu UMEMOTO 	struct cache_ *retval;
47806a99fe3SHajimu UMEMOTO 
47906a99fe3SHajimu UMEMOTO 	TRACE_IN(init_cache);
48006a99fe3SHajimu UMEMOTO 	assert(params != NULL);
48106a99fe3SHajimu UMEMOTO 
4828eeaaffaSDag-Erling Smørgrav 	retval = calloc(1, sizeof(*retval));
48306a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
48406a99fe3SHajimu UMEMOTO 
48506a99fe3SHajimu UMEMOTO 	assert(params != NULL);
48606a99fe3SHajimu UMEMOTO 	memcpy(&retval->params, params, sizeof(struct cache_params));
48706a99fe3SHajimu UMEMOTO 
488*87959e27SPedro F. Giffuni 	retval->entries = calloc(INITIAL_ENTRIES_CAPACITY,
489*87959e27SPedro F. Giffuni 		sizeof(*retval->entries));
49006a99fe3SHajimu UMEMOTO 	assert(retval->entries != NULL);
49106a99fe3SHajimu UMEMOTO 
49206a99fe3SHajimu UMEMOTO 	retval->entries_capacity = INITIAL_ENTRIES_CAPACITY;
49306a99fe3SHajimu UMEMOTO 	retval->entries_size = 0;
49406a99fe3SHajimu UMEMOTO 
49506a99fe3SHajimu UMEMOTO 	TRACE_OUT(init_cache);
49606a99fe3SHajimu UMEMOTO 	return (retval);
49706a99fe3SHajimu UMEMOTO }
49806a99fe3SHajimu UMEMOTO 
49906a99fe3SHajimu UMEMOTO void
destroy_cache(struct cache_ * the_cache)50006a99fe3SHajimu UMEMOTO destroy_cache(struct cache_ *the_cache)
50106a99fe3SHajimu UMEMOTO {
50206a99fe3SHajimu UMEMOTO 
50306a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_cache);
50406a99fe3SHajimu UMEMOTO 	assert(the_cache != NULL);
50506a99fe3SHajimu UMEMOTO 
50606a99fe3SHajimu UMEMOTO 	if (the_cache->entries != NULL) {
50706a99fe3SHajimu UMEMOTO 		size_t i;
50806a99fe3SHajimu UMEMOTO 		for (i = 0; i < the_cache->entries_size; ++i)
50906a99fe3SHajimu UMEMOTO 			destroy_cache_entry(the_cache->entries[i]);
51006a99fe3SHajimu UMEMOTO 
51106a99fe3SHajimu UMEMOTO 		free(the_cache->entries);
51206a99fe3SHajimu UMEMOTO 	}
51306a99fe3SHajimu UMEMOTO 
51406a99fe3SHajimu UMEMOTO 	free(the_cache);
51506a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_cache);
51606a99fe3SHajimu UMEMOTO }
51706a99fe3SHajimu UMEMOTO 
51806a99fe3SHajimu UMEMOTO int
register_cache_entry(struct cache_ * the_cache,struct cache_entry_params const * params)51906a99fe3SHajimu UMEMOTO register_cache_entry(struct cache_ *the_cache,
52006a99fe3SHajimu UMEMOTO 	struct cache_entry_params const *params)
52106a99fe3SHajimu UMEMOTO {
52206a99fe3SHajimu UMEMOTO 	int policies_size;
52306a99fe3SHajimu UMEMOTO 	size_t entry_name_size;
52406a99fe3SHajimu UMEMOTO 	struct cache_common_entry_	*new_common_entry;
52506a99fe3SHajimu UMEMOTO 	struct cache_mp_entry_		*new_mp_entry;
52606a99fe3SHajimu UMEMOTO 
52706a99fe3SHajimu UMEMOTO 	TRACE_IN(register_cache_entry);
52806a99fe3SHajimu UMEMOTO 	assert(the_cache != NULL);
52906a99fe3SHajimu UMEMOTO 
53006a99fe3SHajimu UMEMOTO 	if (find_cache_entry(the_cache, params->entry_name) != NULL) {
53106a99fe3SHajimu UMEMOTO 		TRACE_OUT(register_cache_entry);
53206a99fe3SHajimu UMEMOTO 		return (-1);
53306a99fe3SHajimu UMEMOTO 	}
53406a99fe3SHajimu UMEMOTO 
53506a99fe3SHajimu UMEMOTO 	if (the_cache->entries_size == the_cache->entries_capacity) {
53606a99fe3SHajimu UMEMOTO 		struct cache_entry_ **new_entries;
53706a99fe3SHajimu UMEMOTO 		size_t	new_capacity;
53806a99fe3SHajimu UMEMOTO 
53906a99fe3SHajimu UMEMOTO 		new_capacity = the_cache->entries_capacity +
54006a99fe3SHajimu UMEMOTO 			ENTRIES_CAPACITY_STEP;
541*87959e27SPedro F. Giffuni 		new_entries = calloc(new_capacity,
542*87959e27SPedro F. Giffuni 			sizeof(*new_entries));
54306a99fe3SHajimu UMEMOTO 		assert(new_entries != NULL);
54406a99fe3SHajimu UMEMOTO 
54506a99fe3SHajimu UMEMOTO 		memcpy(new_entries, the_cache->entries,
54606a99fe3SHajimu UMEMOTO 			sizeof(struct cache_entry_ *)
54706a99fe3SHajimu UMEMOTO 			* the_cache->entries_size);
54806a99fe3SHajimu UMEMOTO 
54906a99fe3SHajimu UMEMOTO 		free(the_cache->entries);
55006a99fe3SHajimu UMEMOTO 		the_cache->entries = new_entries;
55106a99fe3SHajimu UMEMOTO 	}
55206a99fe3SHajimu UMEMOTO 
553a3c4f724SXin LI 	entry_name_size = strlen(params->entry_name) + 1;
55406a99fe3SHajimu UMEMOTO 	switch (params->entry_type)
55506a99fe3SHajimu UMEMOTO 	{
55606a99fe3SHajimu UMEMOTO 	case CET_COMMON:
5578eeaaffaSDag-Erling Smørgrav 		new_common_entry = calloc(1,
5588eeaaffaSDag-Erling Smørgrav 			sizeof(*new_common_entry));
55906a99fe3SHajimu UMEMOTO 		assert(new_common_entry != NULL);
56006a99fe3SHajimu UMEMOTO 
56106a99fe3SHajimu UMEMOTO 		memcpy(&new_common_entry->common_params, params,
56206a99fe3SHajimu UMEMOTO 			sizeof(struct common_cache_entry_params));
56306a99fe3SHajimu UMEMOTO 		new_common_entry->params =
56406a99fe3SHajimu UMEMOTO 		  (struct cache_entry_params *)&new_common_entry->common_params;
56506a99fe3SHajimu UMEMOTO 
5668eeaaffaSDag-Erling Smørgrav 		new_common_entry->common_params.cep.entry_name = calloc(1,
567a3c4f724SXin LI 			entry_name_size);
56827f2bc9eSDag-Erling Smørgrav 		assert(new_common_entry->common_params.cep.entry_name != NULL);
56927f2bc9eSDag-Erling Smørgrav 		strlcpy(new_common_entry->common_params.cep.entry_name,
57006a99fe3SHajimu UMEMOTO 			params->entry_name, entry_name_size);
57106a99fe3SHajimu UMEMOTO 		new_common_entry->name =
57227f2bc9eSDag-Erling Smørgrav 			new_common_entry->common_params.cep.entry_name;
57306a99fe3SHajimu UMEMOTO 
57406a99fe3SHajimu UMEMOTO 		HASHTABLE_INIT(&(new_common_entry->items),
57506a99fe3SHajimu UMEMOTO 			struct cache_ht_item_data_, data,
57606a99fe3SHajimu UMEMOTO 			new_common_entry->common_params.cache_entries_size);
57706a99fe3SHajimu UMEMOTO 
57806a99fe3SHajimu UMEMOTO 		if (new_common_entry->common_params.policy == CPT_FIFO)
57906a99fe3SHajimu UMEMOTO 			policies_size = 1;
58006a99fe3SHajimu UMEMOTO 		else
58106a99fe3SHajimu UMEMOTO 			policies_size = 2;
58206a99fe3SHajimu UMEMOTO 
583*87959e27SPedro F. Giffuni 		new_common_entry->policies = calloc(policies_size,
584*87959e27SPedro F. Giffuni 			sizeof(*new_common_entry->policies));
58506a99fe3SHajimu UMEMOTO 		assert(new_common_entry->policies != NULL);
58606a99fe3SHajimu UMEMOTO 
58706a99fe3SHajimu UMEMOTO 		new_common_entry->policies_size = policies_size;
58806a99fe3SHajimu UMEMOTO 		new_common_entry->policies[0] = init_cache_fifo_policy();
58906a99fe3SHajimu UMEMOTO 
59006a99fe3SHajimu UMEMOTO 		if (policies_size > 1) {
59106a99fe3SHajimu UMEMOTO 			switch (new_common_entry->common_params.policy) {
59206a99fe3SHajimu UMEMOTO 			case CPT_LRU:
59306a99fe3SHajimu UMEMOTO 				new_common_entry->policies[1] =
59406a99fe3SHajimu UMEMOTO 					init_cache_lru_policy();
59506a99fe3SHajimu UMEMOTO 			break;
59606a99fe3SHajimu UMEMOTO 			case CPT_LFU:
59706a99fe3SHajimu UMEMOTO 				new_common_entry->policies[1] =
59806a99fe3SHajimu UMEMOTO 					init_cache_lfu_policy();
59906a99fe3SHajimu UMEMOTO 			break;
60006a99fe3SHajimu UMEMOTO 			default:
60106a99fe3SHajimu UMEMOTO 			break;
60206a99fe3SHajimu UMEMOTO 			}
60306a99fe3SHajimu UMEMOTO 		}
60406a99fe3SHajimu UMEMOTO 
60506a99fe3SHajimu UMEMOTO 		new_common_entry->get_time_func =
60606a99fe3SHajimu UMEMOTO 			the_cache->params.get_time_func;
60706a99fe3SHajimu UMEMOTO 		the_cache->entries[the_cache->entries_size++] =
60806a99fe3SHajimu UMEMOTO 			(struct cache_entry_ *)new_common_entry;
60906a99fe3SHajimu UMEMOTO 		break;
61006a99fe3SHajimu UMEMOTO 	case CET_MULTIPART:
6118eeaaffaSDag-Erling Smørgrav 		new_mp_entry = calloc(1,
6128eeaaffaSDag-Erling Smørgrav 			sizeof(*new_mp_entry));
61306a99fe3SHajimu UMEMOTO 		assert(new_mp_entry != NULL);
61406a99fe3SHajimu UMEMOTO 
61506a99fe3SHajimu UMEMOTO 		memcpy(&new_mp_entry->mp_params, params,
61606a99fe3SHajimu UMEMOTO 			sizeof(struct mp_cache_entry_params));
61706a99fe3SHajimu UMEMOTO 		new_mp_entry->params =
61806a99fe3SHajimu UMEMOTO 			(struct cache_entry_params *)&new_mp_entry->mp_params;
61906a99fe3SHajimu UMEMOTO 
6208eeaaffaSDag-Erling Smørgrav 		new_mp_entry->mp_params.cep.entry_name = calloc(1,
621a3c4f724SXin LI 			entry_name_size);
62227f2bc9eSDag-Erling Smørgrav 		assert(new_mp_entry->mp_params.cep.entry_name != NULL);
62327f2bc9eSDag-Erling Smørgrav 		strlcpy(new_mp_entry->mp_params.cep.entry_name, params->entry_name,
62406a99fe3SHajimu UMEMOTO 			entry_name_size);
62527f2bc9eSDag-Erling Smørgrav 		new_mp_entry->name = new_mp_entry->mp_params.cep.entry_name;
62606a99fe3SHajimu UMEMOTO 
62706a99fe3SHajimu UMEMOTO 		TAILQ_INIT(&new_mp_entry->ws_head);
62806a99fe3SHajimu UMEMOTO 		TAILQ_INIT(&new_mp_entry->rs_head);
62906a99fe3SHajimu UMEMOTO 
63006a99fe3SHajimu UMEMOTO 		new_mp_entry->get_time_func = the_cache->params.get_time_func;
63106a99fe3SHajimu UMEMOTO 		the_cache->entries[the_cache->entries_size++] =
63206a99fe3SHajimu UMEMOTO 			(struct cache_entry_ *)new_mp_entry;
63306a99fe3SHajimu UMEMOTO 		break;
63406a99fe3SHajimu UMEMOTO 	}
63506a99fe3SHajimu UMEMOTO 
63606a99fe3SHajimu UMEMOTO 
63706a99fe3SHajimu UMEMOTO 	qsort(the_cache->entries, the_cache->entries_size,
63806a99fe3SHajimu UMEMOTO 		sizeof(struct cache_entry_ *), entries_qsort_cmp_func);
63906a99fe3SHajimu UMEMOTO 
64006a99fe3SHajimu UMEMOTO 	TRACE_OUT(register_cache_entry);
64106a99fe3SHajimu UMEMOTO 	return (0);
64206a99fe3SHajimu UMEMOTO }
64306a99fe3SHajimu UMEMOTO 
64406a99fe3SHajimu UMEMOTO int
unregister_cache_entry(struct cache_ * the_cache,const char * entry_name)64506a99fe3SHajimu UMEMOTO unregister_cache_entry(struct cache_ *the_cache, const char *entry_name)
64606a99fe3SHajimu UMEMOTO {
64706a99fe3SHajimu UMEMOTO 	struct cache_entry_ **del_ent;
64806a99fe3SHajimu UMEMOTO 
64906a99fe3SHajimu UMEMOTO 	TRACE_IN(unregister_cache_entry);
65006a99fe3SHajimu UMEMOTO 	assert(the_cache != NULL);
65106a99fe3SHajimu UMEMOTO 
65206a99fe3SHajimu UMEMOTO 	del_ent = find_cache_entry_p(the_cache, entry_name);
65306a99fe3SHajimu UMEMOTO 	if (del_ent != NULL) {
65406a99fe3SHajimu UMEMOTO 		destroy_cache_entry(*del_ent);
65506a99fe3SHajimu UMEMOTO 		--the_cache->entries_size;
65606a99fe3SHajimu UMEMOTO 
65706a99fe3SHajimu UMEMOTO 		memmove(del_ent, del_ent + 1,
65806a99fe3SHajimu UMEMOTO 			(&(the_cache->entries[--the_cache->entries_size]) -
65906a99fe3SHajimu UMEMOTO 	    		del_ent) * sizeof(struct cache_entry_ *));
66006a99fe3SHajimu UMEMOTO 
66106a99fe3SHajimu UMEMOTO 		TRACE_OUT(unregister_cache_entry);
66206a99fe3SHajimu UMEMOTO 		return (0);
66306a99fe3SHajimu UMEMOTO 	} else {
66406a99fe3SHajimu UMEMOTO 		TRACE_OUT(unregister_cache_entry);
66506a99fe3SHajimu UMEMOTO 		return (-1);
66606a99fe3SHajimu UMEMOTO 	}
66706a99fe3SHajimu UMEMOTO }
66806a99fe3SHajimu UMEMOTO 
66906a99fe3SHajimu UMEMOTO struct cache_entry_ *
find_cache_entry(struct cache_ * the_cache,const char * entry_name)67006a99fe3SHajimu UMEMOTO find_cache_entry(struct cache_ *the_cache, const char *entry_name)
67106a99fe3SHajimu UMEMOTO {
67206a99fe3SHajimu UMEMOTO 	struct cache_entry_ **result;
67306a99fe3SHajimu UMEMOTO 
67406a99fe3SHajimu UMEMOTO 	TRACE_IN(find_cache_entry);
67506a99fe3SHajimu UMEMOTO 	result = find_cache_entry_p(the_cache, entry_name);
67606a99fe3SHajimu UMEMOTO 
67706a99fe3SHajimu UMEMOTO 	if (result == NULL) {
67806a99fe3SHajimu UMEMOTO 		TRACE_OUT(find_cache_entry);
67906a99fe3SHajimu UMEMOTO 		return (NULL);
68006a99fe3SHajimu UMEMOTO 	} else {
68106a99fe3SHajimu UMEMOTO 		TRACE_OUT(find_cache_entry);
68206a99fe3SHajimu UMEMOTO 		return (*result);
68306a99fe3SHajimu UMEMOTO 	}
68406a99fe3SHajimu UMEMOTO }
68506a99fe3SHajimu UMEMOTO 
68606a99fe3SHajimu UMEMOTO /*
68706a99fe3SHajimu UMEMOTO  * Tries to read the element with the specified key from the cache. If the
68806a99fe3SHajimu UMEMOTO  * value_size is too small, it will be filled with the proper number, and
68906a99fe3SHajimu UMEMOTO  * the user will need to call cache_read again with the value buffer, that
69006a99fe3SHajimu UMEMOTO  * is large enough.
69106a99fe3SHajimu UMEMOTO  * Function returns 0 on success, -1 on error, and -2 if the value_size is too
69206a99fe3SHajimu UMEMOTO  * small.
69306a99fe3SHajimu UMEMOTO  */
69406a99fe3SHajimu UMEMOTO int
cache_read(struct cache_entry_ * entry,const char * key,size_t key_size,char * value,size_t * value_size)69506a99fe3SHajimu UMEMOTO cache_read(struct cache_entry_ *entry, const char *key, size_t key_size,
69606a99fe3SHajimu UMEMOTO 	char *value, size_t *value_size)
69706a99fe3SHajimu UMEMOTO {
69806a99fe3SHajimu UMEMOTO 	struct cache_common_entry_	*common_entry;
69906a99fe3SHajimu UMEMOTO 	struct cache_ht_item_data_	item_data, *find_res;
70006a99fe3SHajimu UMEMOTO 	struct cache_ht_item_		*item;
70106a99fe3SHajimu UMEMOTO 	hashtable_index_t	hash;
70206a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *connected_item;
70306a99fe3SHajimu UMEMOTO 
70406a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_read);
70506a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
70606a99fe3SHajimu UMEMOTO 	assert(key != NULL);
70706a99fe3SHajimu UMEMOTO 	assert(value_size != NULL);
70806a99fe3SHajimu UMEMOTO 	assert(entry->params->entry_type == CET_COMMON);
70906a99fe3SHajimu UMEMOTO 
71006a99fe3SHajimu UMEMOTO 	common_entry = (struct cache_common_entry_ *)entry;
71106a99fe3SHajimu UMEMOTO 
71206a99fe3SHajimu UMEMOTO 	memset(&item_data, 0, sizeof(struct cache_ht_item_data_));
71306a99fe3SHajimu UMEMOTO 	/* can't avoid the cast here */
71406a99fe3SHajimu UMEMOTO 	item_data.key = (char *)key;
71506a99fe3SHajimu UMEMOTO 	item_data.key_size = key_size;
71606a99fe3SHajimu UMEMOTO 
71706a99fe3SHajimu UMEMOTO 	hash = HASHTABLE_CALCULATE_HASH(cache_ht_, &common_entry->items,
71806a99fe3SHajimu UMEMOTO 		&item_data);
71906a99fe3SHajimu UMEMOTO 	assert(hash < HASHTABLE_ENTRIES_COUNT(&common_entry->items));
72006a99fe3SHajimu UMEMOTO 
72106a99fe3SHajimu UMEMOTO 	item = HASHTABLE_GET_ENTRY(&(common_entry->items), hash);
72206a99fe3SHajimu UMEMOTO 	find_res = HASHTABLE_ENTRY_FIND(cache_ht_, item, &item_data);
72306a99fe3SHajimu UMEMOTO 	if (find_res == NULL) {
72406a99fe3SHajimu UMEMOTO 		TRACE_OUT(cache_read);
72506a99fe3SHajimu UMEMOTO 		return (-1);
72606a99fe3SHajimu UMEMOTO 	}
727a397989dSStefan Eßer 	/* pretend that entry was not found if confidence is below threshold*/
728a397989dSStefan Eßer 	if (find_res->confidence <
729a397989dSStefan Eßer 	    common_entry->common_params.confidence_threshold) {
730a397989dSStefan Eßer 		TRACE_OUT(cache_read);
731a397989dSStefan Eßer 		return (-1);
732a397989dSStefan Eßer 	}
73306a99fe3SHajimu UMEMOTO 
73406a99fe3SHajimu UMEMOTO 	if ((common_entry->common_params.max_lifetime.tv_sec != 0) ||
73506a99fe3SHajimu UMEMOTO 		(common_entry->common_params.max_lifetime.tv_usec != 0)) {
73606a99fe3SHajimu UMEMOTO 
73706a99fe3SHajimu UMEMOTO 		if (find_res->fifo_policy_item->last_request_time.tv_sec -
73806a99fe3SHajimu UMEMOTO 			find_res->fifo_policy_item->creation_time.tv_sec >
73906a99fe3SHajimu UMEMOTO 			common_entry->common_params.max_lifetime.tv_sec) {
74006a99fe3SHajimu UMEMOTO 
74106a99fe3SHajimu UMEMOTO 			free(find_res->key);
74206a99fe3SHajimu UMEMOTO 			free(find_res->value);
74306a99fe3SHajimu UMEMOTO 
74406a99fe3SHajimu UMEMOTO 			connected_item =
74506a99fe3SHajimu UMEMOTO 			    find_res->fifo_policy_item->connected_item;
74606a99fe3SHajimu UMEMOTO 			if (connected_item != NULL) {
74706a99fe3SHajimu UMEMOTO 				common_entry->policies[1]->remove_item_func(
74806a99fe3SHajimu UMEMOTO 					common_entry->policies[1],
74906a99fe3SHajimu UMEMOTO 			    		connected_item);
75006a99fe3SHajimu UMEMOTO 				common_entry->policies[1]->destroy_item_func(
75106a99fe3SHajimu UMEMOTO 					connected_item);
75206a99fe3SHajimu UMEMOTO 			}
75306a99fe3SHajimu UMEMOTO 
75406a99fe3SHajimu UMEMOTO 			common_entry->policies[0]->remove_item_func(
75506a99fe3SHajimu UMEMOTO 				common_entry->policies[0],
75606a99fe3SHajimu UMEMOTO 					find_res->fifo_policy_item);
75706a99fe3SHajimu UMEMOTO 			common_entry->policies[0]->destroy_item_func(
75806a99fe3SHajimu UMEMOTO 				find_res->fifo_policy_item);
75906a99fe3SHajimu UMEMOTO 
76006a99fe3SHajimu UMEMOTO 			HASHTABLE_ENTRY_REMOVE(cache_ht_, item, find_res);
76106a99fe3SHajimu UMEMOTO 			--common_entry->items_size;
76206a99fe3SHajimu UMEMOTO 		}
76306a99fe3SHajimu UMEMOTO 	}
76406a99fe3SHajimu UMEMOTO 
76506a99fe3SHajimu UMEMOTO 	if ((*value_size < find_res->value_size) || (value == NULL)) {
76606a99fe3SHajimu UMEMOTO 		*value_size = find_res->value_size;
76706a99fe3SHajimu UMEMOTO 		TRACE_OUT(cache_read);
76806a99fe3SHajimu UMEMOTO 		return (-2);
76906a99fe3SHajimu UMEMOTO 	}
77006a99fe3SHajimu UMEMOTO 
77106a99fe3SHajimu UMEMOTO 	*value_size = find_res->value_size;
77206a99fe3SHajimu UMEMOTO 	memcpy(value, find_res->value, find_res->value_size);
77306a99fe3SHajimu UMEMOTO 
77406a99fe3SHajimu UMEMOTO 	++find_res->fifo_policy_item->request_count;
77506a99fe3SHajimu UMEMOTO 	common_entry->get_time_func(
77606a99fe3SHajimu UMEMOTO 		&find_res->fifo_policy_item->last_request_time);
77706a99fe3SHajimu UMEMOTO 	common_entry->policies[0]->update_item_func(common_entry->policies[0],
77806a99fe3SHajimu UMEMOTO 		find_res->fifo_policy_item);
77906a99fe3SHajimu UMEMOTO 
78006a99fe3SHajimu UMEMOTO 	if (find_res->fifo_policy_item->connected_item != NULL) {
78106a99fe3SHajimu UMEMOTO 		connected_item = find_res->fifo_policy_item->connected_item;
78206a99fe3SHajimu UMEMOTO 		memcpy(&connected_item->last_request_time,
78306a99fe3SHajimu UMEMOTO 			&find_res->fifo_policy_item->last_request_time,
78406a99fe3SHajimu UMEMOTO 			sizeof(struct timeval));
78506a99fe3SHajimu UMEMOTO 		connected_item->request_count =
78606a99fe3SHajimu UMEMOTO 			find_res->fifo_policy_item->request_count;
78706a99fe3SHajimu UMEMOTO 
78806a99fe3SHajimu UMEMOTO 		common_entry->policies[1]->update_item_func(
78906a99fe3SHajimu UMEMOTO 			common_entry->policies[1], connected_item);
79006a99fe3SHajimu UMEMOTO 	}
79106a99fe3SHajimu UMEMOTO 
79206a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_read);
79306a99fe3SHajimu UMEMOTO 	return (0);
79406a99fe3SHajimu UMEMOTO }
79506a99fe3SHajimu UMEMOTO 
79606a99fe3SHajimu UMEMOTO /*
79706a99fe3SHajimu UMEMOTO  * Writes the value with the specified key into the cache entry.
79806a99fe3SHajimu UMEMOTO  * Functions returns 0 on success, and -1 on error.
79906a99fe3SHajimu UMEMOTO  */
80006a99fe3SHajimu UMEMOTO int
cache_write(struct cache_entry_ * entry,const char * key,size_t key_size,char const * value,size_t value_size)80106a99fe3SHajimu UMEMOTO cache_write(struct cache_entry_ *entry, const char *key, size_t key_size,
80206a99fe3SHajimu UMEMOTO     	char const *value, size_t value_size)
80306a99fe3SHajimu UMEMOTO {
80406a99fe3SHajimu UMEMOTO 	struct cache_common_entry_	*common_entry;
80506a99fe3SHajimu UMEMOTO 	struct cache_ht_item_data_	item_data, *find_res;
80606a99fe3SHajimu UMEMOTO 	struct cache_ht_item_		*item;
80706a99fe3SHajimu UMEMOTO 	hashtable_index_t	hash;
80806a99fe3SHajimu UMEMOTO 
80906a99fe3SHajimu UMEMOTO 	struct cache_policy_		*policy, *connected_policy;
81006a99fe3SHajimu UMEMOTO 	struct cache_policy_item_	*policy_item;
81106a99fe3SHajimu UMEMOTO 	struct cache_policy_item_	*connected_policy_item;
81206a99fe3SHajimu UMEMOTO 
81306a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_write);
81406a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
81506a99fe3SHajimu UMEMOTO 	assert(key != NULL);
81606a99fe3SHajimu UMEMOTO 	assert(value != NULL);
81706a99fe3SHajimu UMEMOTO 	assert(entry->params->entry_type == CET_COMMON);
81806a99fe3SHajimu UMEMOTO 
81906a99fe3SHajimu UMEMOTO 	common_entry = (struct cache_common_entry_ *)entry;
82006a99fe3SHajimu UMEMOTO 
82106a99fe3SHajimu UMEMOTO 	memset(&item_data, 0, sizeof(struct cache_ht_item_data_));
82206a99fe3SHajimu UMEMOTO 	/* can't avoid the cast here */
82306a99fe3SHajimu UMEMOTO 	item_data.key = (char *)key;
82406a99fe3SHajimu UMEMOTO 	item_data.key_size = key_size;
82506a99fe3SHajimu UMEMOTO 
82606a99fe3SHajimu UMEMOTO 	hash = HASHTABLE_CALCULATE_HASH(cache_ht_, &common_entry->items,
82706a99fe3SHajimu UMEMOTO 		&item_data);
82806a99fe3SHajimu UMEMOTO 	assert(hash < HASHTABLE_ENTRIES_COUNT(&common_entry->items));
82906a99fe3SHajimu UMEMOTO 
83006a99fe3SHajimu UMEMOTO 	item = HASHTABLE_GET_ENTRY(&(common_entry->items), hash);
83106a99fe3SHajimu UMEMOTO 	find_res = HASHTABLE_ENTRY_FIND(cache_ht_, item, &item_data);
83206a99fe3SHajimu UMEMOTO 	if (find_res != NULL) {
833a397989dSStefan Eßer 		if (find_res->confidence < common_entry->common_params.confidence_threshold) {
834a397989dSStefan Eßer 		  	/* duplicate entry is no error, if confidence is low */
835a397989dSStefan Eßer 			if ((find_res->value_size == value_size) &&
836a397989dSStefan Eßer 			    (memcmp(find_res->value, value, value_size) == 0)) {
837a397989dSStefan Eßer 				/* increase confidence on exact match (key and values) */
838a397989dSStefan Eßer 				find_res->confidence++;
839a397989dSStefan Eßer 			} else {
840a397989dSStefan Eßer 				/* create new entry with low confidence, if value changed */
841a397989dSStefan Eßer 				free(item_data.value);
842a397989dSStefan Eßer 				item_data.value = malloc(value_size);
843a397989dSStefan Eßer 				assert(item_data.value != NULL);
844a397989dSStefan Eßer 				memcpy(item_data.value, value, value_size);
845a397989dSStefan Eßer 				item_data.value_size = value_size;
846a397989dSStefan Eßer 				find_res->confidence = 1;
847a397989dSStefan Eßer 			}
848a397989dSStefan Eßer 			TRACE_OUT(cache_write);
849a397989dSStefan Eßer 			return (0);
850a397989dSStefan Eßer 		}
85106a99fe3SHajimu UMEMOTO 		TRACE_OUT(cache_write);
85206a99fe3SHajimu UMEMOTO 		return (-1);
85306a99fe3SHajimu UMEMOTO 	}
85406a99fe3SHajimu UMEMOTO 
8558eeaaffaSDag-Erling Smørgrav 	item_data.key = malloc(key_size);
85606a99fe3SHajimu UMEMOTO 	memcpy(item_data.key, key, key_size);
85706a99fe3SHajimu UMEMOTO 
8588eeaaffaSDag-Erling Smørgrav 	item_data.value = malloc(value_size);
85906a99fe3SHajimu UMEMOTO 	assert(item_data.value != NULL);
86006a99fe3SHajimu UMEMOTO 
86106a99fe3SHajimu UMEMOTO 	memcpy(item_data.value, value, value_size);
86206a99fe3SHajimu UMEMOTO 	item_data.value_size = value_size;
86306a99fe3SHajimu UMEMOTO 
864a397989dSStefan Eßer 	item_data.confidence = 1;
865a397989dSStefan Eßer 
86606a99fe3SHajimu UMEMOTO 	policy_item = common_entry->policies[0]->create_item_func();
86706a99fe3SHajimu UMEMOTO 	policy_item->key = item_data.key;
86806a99fe3SHajimu UMEMOTO 	policy_item->key_size = item_data.key_size;
86906a99fe3SHajimu UMEMOTO 	common_entry->get_time_func(&policy_item->creation_time);
87006a99fe3SHajimu UMEMOTO 
87106a99fe3SHajimu UMEMOTO 	if (common_entry->policies_size > 1) {
87206a99fe3SHajimu UMEMOTO 		connected_policy_item =
87306a99fe3SHajimu UMEMOTO 			common_entry->policies[1]->create_item_func();
87406a99fe3SHajimu UMEMOTO 		memcpy(&connected_policy_item->creation_time,
87506a99fe3SHajimu UMEMOTO 			&policy_item->creation_time,
87606a99fe3SHajimu UMEMOTO 			sizeof(struct timeval));
87706a99fe3SHajimu UMEMOTO 		connected_policy_item->key = policy_item->key;
87806a99fe3SHajimu UMEMOTO 		connected_policy_item->key_size = policy_item->key_size;
87906a99fe3SHajimu UMEMOTO 
88006a99fe3SHajimu UMEMOTO 		connected_policy_item->connected_item = policy_item;
88106a99fe3SHajimu UMEMOTO 		policy_item->connected_item = connected_policy_item;
88206a99fe3SHajimu UMEMOTO 	}
88306a99fe3SHajimu UMEMOTO 
88406a99fe3SHajimu UMEMOTO 	item_data.fifo_policy_item = policy_item;
88506a99fe3SHajimu UMEMOTO 
88606a99fe3SHajimu UMEMOTO 	common_entry->policies[0]->add_item_func(common_entry->policies[0],
88706a99fe3SHajimu UMEMOTO 		policy_item);
88806a99fe3SHajimu UMEMOTO 	if (common_entry->policies_size > 1)
88906a99fe3SHajimu UMEMOTO 		common_entry->policies[1]->add_item_func(
89006a99fe3SHajimu UMEMOTO 			common_entry->policies[1], connected_policy_item);
89106a99fe3SHajimu UMEMOTO 
89206a99fe3SHajimu UMEMOTO 	HASHTABLE_ENTRY_STORE(cache_ht_, item, &item_data);
89306a99fe3SHajimu UMEMOTO 	++common_entry->items_size;
89406a99fe3SHajimu UMEMOTO 
89506a99fe3SHajimu UMEMOTO 	if ((common_entry->common_params.max_elemsize != 0) &&
89606a99fe3SHajimu UMEMOTO 		(common_entry->items_size >
89706a99fe3SHajimu UMEMOTO 		common_entry->common_params.max_elemsize)) {
89806a99fe3SHajimu UMEMOTO 		if (common_entry->policies_size > 1) {
89906a99fe3SHajimu UMEMOTO 			policy = common_entry->policies[1];
90006a99fe3SHajimu UMEMOTO 			connected_policy = common_entry->policies[0];
90106a99fe3SHajimu UMEMOTO 		} else {
90206a99fe3SHajimu UMEMOTO 			policy = common_entry->policies[0];
90306a99fe3SHajimu UMEMOTO 			connected_policy = NULL;
90406a99fe3SHajimu UMEMOTO 		}
90506a99fe3SHajimu UMEMOTO 
90606a99fe3SHajimu UMEMOTO 		flush_cache_policy(common_entry, policy, connected_policy,
90706a99fe3SHajimu UMEMOTO 			cache_elemsize_common_continue_func);
90806a99fe3SHajimu UMEMOTO 	}
90906a99fe3SHajimu UMEMOTO 
91006a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_write);
91106a99fe3SHajimu UMEMOTO 	return (0);
91206a99fe3SHajimu UMEMOTO }
91306a99fe3SHajimu UMEMOTO 
91406a99fe3SHajimu UMEMOTO /*
91506a99fe3SHajimu UMEMOTO  * Initializes the write session for the specified multipart entry. This
91606a99fe3SHajimu UMEMOTO  * session then should be filled with data either committed or abandoned by
91706a99fe3SHajimu UMEMOTO  * using close_cache_mp_write_session or abandon_cache_mp_write_session
91806a99fe3SHajimu UMEMOTO  * respectively.
91906a99fe3SHajimu UMEMOTO  * Returns NULL on errors (when there are too many opened write sessions for
92006a99fe3SHajimu UMEMOTO  * the entry).
92106a99fe3SHajimu UMEMOTO  */
92206a99fe3SHajimu UMEMOTO struct cache_mp_write_session_ *
open_cache_mp_write_session(struct cache_entry_ * entry)92306a99fe3SHajimu UMEMOTO open_cache_mp_write_session(struct cache_entry_ *entry)
92406a99fe3SHajimu UMEMOTO {
92506a99fe3SHajimu UMEMOTO 	struct cache_mp_entry_	*mp_entry;
92606a99fe3SHajimu UMEMOTO 	struct cache_mp_write_session_	*retval;
92706a99fe3SHajimu UMEMOTO 
92806a99fe3SHajimu UMEMOTO 	TRACE_IN(open_cache_mp_write_session);
92906a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
93006a99fe3SHajimu UMEMOTO 	assert(entry->params->entry_type == CET_MULTIPART);
93106a99fe3SHajimu UMEMOTO 	mp_entry = (struct cache_mp_entry_ *)entry;
93206a99fe3SHajimu UMEMOTO 
93306a99fe3SHajimu UMEMOTO 	if ((mp_entry->mp_params.max_sessions > 0) &&
93406a99fe3SHajimu UMEMOTO 		(mp_entry->ws_size == mp_entry->mp_params.max_sessions)) {
93506a99fe3SHajimu UMEMOTO 		TRACE_OUT(open_cache_mp_write_session);
93606a99fe3SHajimu UMEMOTO 		return (NULL);
93706a99fe3SHajimu UMEMOTO 	}
93806a99fe3SHajimu UMEMOTO 
9398eeaaffaSDag-Erling Smørgrav 	retval = calloc(1,
9408eeaaffaSDag-Erling Smørgrav 		sizeof(*retval));
94106a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
94206a99fe3SHajimu UMEMOTO 
94306a99fe3SHajimu UMEMOTO 	TAILQ_INIT(&retval->items);
94406a99fe3SHajimu UMEMOTO 	retval->parent_entry = mp_entry;
94506a99fe3SHajimu UMEMOTO 
94606a99fe3SHajimu UMEMOTO 	TAILQ_INSERT_HEAD(&mp_entry->ws_head, retval, entries);
94706a99fe3SHajimu UMEMOTO 	++mp_entry->ws_size;
94806a99fe3SHajimu UMEMOTO 
94906a99fe3SHajimu UMEMOTO 	TRACE_OUT(open_cache_mp_write_session);
95006a99fe3SHajimu UMEMOTO 	return (retval);
95106a99fe3SHajimu UMEMOTO }
95206a99fe3SHajimu UMEMOTO 
95306a99fe3SHajimu UMEMOTO /*
95406a99fe3SHajimu UMEMOTO  * Writes data to the specified session. Return 0 on success and -1 on errors
95506a99fe3SHajimu UMEMOTO  * (when write session size limit is exceeded).
95606a99fe3SHajimu UMEMOTO  */
95706a99fe3SHajimu UMEMOTO int
cache_mp_write(struct cache_mp_write_session_ * ws,char * data,size_t data_size)95806a99fe3SHajimu UMEMOTO cache_mp_write(struct cache_mp_write_session_ *ws, char *data,
95906a99fe3SHajimu UMEMOTO 	size_t data_size)
96006a99fe3SHajimu UMEMOTO {
96106a99fe3SHajimu UMEMOTO 	struct cache_mp_data_item_	*new_item;
96206a99fe3SHajimu UMEMOTO 
96306a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_mp_write);
96406a99fe3SHajimu UMEMOTO 	assert(ws != NULL);
96506a99fe3SHajimu UMEMOTO 	assert(ws->parent_entry != NULL);
96606a99fe3SHajimu UMEMOTO 	assert(ws->parent_entry->params->entry_type == CET_MULTIPART);
96706a99fe3SHajimu UMEMOTO 
96806a99fe3SHajimu UMEMOTO 	if ((ws->parent_entry->mp_params.max_elemsize > 0) &&
96906a99fe3SHajimu UMEMOTO 		(ws->parent_entry->mp_params.max_elemsize == ws->items_size)) {
97006a99fe3SHajimu UMEMOTO 		TRACE_OUT(cache_mp_write);
97106a99fe3SHajimu UMEMOTO 		return (-1);
97206a99fe3SHajimu UMEMOTO 	}
97306a99fe3SHajimu UMEMOTO 
9748eeaaffaSDag-Erling Smørgrav 	new_item = calloc(1,
9758eeaaffaSDag-Erling Smørgrav 		sizeof(*new_item));
97606a99fe3SHajimu UMEMOTO 	assert(new_item != NULL);
97706a99fe3SHajimu UMEMOTO 
9788eeaaffaSDag-Erling Smørgrav 	new_item->value = malloc(data_size);
97906a99fe3SHajimu UMEMOTO 	assert(new_item->value != NULL);
98006a99fe3SHajimu UMEMOTO 	memcpy(new_item->value, data, data_size);
98106a99fe3SHajimu UMEMOTO 	new_item->value_size = data_size;
98206a99fe3SHajimu UMEMOTO 
98306a99fe3SHajimu UMEMOTO 	TAILQ_INSERT_TAIL(&ws->items, new_item, entries);
98406a99fe3SHajimu UMEMOTO 	++ws->items_size;
98506a99fe3SHajimu UMEMOTO 
98606a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_mp_write);
98706a99fe3SHajimu UMEMOTO 	return (0);
98806a99fe3SHajimu UMEMOTO }
98906a99fe3SHajimu UMEMOTO 
99006a99fe3SHajimu UMEMOTO /*
99106a99fe3SHajimu UMEMOTO  * Abandons the write session and frees all the connected resources.
99206a99fe3SHajimu UMEMOTO  */
99306a99fe3SHajimu UMEMOTO void
abandon_cache_mp_write_session(struct cache_mp_write_session_ * ws)99406a99fe3SHajimu UMEMOTO abandon_cache_mp_write_session(struct cache_mp_write_session_ *ws)
99506a99fe3SHajimu UMEMOTO {
99606a99fe3SHajimu UMEMOTO 
99706a99fe3SHajimu UMEMOTO 	TRACE_IN(abandon_cache_mp_write_session);
99806a99fe3SHajimu UMEMOTO 	assert(ws != NULL);
99906a99fe3SHajimu UMEMOTO 	assert(ws->parent_entry != NULL);
100006a99fe3SHajimu UMEMOTO 	assert(ws->parent_entry->params->entry_type == CET_MULTIPART);
100106a99fe3SHajimu UMEMOTO 
100206a99fe3SHajimu UMEMOTO 	TAILQ_REMOVE(&ws->parent_entry->ws_head, ws, entries);
100306a99fe3SHajimu UMEMOTO 	--ws->parent_entry->ws_size;
100406a99fe3SHajimu UMEMOTO 
100506a99fe3SHajimu UMEMOTO 	destroy_cache_mp_write_session(ws);
100606a99fe3SHajimu UMEMOTO 	TRACE_OUT(abandon_cache_mp_write_session);
100706a99fe3SHajimu UMEMOTO }
100806a99fe3SHajimu UMEMOTO 
100906a99fe3SHajimu UMEMOTO /*
101006a99fe3SHajimu UMEMOTO  * Commits the session to the entry, for which it was created.
101106a99fe3SHajimu UMEMOTO  */
101206a99fe3SHajimu UMEMOTO void
close_cache_mp_write_session(struct cache_mp_write_session_ * ws)101306a99fe3SHajimu UMEMOTO close_cache_mp_write_session(struct cache_mp_write_session_ *ws)
101406a99fe3SHajimu UMEMOTO {
101506a99fe3SHajimu UMEMOTO 
101606a99fe3SHajimu UMEMOTO 	TRACE_IN(close_cache_mp_write_session);
101706a99fe3SHajimu UMEMOTO 	assert(ws != NULL);
101806a99fe3SHajimu UMEMOTO 	assert(ws->parent_entry != NULL);
101906a99fe3SHajimu UMEMOTO 	assert(ws->parent_entry->params->entry_type == CET_MULTIPART);
102006a99fe3SHajimu UMEMOTO 
102106a99fe3SHajimu UMEMOTO 	TAILQ_REMOVE(&ws->parent_entry->ws_head, ws, entries);
102206a99fe3SHajimu UMEMOTO 	--ws->parent_entry->ws_size;
102306a99fe3SHajimu UMEMOTO 
102406a99fe3SHajimu UMEMOTO 	if (ws->parent_entry->completed_write_session == NULL) {
102506a99fe3SHajimu UMEMOTO 		/*
102606a99fe3SHajimu UMEMOTO 		 * If there is no completed session yet, this will be the one
102706a99fe3SHajimu UMEMOTO 		 */
102806a99fe3SHajimu UMEMOTO 		ws->parent_entry->get_time_func(
102906a99fe3SHajimu UMEMOTO 	    		&ws->parent_entry->creation_time);
103006a99fe3SHajimu UMEMOTO 		ws->parent_entry->completed_write_session = ws;
103106a99fe3SHajimu UMEMOTO 	} else {
103206a99fe3SHajimu UMEMOTO 		/*
103306a99fe3SHajimu UMEMOTO 		 * If there is a completed session, then we'll save our session
103406a99fe3SHajimu UMEMOTO 		 * as a pending session. If there is already a pending session,
103506a99fe3SHajimu UMEMOTO 		 * it would be destroyed.
103606a99fe3SHajimu UMEMOTO 		 */
103706a99fe3SHajimu UMEMOTO 		if (ws->parent_entry->pending_write_session != NULL)
103806a99fe3SHajimu UMEMOTO 			destroy_cache_mp_write_session(
103906a99fe3SHajimu UMEMOTO 				ws->parent_entry->pending_write_session);
104006a99fe3SHajimu UMEMOTO 
104106a99fe3SHajimu UMEMOTO 		ws->parent_entry->pending_write_session = ws;
104206a99fe3SHajimu UMEMOTO 	}
104306a99fe3SHajimu UMEMOTO 	TRACE_OUT(close_cache_mp_write_session);
104406a99fe3SHajimu UMEMOTO }
104506a99fe3SHajimu UMEMOTO 
104606a99fe3SHajimu UMEMOTO /*
104706a99fe3SHajimu UMEMOTO  * Opens read session for the specified entry. Returns NULL on errors (when
104806a99fe3SHajimu UMEMOTO  * there are no data in the entry, or the data are obsolete).
104906a99fe3SHajimu UMEMOTO  */
105006a99fe3SHajimu UMEMOTO struct cache_mp_read_session_ *
open_cache_mp_read_session(struct cache_entry_ * entry)105106a99fe3SHajimu UMEMOTO open_cache_mp_read_session(struct cache_entry_ *entry)
105206a99fe3SHajimu UMEMOTO {
105306a99fe3SHajimu UMEMOTO 	struct cache_mp_entry_			*mp_entry;
105406a99fe3SHajimu UMEMOTO 	struct cache_mp_read_session_	*retval;
105506a99fe3SHajimu UMEMOTO 
105606a99fe3SHajimu UMEMOTO 	TRACE_IN(open_cache_mp_read_session);
105706a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
105806a99fe3SHajimu UMEMOTO 	assert(entry->params->entry_type == CET_MULTIPART);
105906a99fe3SHajimu UMEMOTO 	mp_entry = (struct cache_mp_entry_ *)entry;
106006a99fe3SHajimu UMEMOTO 
106106a99fe3SHajimu UMEMOTO 	if (mp_entry->completed_write_session == NULL) {
106206a99fe3SHajimu UMEMOTO 		TRACE_OUT(open_cache_mp_read_session);
106306a99fe3SHajimu UMEMOTO 		return (NULL);
106406a99fe3SHajimu UMEMOTO 	}
106506a99fe3SHajimu UMEMOTO 
106606a99fe3SHajimu UMEMOTO 	if ((mp_entry->mp_params.max_lifetime.tv_sec != 0)
106706a99fe3SHajimu UMEMOTO 		|| (mp_entry->mp_params.max_lifetime.tv_usec != 0)) {
106806a99fe3SHajimu UMEMOTO 		if (mp_entry->last_request_time.tv_sec -
106906a99fe3SHajimu UMEMOTO 			mp_entry->last_request_time.tv_sec >
107006a99fe3SHajimu UMEMOTO 			mp_entry->mp_params.max_lifetime.tv_sec) {
107106a99fe3SHajimu UMEMOTO 			flush_cache_entry(entry);
107206a99fe3SHajimu UMEMOTO 			TRACE_OUT(open_cache_mp_read_session);
107306a99fe3SHajimu UMEMOTO 			return (NULL);
107406a99fe3SHajimu UMEMOTO 		}
107506a99fe3SHajimu UMEMOTO 	}
107606a99fe3SHajimu UMEMOTO 
10778eeaaffaSDag-Erling Smørgrav 	retval = calloc(1,
10788eeaaffaSDag-Erling Smørgrav 		sizeof(*retval));
107906a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
108006a99fe3SHajimu UMEMOTO 
108106a99fe3SHajimu UMEMOTO 	retval->parent_entry = mp_entry;
108206a99fe3SHajimu UMEMOTO 	retval->current_item = TAILQ_FIRST(
108306a99fe3SHajimu UMEMOTO 		&mp_entry->completed_write_session->items);
108406a99fe3SHajimu UMEMOTO 
108506a99fe3SHajimu UMEMOTO 	TAILQ_INSERT_HEAD(&mp_entry->rs_head, retval, entries);
108606a99fe3SHajimu UMEMOTO 	++mp_entry->rs_size;
108706a99fe3SHajimu UMEMOTO 
108806a99fe3SHajimu UMEMOTO 	mp_entry->get_time_func(&mp_entry->last_request_time);
108906a99fe3SHajimu UMEMOTO 	TRACE_OUT(open_cache_mp_read_session);
109006a99fe3SHajimu UMEMOTO 	return (retval);
109106a99fe3SHajimu UMEMOTO }
109206a99fe3SHajimu UMEMOTO 
109306a99fe3SHajimu UMEMOTO /*
109406a99fe3SHajimu UMEMOTO  * Reads the data from the read session - step by step.
109506a99fe3SHajimu UMEMOTO  * Returns 0 on success, -1 on error (when there are no more data), and -2 if
109606a99fe3SHajimu UMEMOTO  * the data_size is too small.  In the last case, data_size would be filled
109706a99fe3SHajimu UMEMOTO  * the proper value.
109806a99fe3SHajimu UMEMOTO  */
109906a99fe3SHajimu UMEMOTO int
cache_mp_read(struct cache_mp_read_session_ * rs,char * data,size_t * data_size)110006a99fe3SHajimu UMEMOTO cache_mp_read(struct cache_mp_read_session_ *rs, char *data, size_t *data_size)
110106a99fe3SHajimu UMEMOTO {
110206a99fe3SHajimu UMEMOTO 
110306a99fe3SHajimu UMEMOTO 	TRACE_IN(cache_mp_read);
110406a99fe3SHajimu UMEMOTO 	assert(rs != NULL);
110506a99fe3SHajimu UMEMOTO 
110606a99fe3SHajimu UMEMOTO 	if (rs->current_item == NULL) {
110706a99fe3SHajimu UMEMOTO 		TRACE_OUT(cache_mp_read);
110806a99fe3SHajimu UMEMOTO 		return (-1);
110906a99fe3SHajimu UMEMOTO 	}
111006a99fe3SHajimu UMEMOTO 
111106a99fe3SHajimu UMEMOTO 	if (rs->current_item->value_size > *data_size) {
111206a99fe3SHajimu UMEMOTO 		*data_size = rs->current_item->value_size;
111306a99fe3SHajimu UMEMOTO 		if (data == NULL) {
111406a99fe3SHajimu UMEMOTO 			TRACE_OUT(cache_mp_read);
111506a99fe3SHajimu UMEMOTO 			return (0);
111606a99fe3SHajimu UMEMOTO 		}
111706a99fe3SHajimu UMEMOTO 
111806a99fe3SHajimu UMEMOTO 		TRACE_OUT(cache_mp_read);
111906a99fe3SHajimu UMEMOTO 		return (-2);
112006a99fe3SHajimu UMEMOTO 	}
112106a99fe3SHajimu UMEMOTO 
112206a99fe3SHajimu UMEMOTO 	*data_size = rs->current_item->value_size;
112306a99fe3SHajimu UMEMOTO 	memcpy(data, rs->current_item->value, rs->current_item->value_size);
112406a99fe3SHajimu UMEMOTO 	rs->current_item = TAILQ_NEXT(rs->current_item, entries);
112506a99fe3SHajimu UMEMOTO 
112606a99fe3SHajimu UMEMOTO 	TRACE_OUT(cache_mp_read);
112706a99fe3SHajimu UMEMOTO 	return (0);
112806a99fe3SHajimu UMEMOTO }
112906a99fe3SHajimu UMEMOTO 
113006a99fe3SHajimu UMEMOTO /*
113106a99fe3SHajimu UMEMOTO  * Closes the read session. If there are no more read sessions and there is
113206a99fe3SHajimu UMEMOTO  * a pending write session, it will be committed and old
113306a99fe3SHajimu UMEMOTO  * completed_write_session will be destroyed.
113406a99fe3SHajimu UMEMOTO  */
113506a99fe3SHajimu UMEMOTO void
close_cache_mp_read_session(struct cache_mp_read_session_ * rs)113606a99fe3SHajimu UMEMOTO close_cache_mp_read_session(struct cache_mp_read_session_ *rs)
113706a99fe3SHajimu UMEMOTO {
113806a99fe3SHajimu UMEMOTO 
113906a99fe3SHajimu UMEMOTO 	TRACE_IN(close_cache_mp_read_session);
114006a99fe3SHajimu UMEMOTO 	assert(rs != NULL);
114106a99fe3SHajimu UMEMOTO 	assert(rs->parent_entry != NULL);
114206a99fe3SHajimu UMEMOTO 
114306a99fe3SHajimu UMEMOTO 	TAILQ_REMOVE(&rs->parent_entry->rs_head, rs, entries);
114406a99fe3SHajimu UMEMOTO 	--rs->parent_entry->rs_size;
114506a99fe3SHajimu UMEMOTO 
114606a99fe3SHajimu UMEMOTO 	if ((rs->parent_entry->rs_size == 0) &&
114706a99fe3SHajimu UMEMOTO 		(rs->parent_entry->pending_write_session != NULL)) {
114806a99fe3SHajimu UMEMOTO 		destroy_cache_mp_write_session(
114906a99fe3SHajimu UMEMOTO 			rs->parent_entry->completed_write_session);
115006a99fe3SHajimu UMEMOTO 		rs->parent_entry->completed_write_session =
115106a99fe3SHajimu UMEMOTO 			rs->parent_entry->pending_write_session;
115206a99fe3SHajimu UMEMOTO 		rs->parent_entry->pending_write_session = NULL;
115306a99fe3SHajimu UMEMOTO 	}
115406a99fe3SHajimu UMEMOTO 
115506a99fe3SHajimu UMEMOTO 	destroy_cache_mp_read_session(rs);
115606a99fe3SHajimu UMEMOTO 	TRACE_OUT(close_cache_mp_read_session);
115706a99fe3SHajimu UMEMOTO }
115806a99fe3SHajimu UMEMOTO 
115906a99fe3SHajimu UMEMOTO int
transform_cache_entry(struct cache_entry_ * entry,enum cache_transformation_t transformation)116006a99fe3SHajimu UMEMOTO transform_cache_entry(struct cache_entry_ *entry,
116106a99fe3SHajimu UMEMOTO 	enum cache_transformation_t transformation)
116206a99fe3SHajimu UMEMOTO {
116306a99fe3SHajimu UMEMOTO 
116406a99fe3SHajimu UMEMOTO 	TRACE_IN(transform_cache_entry);
116506a99fe3SHajimu UMEMOTO 	switch (transformation) {
116606a99fe3SHajimu UMEMOTO 	case CTT_CLEAR:
116706a99fe3SHajimu UMEMOTO 		clear_cache_entry(entry);
116806a99fe3SHajimu UMEMOTO 		TRACE_OUT(transform_cache_entry);
116906a99fe3SHajimu UMEMOTO 		return (0);
117006a99fe3SHajimu UMEMOTO 	case CTT_FLUSH:
117106a99fe3SHajimu UMEMOTO 		flush_cache_entry(entry);
117206a99fe3SHajimu UMEMOTO 		TRACE_OUT(transform_cache_entry);
117306a99fe3SHajimu UMEMOTO 		return (0);
117406a99fe3SHajimu UMEMOTO 	default:
117506a99fe3SHajimu UMEMOTO 		TRACE_OUT(transform_cache_entry);
117606a99fe3SHajimu UMEMOTO 		return (-1);
117706a99fe3SHajimu UMEMOTO 	}
117806a99fe3SHajimu UMEMOTO }
117906a99fe3SHajimu UMEMOTO 
118006a99fe3SHajimu UMEMOTO int
transform_cache_entry_part(struct cache_entry_ * entry,enum cache_transformation_t transformation,const char * key_part,size_t key_part_size,enum part_position_t part_position)118106a99fe3SHajimu UMEMOTO transform_cache_entry_part(struct cache_entry_ *entry,
118206a99fe3SHajimu UMEMOTO 	enum cache_transformation_t transformation, const char *key_part,
118306a99fe3SHajimu UMEMOTO 	size_t key_part_size, enum part_position_t part_position)
118406a99fe3SHajimu UMEMOTO {
118506a99fe3SHajimu UMEMOTO 	struct cache_common_entry_ *common_entry;
118606a99fe3SHajimu UMEMOTO 	struct cache_ht_item_ *ht_item;
118706a99fe3SHajimu UMEMOTO 	struct cache_ht_item_data_ *ht_item_data, ht_key;
118806a99fe3SHajimu UMEMOTO 
118906a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *item, *connected_item;
119006a99fe3SHajimu UMEMOTO 
119106a99fe3SHajimu UMEMOTO 	TRACE_IN(transform_cache_entry_part);
119206a99fe3SHajimu UMEMOTO 	if (entry->params->entry_type != CET_COMMON) {
119306a99fe3SHajimu UMEMOTO 		TRACE_OUT(transform_cache_entry_part);
119406a99fe3SHajimu UMEMOTO 		return (-1);
119506a99fe3SHajimu UMEMOTO 	}
119606a99fe3SHajimu UMEMOTO 
119706a99fe3SHajimu UMEMOTO 	if (transformation != CTT_CLEAR) {
119806a99fe3SHajimu UMEMOTO 		TRACE_OUT(transform_cache_entry_part);
119906a99fe3SHajimu UMEMOTO 		return (-1);
120006a99fe3SHajimu UMEMOTO 	}
120106a99fe3SHajimu UMEMOTO 
120206a99fe3SHajimu UMEMOTO 	memset(&ht_key, 0, sizeof(struct cache_ht_item_data_));
120306a99fe3SHajimu UMEMOTO 	ht_key.key = (char *)key_part;	/* can't avoid casting here */
120406a99fe3SHajimu UMEMOTO 	ht_key.key_size = key_part_size;
120506a99fe3SHajimu UMEMOTO 
120606a99fe3SHajimu UMEMOTO 	common_entry = (struct cache_common_entry_ *)entry;
120706a99fe3SHajimu UMEMOTO 	HASHTABLE_FOREACH(&(common_entry->items), ht_item) {
120806a99fe3SHajimu UMEMOTO 		do {
120906a99fe3SHajimu UMEMOTO 			ht_item_data = HASHTABLE_ENTRY_FIND_SPECIAL(cache_ht_,
121006a99fe3SHajimu UMEMOTO 				ht_item, &ht_key,
121106a99fe3SHajimu UMEMOTO 				ht_items_fixed_size_left_cmp_func);
121206a99fe3SHajimu UMEMOTO 
121306a99fe3SHajimu UMEMOTO 			if (ht_item_data != NULL) {
121406a99fe3SHajimu UMEMOTO 			    item = ht_item_data->fifo_policy_item;
121506a99fe3SHajimu UMEMOTO 			    connected_item = item->connected_item;
121606a99fe3SHajimu UMEMOTO 
121706a99fe3SHajimu UMEMOTO 			    common_entry->policies[0]->remove_item_func(
121806a99fe3SHajimu UMEMOTO 				common_entry->policies[0],
121906a99fe3SHajimu UMEMOTO 				item);
122006a99fe3SHajimu UMEMOTO 
122106a99fe3SHajimu UMEMOTO 			    free(ht_item_data->key);
122206a99fe3SHajimu UMEMOTO 			    free(ht_item_data->value);
122306a99fe3SHajimu UMEMOTO 			    HASHTABLE_ENTRY_REMOVE(cache_ht_, ht_item,
122406a99fe3SHajimu UMEMOTO 				ht_item_data);
122506a99fe3SHajimu UMEMOTO 			    --common_entry->items_size;
122606a99fe3SHajimu UMEMOTO 
122706a99fe3SHajimu UMEMOTO 			    common_entry->policies[0]->destroy_item_func(
122806a99fe3SHajimu UMEMOTO 				item);
122906a99fe3SHajimu UMEMOTO 			    if (common_entry->policies_size == 2) {
123006a99fe3SHajimu UMEMOTO 				common_entry->policies[1]->remove_item_func(
123106a99fe3SHajimu UMEMOTO 				    common_entry->policies[1],
123206a99fe3SHajimu UMEMOTO 				    connected_item);
123306a99fe3SHajimu UMEMOTO 				common_entry->policies[1]->destroy_item_func(
123406a99fe3SHajimu UMEMOTO 				    connected_item);
123506a99fe3SHajimu UMEMOTO 			    }
123606a99fe3SHajimu UMEMOTO 			}
123706a99fe3SHajimu UMEMOTO 		} while (ht_item_data != NULL);
123806a99fe3SHajimu UMEMOTO 	}
123906a99fe3SHajimu UMEMOTO 
124006a99fe3SHajimu UMEMOTO 	TRACE_OUT(transform_cache_entry_part);
124106a99fe3SHajimu UMEMOTO 	return (0);
124206a99fe3SHajimu UMEMOTO }
1243