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