xref: /freebsd/usr.sbin/nscd/cachelib.h (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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 
27db1bdf2bSMichael Bushkov #ifndef __NSCD_CACHELIB_H__
28db1bdf2bSMichael Bushkov #define __NSCD_CACHELIB_H__
2906a99fe3SHajimu UMEMOTO 
3006a99fe3SHajimu UMEMOTO #include "hashtable.h"
3106a99fe3SHajimu UMEMOTO #include "cacheplcs.h"
3206a99fe3SHajimu UMEMOTO 
3306a99fe3SHajimu UMEMOTO enum cache_entry_t	{
3406a99fe3SHajimu UMEMOTO 	CET_COMMON = 0,	/* cache item is atomic */
3506a99fe3SHajimu UMEMOTO 	CET_MULTIPART	/* cache item is formed part by part */
3606a99fe3SHajimu UMEMOTO };
3706a99fe3SHajimu UMEMOTO 
3806a99fe3SHajimu UMEMOTO enum cache_transformation_t {
3906a99fe3SHajimu UMEMOTO 	CTT_FLUSH = 0,	/* flush the cache - delete all obsolete items */
4006a99fe3SHajimu UMEMOTO 	CTT_CLEAR = 1	/* delete all items in the cache */
4106a99fe3SHajimu UMEMOTO };
4206a99fe3SHajimu UMEMOTO 
4306a99fe3SHajimu UMEMOTO /* cache deletion policy type enum */
4406a99fe3SHajimu UMEMOTO enum cache_policy_t {
4506a99fe3SHajimu UMEMOTO 	CPT_FIFO = 0, 	/* first-in first-out */
4606a99fe3SHajimu UMEMOTO 	CPT_LRU = 1,	/* least recently used */
4706a99fe3SHajimu UMEMOTO 	CPT_LFU = 2 	/* least frequently used */
4806a99fe3SHajimu UMEMOTO };
4906a99fe3SHajimu UMEMOTO 
5006a99fe3SHajimu UMEMOTO /* multipart sessions can be used for reading and writing */
5106a99fe3SHajimu UMEMOTO enum cache_mp_session_t {
5206a99fe3SHajimu UMEMOTO 	CMPT_READ_SESSION,
5306a99fe3SHajimu UMEMOTO 	CMPT_WRITE_SESSION
5406a99fe3SHajimu UMEMOTO };
5506a99fe3SHajimu UMEMOTO 
5606a99fe3SHajimu UMEMOTO /*
5706a99fe3SHajimu UMEMOTO  * When doing partial transformations of entries (which are applied for
5806a99fe3SHajimu UMEMOTO  * elements with keys, that contain specified buffer in its left or
5906a99fe3SHajimu UMEMOTO  * right part), this enum will show the needed position of the key part.
6006a99fe3SHajimu UMEMOTO  */
6106a99fe3SHajimu UMEMOTO enum part_position_t {
6206a99fe3SHajimu UMEMOTO 	KPPT_LEFT,
6306a99fe3SHajimu UMEMOTO 	KPPT_RIGHT
6406a99fe3SHajimu UMEMOTO };
6506a99fe3SHajimu UMEMOTO 
6606a99fe3SHajimu UMEMOTO /* num_levels attribute is obsolete, i think - user can always emulate it
6706a99fe3SHajimu UMEMOTO  * by using one entry.
6806a99fe3SHajimu UMEMOTO  * get_time_func is needed to have the clocks-independent counter
6906a99fe3SHajimu UMEMOTO  */
70d2432adbSDag-Erling Smørgrav struct cache_params {
7106a99fe3SHajimu UMEMOTO 	void	(*get_time_func)(struct timeval *);
7206a99fe3SHajimu UMEMOTO };
7306a99fe3SHajimu UMEMOTO 
7406a99fe3SHajimu UMEMOTO /*
7506a99fe3SHajimu UMEMOTO  * base structure - normal_cache_entry_params and multipart_cache_entry_params
7606a99fe3SHajimu UMEMOTO  * are "inherited" from it
7706a99fe3SHajimu UMEMOTO  */
78d2432adbSDag-Erling Smørgrav struct cache_entry_params {
7906a99fe3SHajimu UMEMOTO 	enum cache_entry_t entry_type;
8006a99fe3SHajimu UMEMOTO 	char	*entry_name;
8106a99fe3SHajimu UMEMOTO };
8206a99fe3SHajimu UMEMOTO 
8306a99fe3SHajimu UMEMOTO /* params, used for most entries */
84d2432adbSDag-Erling Smørgrav struct common_cache_entry_params {
8527f2bc9eSDag-Erling Smørgrav 	struct cache_entry_params cep;
8606a99fe3SHajimu UMEMOTO 
8706a99fe3SHajimu UMEMOTO 	size_t	cache_entries_size;
8806a99fe3SHajimu UMEMOTO 
8906a99fe3SHajimu UMEMOTO 	size_t	max_elemsize;		/* if 0 then no check is made */
9006a99fe3SHajimu UMEMOTO 	size_t	satisf_elemsize;	/* if entry size is exceeded,
9106a99fe3SHajimu UMEMOTO 					 * this number of elements will be left,
9206a99fe3SHajimu UMEMOTO 					 * others will be deleted */
93*a397989dSStefan Eßer 	int	confidence_threshold;	/* number matching replies required */
9406a99fe3SHajimu UMEMOTO 	struct timeval	max_lifetime;	/* if 0 then no check is made */
9506a99fe3SHajimu UMEMOTO 	enum cache_policy_t policy;	/* policy used for transformations */
9606a99fe3SHajimu UMEMOTO };
9706a99fe3SHajimu UMEMOTO 
9806a99fe3SHajimu UMEMOTO /* params, used for multipart entries */
99d2432adbSDag-Erling Smørgrav struct	mp_cache_entry_params {
10027f2bc9eSDag-Erling Smørgrav 	struct cache_entry_params cep;
10106a99fe3SHajimu UMEMOTO 
10206a99fe3SHajimu UMEMOTO 	/* unique fields */
10306a99fe3SHajimu UMEMOTO 	size_t	max_elemsize;	/* if 0 then no check is made */
10406a99fe3SHajimu UMEMOTO 	size_t	max_sessions;	/* maximum number of active sessions */
10506a99fe3SHajimu UMEMOTO 
10606a99fe3SHajimu UMEMOTO 	struct timeval	max_lifetime;	/* maximum elements lifetime */
10706a99fe3SHajimu UMEMOTO };
10806a99fe3SHajimu UMEMOTO 
109d2432adbSDag-Erling Smørgrav struct cache_ht_item_data_ {
11006a99fe3SHajimu UMEMOTO     	/* key is the bytes sequence only - not the null-terminated string */
11106a99fe3SHajimu UMEMOTO 	char	*key;
11206a99fe3SHajimu UMEMOTO     	size_t	key_size;
11306a99fe3SHajimu UMEMOTO 
11406a99fe3SHajimu UMEMOTO 	char	*value;
11506a99fe3SHajimu UMEMOTO 	size_t	value_size;
11606a99fe3SHajimu UMEMOTO 
11706a99fe3SHajimu UMEMOTO 	struct cache_policy_item_ *fifo_policy_item;
118*a397989dSStefan Eßer 	int	confidence;	/* incremented for each verification */
11906a99fe3SHajimu UMEMOTO };
12006a99fe3SHajimu UMEMOTO 
121d2432adbSDag-Erling Smørgrav struct cache_ht_item_ {
12206a99fe3SHajimu UMEMOTO 	HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data;
12306a99fe3SHajimu UMEMOTO };
12406a99fe3SHajimu UMEMOTO 
125d2432adbSDag-Erling Smørgrav struct cache_entry_ {
12606a99fe3SHajimu UMEMOTO 	char	*name;
12706a99fe3SHajimu UMEMOTO 	struct cache_entry_params *params;
12806a99fe3SHajimu UMEMOTO };
12906a99fe3SHajimu UMEMOTO 
130d2432adbSDag-Erling Smørgrav struct cache_common_entry_ {
13106a99fe3SHajimu UMEMOTO 	char	*name;
13206a99fe3SHajimu UMEMOTO 	struct cache_entry_params *params;
13306a99fe3SHajimu UMEMOTO 
13406a99fe3SHajimu UMEMOTO 	struct common_cache_entry_params common_params;
13506a99fe3SHajimu UMEMOTO 
13606a99fe3SHajimu UMEMOTO 	HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items;
13706a99fe3SHajimu UMEMOTO 	size_t items_size;
13806a99fe3SHajimu UMEMOTO 
13906a99fe3SHajimu UMEMOTO 	/*
14006a99fe3SHajimu UMEMOTO 	 * Entry always has the FIFO policy, that is used to eliminate old
14106a99fe3SHajimu UMEMOTO 	 * elements (the ones, with lifetime more than max_lifetime). Besides,
14206a99fe3SHajimu UMEMOTO 	 * user can specify another policy to be applied, when there are too
14306a99fe3SHajimu UMEMOTO 	 * many elements in the entry. So policies_size can be 1 or 2.
14406a99fe3SHajimu UMEMOTO 	 */
14506a99fe3SHajimu UMEMOTO 	struct cache_policy_ **policies;
14606a99fe3SHajimu UMEMOTO 	size_t policies_size;
14706a99fe3SHajimu UMEMOTO 
14806a99fe3SHajimu UMEMOTO 	void	(*get_time_func)(struct timeval *);
14906a99fe3SHajimu UMEMOTO };
15006a99fe3SHajimu UMEMOTO 
15106a99fe3SHajimu UMEMOTO struct cache_mp_data_item_ {
15206a99fe3SHajimu UMEMOTO 	char	*value;
15306a99fe3SHajimu UMEMOTO 	size_t	value_size;
15406a99fe3SHajimu UMEMOTO 
15506a99fe3SHajimu UMEMOTO 	TAILQ_ENTRY(cache_mp_data_item_) entries;
15606a99fe3SHajimu UMEMOTO };
15706a99fe3SHajimu UMEMOTO 
158d2432adbSDag-Erling Smørgrav struct cache_mp_write_session_ {
15906a99fe3SHajimu UMEMOTO 	struct cache_mp_entry_	*parent_entry;
16006a99fe3SHajimu UMEMOTO 
16106a99fe3SHajimu UMEMOTO 	/*
16206a99fe3SHajimu UMEMOTO 	 * All items are accumulated in this queue. When the session is
16306a99fe3SHajimu UMEMOTO 	 * committed, they all will be copied to the multipart entry.
16406a99fe3SHajimu UMEMOTO 	 */
16506a99fe3SHajimu UMEMOTO 	TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items;
16606a99fe3SHajimu UMEMOTO 	size_t	items_size;
16706a99fe3SHajimu UMEMOTO 
16806a99fe3SHajimu UMEMOTO 	TAILQ_ENTRY(cache_mp_write_session_) entries;
16906a99fe3SHajimu UMEMOTO };
17006a99fe3SHajimu UMEMOTO 
171d2432adbSDag-Erling Smørgrav struct cache_mp_read_session_ {
17206a99fe3SHajimu UMEMOTO 	struct cache_mp_entry_ *parent_entry;
17306a99fe3SHajimu UMEMOTO 	struct cache_mp_data_item_ *current_item;
17406a99fe3SHajimu UMEMOTO 
17506a99fe3SHajimu UMEMOTO 	TAILQ_ENTRY(cache_mp_read_session_) entries;
17606a99fe3SHajimu UMEMOTO };
17706a99fe3SHajimu UMEMOTO 
178d2432adbSDag-Erling Smørgrav struct cache_mp_entry_ {
17906a99fe3SHajimu UMEMOTO 	char	*name;
18006a99fe3SHajimu UMEMOTO 	struct cache_entry_params *params;
18106a99fe3SHajimu UMEMOTO 
18206a99fe3SHajimu UMEMOTO 	struct mp_cache_entry_params mp_params;
18306a99fe3SHajimu UMEMOTO 
18406a99fe3SHajimu UMEMOTO 	/* All opened write sessions */
18506a99fe3SHajimu UMEMOTO 	TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head;
18606a99fe3SHajimu UMEMOTO 	size_t	ws_size;
18706a99fe3SHajimu UMEMOTO 
18806a99fe3SHajimu UMEMOTO 	/* All opened read sessions */
18906a99fe3SHajimu UMEMOTO 	TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head;
19006a99fe3SHajimu UMEMOTO 	size_t	rs_size;
19106a99fe3SHajimu UMEMOTO 
19206a99fe3SHajimu UMEMOTO 	/*
19306a99fe3SHajimu UMEMOTO 	 * completed_write_session is the committed write sessions. All read
19406a99fe3SHajimu UMEMOTO 	 * sessions use data from it. If the completed_write_session is out of
19506a99fe3SHajimu UMEMOTO 	 * date, but still in use by some of the read sessions, the newly
19606a99fe3SHajimu UMEMOTO 	 * committed write session is stored in the pending_write_session.
19706a99fe3SHajimu UMEMOTO 	 * In such a case, completed_write_session will be substituted with
19806a99fe3SHajimu UMEMOTO 	 * pending_write_session as soon as it won't be used by any of
19906a99fe3SHajimu UMEMOTO 	 * the read sessions.
20006a99fe3SHajimu UMEMOTO 	 */
20106a99fe3SHajimu UMEMOTO 	struct cache_mp_write_session_	*completed_write_session;
20206a99fe3SHajimu UMEMOTO 	struct cache_mp_write_session_	*pending_write_session;
20306a99fe3SHajimu UMEMOTO 	struct timeval	creation_time;
20406a99fe3SHajimu UMEMOTO 	struct timeval	last_request_time;
20506a99fe3SHajimu UMEMOTO 
20606a99fe3SHajimu UMEMOTO 	void	(*get_time_func)(struct timeval *);
20706a99fe3SHajimu UMEMOTO };
20806a99fe3SHajimu UMEMOTO 
209d2432adbSDag-Erling Smørgrav struct cache_ {
21006a99fe3SHajimu UMEMOTO 	struct cache_params params;
21106a99fe3SHajimu UMEMOTO 
21206a99fe3SHajimu UMEMOTO 	struct cache_entry_ **entries;
21306a99fe3SHajimu UMEMOTO 	size_t	entries_capacity;
21406a99fe3SHajimu UMEMOTO 	size_t	entries_size;
21506a99fe3SHajimu UMEMOTO };
21606a99fe3SHajimu UMEMOTO 
21706a99fe3SHajimu UMEMOTO /* simple abstractions - for not to write "struct" every time */
21806a99fe3SHajimu UMEMOTO typedef struct cache_		*cache;
21906a99fe3SHajimu UMEMOTO typedef struct cache_entry_	*cache_entry;
22006a99fe3SHajimu UMEMOTO typedef struct cache_mp_write_session_	*cache_mp_write_session;
22106a99fe3SHajimu UMEMOTO typedef struct cache_mp_read_session_	*cache_mp_read_session;
22206a99fe3SHajimu UMEMOTO 
22306a99fe3SHajimu UMEMOTO #define INVALID_CACHE		(NULL)
22406a99fe3SHajimu UMEMOTO #define INVALID_CACHE_ENTRY	(NULL)
22506a99fe3SHajimu UMEMOTO #define INVALID_CACHE_MP_WRITE_SESSION	(NULL)
22606a99fe3SHajimu UMEMOTO #define INVALID_CACHE_MP_READ_SESSION	(NULL)
22706a99fe3SHajimu UMEMOTO 
22806a99fe3SHajimu UMEMOTO /*
22906a99fe3SHajimu UMEMOTO  * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety
23006a99fe3SHajimu UMEMOTO  * externally, by yourself.
23106a99fe3SHajimu UMEMOTO  */
23206a99fe3SHajimu UMEMOTO 
23306a99fe3SHajimu UMEMOTO /* cache initialization/destruction routines */
234d2432adbSDag-Erling Smørgrav cache init_cache(struct cache_params const *);
235d2432adbSDag-Erling Smørgrav void destroy_cache(cache);
23606a99fe3SHajimu UMEMOTO 
23706a99fe3SHajimu UMEMOTO /* cache entries manipulation routines */
238d2432adbSDag-Erling Smørgrav int register_cache_entry(cache, struct cache_entry_params const *);
239d2432adbSDag-Erling Smørgrav int unregister_cache_entry(cache, const char *);
240d2432adbSDag-Erling Smørgrav cache_entry find_cache_entry(cache, const char *);
24106a99fe3SHajimu UMEMOTO 
24206a99fe3SHajimu UMEMOTO /* read/write operations used on common entries */
243d2432adbSDag-Erling Smørgrav int cache_read(cache_entry, const char *, size_t, char *, size_t *);
244d2432adbSDag-Erling Smørgrav int cache_write(cache_entry, const char *, size_t, char const *, size_t);
24506a99fe3SHajimu UMEMOTO 
24606a99fe3SHajimu UMEMOTO /* read/write operations used on multipart entries */
247d2432adbSDag-Erling Smørgrav cache_mp_write_session open_cache_mp_write_session(cache_entry);
248d2432adbSDag-Erling Smørgrav int cache_mp_write(cache_mp_write_session, char *, size_t);
249d2432adbSDag-Erling Smørgrav void abandon_cache_mp_write_session(cache_mp_write_session);
250d2432adbSDag-Erling Smørgrav void close_cache_mp_write_session(cache_mp_write_session);
25106a99fe3SHajimu UMEMOTO 
252d2432adbSDag-Erling Smørgrav cache_mp_read_session open_cache_mp_read_session(cache_entry);
253d2432adbSDag-Erling Smørgrav int cache_mp_read(cache_mp_read_session, char *, size_t *);
254d2432adbSDag-Erling Smørgrav void close_cache_mp_read_session(cache_mp_read_session);
25506a99fe3SHajimu UMEMOTO 
25606a99fe3SHajimu UMEMOTO /* transformation routines */
257d2432adbSDag-Erling Smørgrav int transform_cache_entry(cache_entry, enum cache_transformation_t);
258d2432adbSDag-Erling Smørgrav int transform_cache_entry_part(cache_entry, enum cache_transformation_t,
25906a99fe3SHajimu UMEMOTO 	const char *, size_t, enum part_position_t);
26006a99fe3SHajimu UMEMOTO 
26106a99fe3SHajimu UMEMOTO #endif
262