cachelib.h revision 194097
1158115Sume/*-
2158115Sume * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3158115Sume * All rights reserved.
4158115Sume *
5158115Sume * Redistribution and use in source and binary forms, with or without
6158115Sume * modification, are permitted provided that the following conditions
7158115Sume * are met:
8158115Sume * 1. Redistributions of source code must retain the above copyright
9158115Sume *    notice, this list of conditions and the following disclaimer.
10158115Sume * 2. Redistributions in binary form must reproduce the above copyright
11158115Sume *    notice, this list of conditions and the following disclaimer in the
12158115Sume *    documentation and/or other materials provided with the distribution.
13158115Sume *
14158115Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15158115Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16158115Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17158115Sume * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18158115Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19158115Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20158115Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21158115Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22158115Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23158115Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24158115Sume * SUCH DAMAGE.
25158115Sume *
26158115Sume * $FreeBSD: head/usr.sbin/nscd/cachelib.h 194097 2009-06-13 01:22:56Z des $
27158115Sume */
28158115Sume
29171795Sbushman#ifndef __NSCD_CACHELIB_H__
30171795Sbushman#define __NSCD_CACHELIB_H__
31158115Sume
32158115Sume#include "hashtable.h"
33158115Sume#include "cacheplcs.h"
34158115Sume
35158115Sumeenum cache_entry_t	{
36158115Sume	CET_COMMON = 0,	/* cache item is atomic */
37158115Sume	CET_MULTIPART	/* cache item is formed part by part */
38158115Sume};
39158115Sume
40158115Sumeenum cache_transformation_t {
41158115Sume	CTT_FLUSH = 0,	/* flush the cache - delete all obsolete items */
42158115Sume	CTT_CLEAR = 1	/* delete all items in the cache */
43158115Sume};
44158115Sume
45158115Sume/* cache deletion policy type enum */
46158115Sumeenum cache_policy_t {
47158115Sume	CPT_FIFO = 0, 	/* first-in first-out */
48158115Sume	CPT_LRU = 1,	/* least recently used */
49158115Sume	CPT_LFU = 2 	/* least frequently used */
50158115Sume};
51158115Sume
52158115Sume/* multipart sessions can be used for reading and writing */
53158115Sumeenum cache_mp_session_t {
54158115Sume	CMPT_READ_SESSION,
55158115Sume	CMPT_WRITE_SESSION
56158115Sume};
57158115Sume
58158115Sume/*
59158115Sume * When doing partial transformations of entries (which are applied for
60158115Sume * elements with keys, that contain specified buffer in its left or
61158115Sume * right part), this enum will show the needed position of the key part.
62158115Sume */
63158115Sumeenum part_position_t {
64158115Sume	KPPT_LEFT,
65158115Sume	KPPT_RIGHT
66158115Sume};
67158115Sume
68158115Sume/* num_levels attribute is obsolete, i think - user can always emulate it
69158115Sume * by using one entry.
70158115Sume * get_time_func is needed to have the clocks-independent counter
71158115Sume */
72158115Sumestruct cache_params
73158115Sume{
74158115Sume	void	(*get_time_func)(struct timeval *);
75158115Sume};
76158115Sume
77158115Sume/*
78158115Sume * base structure - normal_cache_entry_params and multipart_cache_entry_params
79158115Sume * are "inherited" from it
80158115Sume */
81158115Sumestruct cache_entry_params
82158115Sume{
83158115Sume	enum cache_entry_t entry_type;
84158115Sume	char	*entry_name;
85158115Sume};
86158115Sume
87158115Sume/* params, used for most entries */
88158115Sumestruct common_cache_entry_params
89158115Sume{
90194097Sdes	struct cache_entry_params cep;
91158115Sume
92158115Sume	size_t	cache_entries_size;
93158115Sume
94158115Sume	size_t	max_elemsize;		/* if 0 then no check is made */
95158115Sume	size_t	satisf_elemsize;	/* if entry size is exceeded,
96158115Sume					 * this number of elements will be left,
97158115Sume					 * others will be deleted */
98158115Sume	struct timeval	max_lifetime;	/* if 0 then no check is made */
99158115Sume	enum cache_policy_t policy;	/* policy used for transformations */
100158115Sume};
101158115Sume
102158115Sume/* params, used for multipart entries */
103158115Sumestruct	mp_cache_entry_params
104158115Sume{
105194097Sdes	struct cache_entry_params cep;
106158115Sume
107158115Sume	/* unique fields */
108158115Sume	size_t	max_elemsize;	/* if 0 then no check is made */
109158115Sume	size_t	max_sessions;	/* maximum number of active sessions */
110158115Sume
111158115Sume	struct timeval	max_lifetime;	/* maximum elements lifetime */
112158115Sume};
113158115Sume
114158115Sumestruct cache_ht_item_data_
115158115Sume{
116158115Sume    	/* key is the bytes sequence only - not the null-terminated string */
117158115Sume	char	*key;
118158115Sume    	size_t	key_size;
119158115Sume
120158115Sume	char	*value;
121158115Sume	size_t	value_size;
122158115Sume
123158115Sume	struct cache_policy_item_ *fifo_policy_item;
124158115Sume};
125158115Sume
126158115Sumestruct cache_ht_item_
127158115Sume{
128158115Sume	HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data;
129158115Sume};
130158115Sume
131158115Sumestruct cache_entry_
132158115Sume{
133158115Sume	char	*name;
134158115Sume	struct cache_entry_params *params;
135158115Sume};
136158115Sume
137158115Sumestruct cache_common_entry_
138158115Sume{
139158115Sume	char	*name;
140158115Sume	struct cache_entry_params *params;
141158115Sume
142158115Sume	struct common_cache_entry_params common_params;
143158115Sume
144158115Sume	HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items;
145158115Sume	size_t items_size;
146158115Sume
147158115Sume	/*
148158115Sume	 * Entry always has the FIFO policy, that is used to eliminate old
149158115Sume	 * elements (the ones, with lifetime more than max_lifetime). Besides,
150158115Sume	 * user can specify another policy to be applied, when there are too
151158115Sume	 * many elements in the entry. So policies_size can be 1 or 2.
152158115Sume	 */
153158115Sume	struct cache_policy_ **policies;
154158115Sume	size_t policies_size;
155158115Sume
156158115Sume	void	(*get_time_func)(struct timeval *);
157158115Sume};
158158115Sume
159158115Sumestruct cache_mp_data_item_ {
160158115Sume	char	*value;
161158115Sume	size_t	value_size;
162158115Sume
163158115Sume	TAILQ_ENTRY(cache_mp_data_item_) entries;
164158115Sume};
165158115Sume
166158115Sumestruct cache_mp_write_session_
167158115Sume{
168158115Sume	struct cache_mp_entry_	*parent_entry;
169158115Sume
170158115Sume	/*
171158115Sume	 * All items are accumulated in this queue. When the session is
172158115Sume	 * committed, they all will be copied to the multipart entry.
173158115Sume	 */
174158115Sume	TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items;
175158115Sume	size_t	items_size;
176158115Sume
177158115Sume	TAILQ_ENTRY(cache_mp_write_session_) entries;
178158115Sume};
179158115Sume
180158115Sumestruct cache_mp_read_session_
181158115Sume{
182158115Sume	struct cache_mp_entry_ *parent_entry;
183158115Sume	struct cache_mp_data_item_ *current_item;
184158115Sume
185158115Sume	TAILQ_ENTRY(cache_mp_read_session_) entries;
186158115Sume};
187158115Sume
188158115Sumestruct cache_mp_entry_
189158115Sume{
190158115Sume	char	*name;
191158115Sume	struct cache_entry_params *params;
192158115Sume
193158115Sume	struct mp_cache_entry_params mp_params;
194158115Sume
195158115Sume	/* All opened write sessions */
196158115Sume	TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head;
197158115Sume	size_t	ws_size;
198158115Sume
199158115Sume	/* All opened read sessions */
200158115Sume	TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head;
201158115Sume	size_t	rs_size;
202158115Sume
203158115Sume	/*
204158115Sume	 * completed_write_session is the committed write sessions. All read
205158115Sume	 * sessions use data from it. If the completed_write_session is out of
206158115Sume	 * date, but still in use by some of the read sessions, the newly
207158115Sume	 * committed write session is stored in the pending_write_session.
208158115Sume	 * In such a case, completed_write_session will be substituted with
209158115Sume	 * pending_write_session as soon as it won't be used by any of
210158115Sume	 * the read sessions.
211158115Sume	 */
212158115Sume	struct cache_mp_write_session_	*completed_write_session;
213158115Sume	struct cache_mp_write_session_	*pending_write_session;
214158115Sume	struct timeval	creation_time;
215158115Sume	struct timeval	last_request_time;
216158115Sume
217158115Sume	void	(*get_time_func)(struct timeval *);
218158115Sume};
219158115Sume
220158115Sumestruct cache_
221158115Sume{
222158115Sume	struct cache_params params;
223158115Sume
224158115Sume	struct cache_entry_ **entries;
225158115Sume	size_t	entries_capacity;
226158115Sume	size_t	entries_size;
227158115Sume};
228158115Sume
229158115Sume/* simple abstractions - for not to write "struct" every time */
230158115Sumetypedef struct cache_		*cache;
231158115Sumetypedef struct cache_entry_	*cache_entry;
232158115Sumetypedef struct cache_mp_write_session_	*cache_mp_write_session;
233158115Sumetypedef struct cache_mp_read_session_	*cache_mp_read_session;
234158115Sume
235158115Sume#define INVALID_CACHE		(NULL)
236158115Sume#define INVALID_CACHE_ENTRY	(NULL)
237158115Sume#define INVALID_CACHE_MP_WRITE_SESSION	(NULL)
238158115Sume#define INVALID_CACHE_MP_READ_SESSION	(NULL)
239158115Sume
240158115Sume/*
241158115Sume * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety
242158115Sume * externally, by yourself.
243158115Sume */
244158115Sume
245158115Sume/* cache initialization/destruction routines */
246158115Sumeextern cache init_cache(struct cache_params const *);
247158115Sumeextern void destroy_cache(cache);
248158115Sume
249158115Sume/* cache entries manipulation routines */
250158115Sumeextern int register_cache_entry(cache, struct cache_entry_params const *);
251158115Sumeextern int unregister_cache_entry(cache, const char *);
252158115Sumeextern cache_entry find_cache_entry(cache, const char *);
253158115Sume
254158115Sume/* read/write operations used on common entries */
255158115Sumeextern int cache_read(cache_entry, const char *, size_t, char *, size_t *);
256158115Sumeextern int cache_write(cache_entry, const char *, size_t, char const *, size_t);
257158115Sume
258158115Sume/* read/write operations used on multipart entries */
259158115Sumeextern cache_mp_write_session open_cache_mp_write_session(cache_entry);
260158115Sumeextern int cache_mp_write(cache_mp_write_session, char *, size_t);
261158115Sumeextern void abandon_cache_mp_write_session(cache_mp_write_session);
262158115Sumeextern void close_cache_mp_write_session(cache_mp_write_session);
263158115Sume
264158115Sumeextern cache_mp_read_session open_cache_mp_read_session(cache_entry);
265158115Sumeextern int cache_mp_read(cache_mp_read_session, char *, size_t *);
266158115Sumeextern void close_cache_mp_read_session(cache_mp_read_session);
267158115Sume
268158115Sume/* transformation routines */
269158115Sumeextern int transform_cache_entry(cache_entry, enum cache_transformation_t);
270158115Sumeextern int transform_cache_entry_part(cache_entry, enum cache_transformation_t,
271158115Sume	const char *, size_t, enum part_position_t);
272158115Sume
273158115Sume#endif
274