xref: /dflybsd-src/usr.sbin/nscd/cachelib.h (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino  * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3*86d7f5d3SJohn Marino  * All rights reserved.
4*86d7f5d3SJohn Marino  *
5*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino  * are met:
8*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino  *
14*86d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*86d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*86d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*86d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*86d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*86d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*86d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*86d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*86d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*86d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*86d7f5d3SJohn Marino  * SUCH DAMAGE.
25*86d7f5d3SJohn Marino  *
26*86d7f5d3SJohn Marino  * $FreeBSD: src/usr.sbin/nscd/cachelib.h,v 1.3 2007/09/27 12:30:11 bushman Exp $
27*86d7f5d3SJohn Marino  */
28*86d7f5d3SJohn Marino 
29*86d7f5d3SJohn Marino #ifndef __NSCD_CACHELIB_H__
30*86d7f5d3SJohn Marino #define __NSCD_CACHELIB_H__
31*86d7f5d3SJohn Marino 
32*86d7f5d3SJohn Marino #include <sys/queue.h>
33*86d7f5d3SJohn Marino #include <sys/time.h>
34*86d7f5d3SJohn Marino #include <stdlib.h>
35*86d7f5d3SJohn Marino #include "hashtable.h"
36*86d7f5d3SJohn Marino #include "cacheplcs.h"
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino enum cache_entry_t	{
39*86d7f5d3SJohn Marino 	CET_COMMON = 0,	/* cache item is atomic */
40*86d7f5d3SJohn Marino 	CET_MULTIPART	/* cache item is formed part by part */
41*86d7f5d3SJohn Marino };
42*86d7f5d3SJohn Marino 
43*86d7f5d3SJohn Marino enum cache_transformation_t {
44*86d7f5d3SJohn Marino 	CTT_FLUSH = 0,	/* flush the cache - delete all obsolete items */
45*86d7f5d3SJohn Marino 	CTT_CLEAR = 1	/* delete all items in the cache */
46*86d7f5d3SJohn Marino };
47*86d7f5d3SJohn Marino 
48*86d7f5d3SJohn Marino /* cache deletion policy type enum */
49*86d7f5d3SJohn Marino enum cache_policy_t {
50*86d7f5d3SJohn Marino 	CPT_FIFO = 0, 	/* first-in first-out */
51*86d7f5d3SJohn Marino 	CPT_LRU = 1,	/* least recently used */
52*86d7f5d3SJohn Marino 	CPT_LFU = 2 	/* least frequently used */
53*86d7f5d3SJohn Marino };
54*86d7f5d3SJohn Marino 
55*86d7f5d3SJohn Marino /* multipart sessions can be used for reading and writing */
56*86d7f5d3SJohn Marino enum cache_mp_session_t {
57*86d7f5d3SJohn Marino 	CMPT_READ_SESSION,
58*86d7f5d3SJohn Marino 	CMPT_WRITE_SESSION
59*86d7f5d3SJohn Marino };
60*86d7f5d3SJohn Marino 
61*86d7f5d3SJohn Marino /*
62*86d7f5d3SJohn Marino  * When doing partial transformations of entries (which are applied for
63*86d7f5d3SJohn Marino  * elements with keys, that contain specified buffer in its left or
64*86d7f5d3SJohn Marino  * right part), this enum will show the needed position of the key part.
65*86d7f5d3SJohn Marino  */
66*86d7f5d3SJohn Marino enum part_position_t {
67*86d7f5d3SJohn Marino 	KPPT_LEFT,
68*86d7f5d3SJohn Marino 	KPPT_RIGHT
69*86d7f5d3SJohn Marino };
70*86d7f5d3SJohn Marino 
71*86d7f5d3SJohn Marino /* num_levels attribute is obsolete, i think - user can always emulate it
72*86d7f5d3SJohn Marino  * by using one entry.
73*86d7f5d3SJohn Marino  * get_time_func is needed to have the clocks-independent counter
74*86d7f5d3SJohn Marino  */
75*86d7f5d3SJohn Marino struct cache_params
76*86d7f5d3SJohn Marino {
77*86d7f5d3SJohn Marino 	void	(*get_time_func)(struct timeval *);
78*86d7f5d3SJohn Marino };
79*86d7f5d3SJohn Marino 
80*86d7f5d3SJohn Marino /*
81*86d7f5d3SJohn Marino  * base structure - normal_cache_entry_params and multipart_cache_entry_params
82*86d7f5d3SJohn Marino  * are "inherited" from it
83*86d7f5d3SJohn Marino  */
84*86d7f5d3SJohn Marino struct cache_entry_params
85*86d7f5d3SJohn Marino {
86*86d7f5d3SJohn Marino 	enum cache_entry_t entry_type;
87*86d7f5d3SJohn Marino 	char	*entry_name;
88*86d7f5d3SJohn Marino };
89*86d7f5d3SJohn Marino 
90*86d7f5d3SJohn Marino /* params, used for most entries */
91*86d7f5d3SJohn Marino struct common_cache_entry_params
92*86d7f5d3SJohn Marino {
93*86d7f5d3SJohn Marino 	/* inherited fields */
94*86d7f5d3SJohn Marino 	enum cache_entry_t	entry_type;
95*86d7f5d3SJohn Marino 
96*86d7f5d3SJohn Marino 	/* unique fields */
97*86d7f5d3SJohn Marino 	char	*entry_name;
98*86d7f5d3SJohn Marino 	size_t	cache_entries_size;
99*86d7f5d3SJohn Marino 
100*86d7f5d3SJohn Marino 	size_t	max_elemsize;		/* if 0 then no check is made */
101*86d7f5d3SJohn Marino 	size_t	satisf_elemsize;	/* if entry size is exceeded,
102*86d7f5d3SJohn Marino 					 * this number of elements will be left,
103*86d7f5d3SJohn Marino 					 * others will be deleted */
104*86d7f5d3SJohn Marino 	struct timeval	max_lifetime;	/* if 0 then no check is made */
105*86d7f5d3SJohn Marino 	enum cache_policy_t policy;	/* policy used for transformations */
106*86d7f5d3SJohn Marino };
107*86d7f5d3SJohn Marino 
108*86d7f5d3SJohn Marino /* params, used for multipart entries */
109*86d7f5d3SJohn Marino struct	mp_cache_entry_params
110*86d7f5d3SJohn Marino {
111*86d7f5d3SJohn Marino 	/* inherited fields */
112*86d7f5d3SJohn Marino 	enum cache_entry_t entry_type;
113*86d7f5d3SJohn Marino 	char	*entry_name;
114*86d7f5d3SJohn Marino 
115*86d7f5d3SJohn Marino 	/* unique fields */
116*86d7f5d3SJohn Marino 	size_t	max_elemsize;	/* if 0 then no check is made */
117*86d7f5d3SJohn Marino 	size_t	max_sessions;	/* maximum number of active sessions */
118*86d7f5d3SJohn Marino 
119*86d7f5d3SJohn Marino 	struct timeval	max_lifetime;	/* maximum elements lifetime */
120*86d7f5d3SJohn Marino };
121*86d7f5d3SJohn Marino 
122*86d7f5d3SJohn Marino struct cache_ht_item_data_
123*86d7f5d3SJohn Marino {
124*86d7f5d3SJohn Marino 	/* key is the bytes sequence only - not the null-terminated string */
125*86d7f5d3SJohn Marino 	char	*key;
126*86d7f5d3SJohn Marino 	size_t	key_size;
127*86d7f5d3SJohn Marino 
128*86d7f5d3SJohn Marino 	char	*value;
129*86d7f5d3SJohn Marino 	size_t	value_size;
130*86d7f5d3SJohn Marino 
131*86d7f5d3SJohn Marino 	struct cache_policy_item_ *fifo_policy_item;
132*86d7f5d3SJohn Marino };
133*86d7f5d3SJohn Marino 
134*86d7f5d3SJohn Marino struct cache_ht_item_
135*86d7f5d3SJohn Marino {
136*86d7f5d3SJohn Marino 	HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data;
137*86d7f5d3SJohn Marino };
138*86d7f5d3SJohn Marino 
139*86d7f5d3SJohn Marino struct cache_entry_
140*86d7f5d3SJohn Marino {
141*86d7f5d3SJohn Marino 	char	*name;
142*86d7f5d3SJohn Marino 	struct cache_entry_params *params;
143*86d7f5d3SJohn Marino };
144*86d7f5d3SJohn Marino 
145*86d7f5d3SJohn Marino struct cache_common_entry_
146*86d7f5d3SJohn Marino {
147*86d7f5d3SJohn Marino 	char	*name;
148*86d7f5d3SJohn Marino 	struct cache_entry_params *params;
149*86d7f5d3SJohn Marino 
150*86d7f5d3SJohn Marino 	struct common_cache_entry_params common_params;
151*86d7f5d3SJohn Marino 
152*86d7f5d3SJohn Marino 	HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items;
153*86d7f5d3SJohn Marino 	size_t items_size;
154*86d7f5d3SJohn Marino 
155*86d7f5d3SJohn Marino 	/*
156*86d7f5d3SJohn Marino 	 * Entry always has the FIFO policy, that is used to eliminate old
157*86d7f5d3SJohn Marino 	 * elements (the ones, with lifetime more than max_lifetime). Besides,
158*86d7f5d3SJohn Marino 	 * user can specify another policy to be applied, when there are too
159*86d7f5d3SJohn Marino 	 * many elements in the entry. So policies_size can be 1 or 2.
160*86d7f5d3SJohn Marino 	 */
161*86d7f5d3SJohn Marino 	struct cache_policy_ **policies;
162*86d7f5d3SJohn Marino 	size_t policies_size;
163*86d7f5d3SJohn Marino 
164*86d7f5d3SJohn Marino 	void	(*get_time_func)(struct timeval *);
165*86d7f5d3SJohn Marino };
166*86d7f5d3SJohn Marino 
167*86d7f5d3SJohn Marino struct cache_mp_data_item_ {
168*86d7f5d3SJohn Marino 	char	*value;
169*86d7f5d3SJohn Marino 	size_t	value_size;
170*86d7f5d3SJohn Marino 
171*86d7f5d3SJohn Marino 	TAILQ_ENTRY(cache_mp_data_item_) entries;
172*86d7f5d3SJohn Marino };
173*86d7f5d3SJohn Marino 
174*86d7f5d3SJohn Marino struct cache_mp_write_session_
175*86d7f5d3SJohn Marino {
176*86d7f5d3SJohn Marino 	struct cache_mp_entry_	*parent_entry;
177*86d7f5d3SJohn Marino 
178*86d7f5d3SJohn Marino 	/*
179*86d7f5d3SJohn Marino 	 * All items are accumulated in this queue. When the session is
180*86d7f5d3SJohn Marino 	 * committed, they all will be copied to the multipart entry.
181*86d7f5d3SJohn Marino 	 */
182*86d7f5d3SJohn Marino 	TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items;
183*86d7f5d3SJohn Marino 	size_t	items_size;
184*86d7f5d3SJohn Marino 
185*86d7f5d3SJohn Marino 	TAILQ_ENTRY(cache_mp_write_session_) entries;
186*86d7f5d3SJohn Marino };
187*86d7f5d3SJohn Marino 
188*86d7f5d3SJohn Marino struct cache_mp_read_session_
189*86d7f5d3SJohn Marino {
190*86d7f5d3SJohn Marino 	struct cache_mp_entry_ *parent_entry;
191*86d7f5d3SJohn Marino 	struct cache_mp_data_item_ *current_item;
192*86d7f5d3SJohn Marino 
193*86d7f5d3SJohn Marino 	TAILQ_ENTRY(cache_mp_read_session_) entries;
194*86d7f5d3SJohn Marino };
195*86d7f5d3SJohn Marino 
196*86d7f5d3SJohn Marino struct cache_mp_entry_
197*86d7f5d3SJohn Marino {
198*86d7f5d3SJohn Marino 	char	*name;
199*86d7f5d3SJohn Marino 	struct cache_entry_params *params;
200*86d7f5d3SJohn Marino 
201*86d7f5d3SJohn Marino 	struct mp_cache_entry_params mp_params;
202*86d7f5d3SJohn Marino 
203*86d7f5d3SJohn Marino 	/* All opened write sessions */
204*86d7f5d3SJohn Marino 	TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head;
205*86d7f5d3SJohn Marino 	size_t	ws_size;
206*86d7f5d3SJohn Marino 
207*86d7f5d3SJohn Marino 	/* All opened read sessions */
208*86d7f5d3SJohn Marino 	TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head;
209*86d7f5d3SJohn Marino 	size_t	rs_size;
210*86d7f5d3SJohn Marino 
211*86d7f5d3SJohn Marino 	/*
212*86d7f5d3SJohn Marino 	 * completed_write_session is the committed write sessions. All read
213*86d7f5d3SJohn Marino 	 * sessions use data from it. If the completed_write_session is out of
214*86d7f5d3SJohn Marino 	 * date, but still in use by some of the read sessions, the newly
215*86d7f5d3SJohn Marino 	 * committed write session is stored in the pending_write_session.
216*86d7f5d3SJohn Marino 	 * In such a case, completed_write_session will be substituted with
217*86d7f5d3SJohn Marino 	 * pending_write_session as soon as it won't be used by any of
218*86d7f5d3SJohn Marino 	 * the read sessions.
219*86d7f5d3SJohn Marino 	 */
220*86d7f5d3SJohn Marino 	struct cache_mp_write_session_	*completed_write_session;
221*86d7f5d3SJohn Marino 	struct cache_mp_write_session_	*pending_write_session;
222*86d7f5d3SJohn Marino 	struct timeval	creation_time;
223*86d7f5d3SJohn Marino 	struct timeval	last_request_time;
224*86d7f5d3SJohn Marino 
225*86d7f5d3SJohn Marino 	void	(*get_time_func)(struct timeval *);
226*86d7f5d3SJohn Marino };
227*86d7f5d3SJohn Marino 
228*86d7f5d3SJohn Marino struct cache_
229*86d7f5d3SJohn Marino {
230*86d7f5d3SJohn Marino 	struct cache_params params;
231*86d7f5d3SJohn Marino 
232*86d7f5d3SJohn Marino 	struct cache_entry_ **entries;
233*86d7f5d3SJohn Marino 	size_t	entries_capacity;
234*86d7f5d3SJohn Marino 	size_t	entries_size;
235*86d7f5d3SJohn Marino };
236*86d7f5d3SJohn Marino 
237*86d7f5d3SJohn Marino /* simple abstractions - for not to write "struct" every time */
238*86d7f5d3SJohn Marino typedef struct cache_		*cache;
239*86d7f5d3SJohn Marino typedef struct cache_entry_	*cache_entry;
240*86d7f5d3SJohn Marino typedef struct cache_mp_write_session_	*cache_mp_write_session;
241*86d7f5d3SJohn Marino typedef struct cache_mp_read_session_	*cache_mp_read_session;
242*86d7f5d3SJohn Marino 
243*86d7f5d3SJohn Marino #define INVALID_CACHE		(NULL)
244*86d7f5d3SJohn Marino #define INVALID_CACHE_ENTRY	(NULL)
245*86d7f5d3SJohn Marino #define INVALID_CACHE_MP_WRITE_SESSION	(NULL)
246*86d7f5d3SJohn Marino #define INVALID_CACHE_MP_READ_SESSION	(NULL)
247*86d7f5d3SJohn Marino 
248*86d7f5d3SJohn Marino /*
249*86d7f5d3SJohn Marino  * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety
250*86d7f5d3SJohn Marino  * externally, by yourself.
251*86d7f5d3SJohn Marino  */
252*86d7f5d3SJohn Marino 
253*86d7f5d3SJohn Marino /* cache initialization/destruction routines */
254*86d7f5d3SJohn Marino extern cache init_cache(struct cache_params const *);
255*86d7f5d3SJohn Marino extern void destroy_cache(cache);
256*86d7f5d3SJohn Marino 
257*86d7f5d3SJohn Marino /* cache entries manipulation routines */
258*86d7f5d3SJohn Marino extern int register_cache_entry(cache, struct cache_entry_params const *);
259*86d7f5d3SJohn Marino extern int unregister_cache_entry(cache, const char *);
260*86d7f5d3SJohn Marino extern cache_entry find_cache_entry(cache, const char *);
261*86d7f5d3SJohn Marino 
262*86d7f5d3SJohn Marino /* read/write operations used on common entries */
263*86d7f5d3SJohn Marino extern int cache_read(cache_entry, const char *, size_t, char *, size_t *);
264*86d7f5d3SJohn Marino extern int cache_write(cache_entry, const char *, size_t, char const *, size_t);
265*86d7f5d3SJohn Marino 
266*86d7f5d3SJohn Marino /* read/write operations used on multipart entries */
267*86d7f5d3SJohn Marino extern cache_mp_write_session open_cache_mp_write_session(cache_entry);
268*86d7f5d3SJohn Marino extern int cache_mp_write(cache_mp_write_session, char *, size_t);
269*86d7f5d3SJohn Marino extern void abandon_cache_mp_write_session(cache_mp_write_session);
270*86d7f5d3SJohn Marino extern void close_cache_mp_write_session(cache_mp_write_session);
271*86d7f5d3SJohn Marino 
272*86d7f5d3SJohn Marino extern cache_mp_read_session open_cache_mp_read_session(cache_entry);
273*86d7f5d3SJohn Marino extern int cache_mp_read(cache_mp_read_session, char *, size_t *);
274*86d7f5d3SJohn Marino extern void close_cache_mp_read_session(cache_mp_read_session);
275*86d7f5d3SJohn Marino 
276*86d7f5d3SJohn Marino /* transformation routines */
277*86d7f5d3SJohn Marino extern int transform_cache_entry(cache_entry, enum cache_transformation_t);
278*86d7f5d3SJohn Marino extern int transform_cache_entry_part(cache_entry, enum cache_transformation_t,
279*86d7f5d3SJohn Marino 	const char *, size_t, enum part_position_t);
280*86d7f5d3SJohn Marino 
281*86d7f5d3SJohn Marino #endif
282