cachelib.h revision 158115
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: head/usr.sbin/nscd/cachelib.h 158115 2006-04-28 12:03:38Z ume $
27 */
28
29#ifndef __CACHED_CACHELIB_H__
30#define __CACHED_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
38enum cache_entry_t	{
39	CET_COMMON = 0,	/* cache item is atomic */
40	CET_MULTIPART	/* cache item is formed part by part */
41};
42
43enum 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 */
49enum 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 */
56enum 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 */
66enum 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 */
75struct 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 */
84struct cache_entry_params
85{
86	enum cache_entry_t entry_type;
87	char	*entry_name;
88};
89
90/* params, used for most entries */
91struct 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 */
109struct	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
122struct 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
134struct cache_ht_item_
135{
136	HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data;
137};
138
139struct cache_entry_
140{
141	char	*name;
142	struct cache_entry_params *params;
143};
144
145struct 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
167struct cache_mp_data_item_ {
168	char	*value;
169	size_t	value_size;
170
171	TAILQ_ENTRY(cache_mp_data_item_) entries;
172};
173
174struct 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
188struct 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
196struct 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
228struct 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 */
238typedef struct cache_		*cache;
239typedef struct cache_entry_	*cache_entry;
240typedef struct cache_mp_write_session_	*cache_mp_write_session;
241typedef 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 */
254extern cache init_cache(struct cache_params const *);
255extern void destroy_cache(cache);
256
257/* cache entries manipulation routines */
258extern int register_cache_entry(cache, struct cache_entry_params const *);
259extern int unregister_cache_entry(cache, const char *);
260extern cache_entry find_cache_entry(cache, const char *);
261
262/* read/write operations used on common entries */
263extern int cache_read(cache_entry, const char *, size_t, char *, size_t *);
264extern int cache_write(cache_entry, const char *, size_t, char const *, size_t);
265
266/* read/write operations used on multipart entries */
267extern cache_mp_write_session open_cache_mp_write_session(cache_entry);
268extern int cache_mp_write(cache_mp_write_session, char *, size_t);
269extern void abandon_cache_mp_write_session(cache_mp_write_session);
270extern void close_cache_mp_write_session(cache_mp_write_session);
271
272extern cache_mp_read_session open_cache_mp_read_session(cache_entry);
273extern int cache_mp_read(cache_mp_read_session, char *, size_t *);
274extern void close_cache_mp_read_session(cache_mp_read_session);
275
276/* transformation routines */
277extern int transform_cache_entry(cache_entry, enum cache_transformation_t);
278extern int transform_cache_entry_part(cache_entry, enum cache_transformation_t,
279	const char *, size_t, enum part_position_t);
280
281#endif
282