cachelib.h revision 194089
156067Smarkm/*-
256067Smarkm * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
356067Smarkm * All rights reserved.
456067Smarkm *
556067Smarkm * Redistribution and use in source and binary forms, with or without
656067Smarkm * modification, are permitted provided that the following conditions
756067Smarkm * are met:
856067Smarkm * 1. Redistributions of source code must retain the above copyright
956067Smarkm *    notice, this list of conditions and the following disclaimer.
1056067Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1156067Smarkm *    notice, this list of conditions and the following disclaimer in the
1256067Smarkm *    documentation and/or other materials provided with the distribution.
1356067Smarkm *
1456549Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1556549Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1657672Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1758485Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1857672Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1956549Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2056549Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2156549Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2256549Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2356067Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2456067Smarkm * SUCH DAMAGE.
2556067Smarkm *
2656067Smarkm * $FreeBSD: head/usr.sbin/nscd/cachelib.h 194089 2009-06-13 00:06:52Z des $
2756067Smarkm */
2856067Smarkm
2956067Smarkm#ifndef __NSCD_CACHELIB_H__
3056067Smarkm#define __NSCD_CACHELIB_H__
3156067Smarkm
3256067Smarkm#include "hashtable.h"
3356067Smarkm#include "cacheplcs.h"
3456067Smarkm
3556067Smarkmenum cache_entry_t	{
3656067Smarkm	CET_COMMON = 0,	/* cache item is atomic */
3756067Smarkm	CET_MULTIPART	/* cache item is formed part by part */
3856067Smarkm};
3956067Smarkm
4056067Smarkmenum cache_transformation_t {
4156067Smarkm	CTT_FLUSH = 0,	/* flush the cache - delete all obsolete items */
4256067Smarkm	CTT_CLEAR = 1	/* delete all items in the cache */
4356067Smarkm};
4456067Smarkm
4556067Smarkm/* cache deletion policy type enum */
4656067Smarkmenum cache_policy_t {
4772450Sassar	CPT_FIFO = 0, 	/* first-in first-out */
4872450Sassar	CPT_LRU = 1,	/* least recently used */
4972450Sassar	CPT_LFU = 2 	/* least frequently used */
5072450Sassar};
5172450Sassar
5272450Sassar/* multipart sessions can be used for reading and writing */
5356067Smarkmenum cache_mp_session_t {
5456067Smarkm	CMPT_READ_SESSION,
5556067Smarkm	CMPT_WRITE_SESSION
5656067Smarkm};
5756067Smarkm
5856067Smarkm/*
5956067Smarkm * When doing partial transformations of entries (which are applied for
6056067Smarkm * elements with keys, that contain specified buffer in its left or
6156067Smarkm * right part), this enum will show the needed position of the key part.
6256067Smarkm */
6356067Smarkmenum part_position_t {
6456067Smarkm	KPPT_LEFT,
6556067Smarkm	KPPT_RIGHT
6656067Smarkm};
6756067Smarkm
6856067Smarkm/* num_levels attribute is obsolete, i think - user can always emulate it
6956067Smarkm * by using one entry.
7056067Smarkm * get_time_func is needed to have the clocks-independent counter
7156067Smarkm */
7256067Smarkmstruct cache_params
7356067Smarkm{
7456067Smarkm	void	(*get_time_func)(struct timeval *);
7556067Smarkm};
7656067Smarkm
7756067Smarkm/*
7856067Smarkm * base structure - normal_cache_entry_params and multipart_cache_entry_params
7956067Smarkm * are "inherited" from it
8056067Smarkm */
8156067Smarkmstruct cache_entry_params
8256067Smarkm{
8356067Smarkm	enum cache_entry_t entry_type;
8456067Smarkm	char	*entry_name;
8556067Smarkm};
8656067Smarkm
8756067Smarkm/* params, used for most entries */
8856067Smarkmstruct common_cache_entry_params
8956067Smarkm{
9056067Smarkm	/* inherited fields */
9156067Smarkm	enum cache_entry_t	entry_type;
9256067Smarkm
9356067Smarkm	/* unique fields */
9456067Smarkm	char	*entry_name;
9556067Smarkm	size_t	cache_entries_size;
9656067Smarkm
9756067Smarkm	size_t	max_elemsize;		/* if 0 then no check is made */
9856067Smarkm	size_t	satisf_elemsize;	/* if entry size is exceeded,
9956067Smarkm					 * this number of elements will be left,
10056067Smarkm					 * others will be deleted */
10156067Smarkm	struct timeval	max_lifetime;	/* if 0 then no check is made */
10256067Smarkm	enum cache_policy_t policy;	/* policy used for transformations */
10356067Smarkm};
10456067Smarkm
10556067Smarkm/* params, used for multipart entries */
10656067Smarkmstruct	mp_cache_entry_params
10756067Smarkm{
10856067Smarkm	/* inherited fields */
10956067Smarkm	enum cache_entry_t entry_type;
11056067Smarkm	char	*entry_name;
11156067Smarkm
11256067Smarkm	/* unique fields */
11356067Smarkm	size_t	max_elemsize;	/* if 0 then no check is made */
11456067Smarkm	size_t	max_sessions;	/* maximum number of active sessions */
11556067Smarkm
11656067Smarkm	struct timeval	max_lifetime;	/* maximum elements lifetime */
11756067Smarkm};
11856067Smarkm
11956067Smarkmstruct cache_ht_item_data_
12056067Smarkm{
12156067Smarkm    	/* key is the bytes sequence only - not the null-terminated string */
12256067Smarkm	char	*key;
12356067Smarkm    	size_t	key_size;
12456067Smarkm
12556067Smarkm	char	*value;
12656067Smarkm	size_t	value_size;
12756067Smarkm
12856067Smarkm	struct cache_policy_item_ *fifo_policy_item;
12956067Smarkm};
13056067Smarkm
13156067Smarkmstruct cache_ht_item_
13256067Smarkm{
13356067Smarkm	HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data;
13456067Smarkm};
13556067Smarkm
13656067Smarkmstruct cache_entry_
13756067Smarkm{
13856067Smarkm	char	*name;
13956067Smarkm	struct cache_entry_params *params;
14056067Smarkm};
14156067Smarkm
14256067Smarkmstruct cache_common_entry_
14357566Smarkm{
14456067Smarkm	char	*name;
14556067Smarkm	struct cache_entry_params *params;
14656067Smarkm
14757452Smarkm	struct common_cache_entry_params common_params;
14857452Smarkm
14957452Smarkm	HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items;
15057452Smarkm	size_t items_size;
15157452Smarkm
15257452Smarkm	/*
15357452Smarkm	 * Entry always has the FIFO policy, that is used to eliminate old
15457452Smarkm	 * elements (the ones, with lifetime more than max_lifetime). Besides,
15557452Smarkm	 * user can specify another policy to be applied, when there are too
15657452Smarkm	 * many elements in the entry. So policies_size can be 1 or 2.
15756067Smarkm	 */
15856067Smarkm	struct cache_policy_ **policies;
15956067Smarkm	size_t policies_size;
16056067Smarkm
16156067Smarkm	void	(*get_time_func)(struct timeval *);
16256067Smarkm};
16356067Smarkm
16456067Smarkmstruct cache_mp_data_item_ {
16556067Smarkm	char	*value;
16656067Smarkm	size_t	value_size;
167
168	TAILQ_ENTRY(cache_mp_data_item_) entries;
169};
170
171struct cache_mp_write_session_
172{
173	struct cache_mp_entry_	*parent_entry;
174
175	/*
176	 * All items are accumulated in this queue. When the session is
177	 * committed, they all will be copied to the multipart entry.
178	 */
179	TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items;
180	size_t	items_size;
181
182	TAILQ_ENTRY(cache_mp_write_session_) entries;
183};
184
185struct cache_mp_read_session_
186{
187	struct cache_mp_entry_ *parent_entry;
188	struct cache_mp_data_item_ *current_item;
189
190	TAILQ_ENTRY(cache_mp_read_session_) entries;
191};
192
193struct cache_mp_entry_
194{
195	char	*name;
196	struct cache_entry_params *params;
197
198	struct mp_cache_entry_params mp_params;
199
200	/* All opened write sessions */
201	TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head;
202	size_t	ws_size;
203
204	/* All opened read sessions */
205	TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head;
206	size_t	rs_size;
207
208	/*
209	 * completed_write_session is the committed write sessions. All read
210	 * sessions use data from it. If the completed_write_session is out of
211	 * date, but still in use by some of the read sessions, the newly
212	 * committed write session is stored in the pending_write_session.
213	 * In such a case, completed_write_session will be substituted with
214	 * pending_write_session as soon as it won't be used by any of
215	 * the read sessions.
216	 */
217	struct cache_mp_write_session_	*completed_write_session;
218	struct cache_mp_write_session_	*pending_write_session;
219	struct timeval	creation_time;
220	struct timeval	last_request_time;
221
222	void	(*get_time_func)(struct timeval *);
223};
224
225struct cache_
226{
227	struct cache_params params;
228
229	struct cache_entry_ **entries;
230	size_t	entries_capacity;
231	size_t	entries_size;
232};
233
234/* simple abstractions - for not to write "struct" every time */
235typedef struct cache_		*cache;
236typedef struct cache_entry_	*cache_entry;
237typedef struct cache_mp_write_session_	*cache_mp_write_session;
238typedef struct cache_mp_read_session_	*cache_mp_read_session;
239
240#define INVALID_CACHE		(NULL)
241#define INVALID_CACHE_ENTRY	(NULL)
242#define INVALID_CACHE_MP_WRITE_SESSION	(NULL)
243#define INVALID_CACHE_MP_READ_SESSION	(NULL)
244
245/*
246 * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety
247 * externally, by yourself.
248 */
249
250/* cache initialization/destruction routines */
251extern cache init_cache(struct cache_params const *);
252extern void destroy_cache(cache);
253
254/* cache entries manipulation routines */
255extern int register_cache_entry(cache, struct cache_entry_params const *);
256extern int unregister_cache_entry(cache, const char *);
257extern cache_entry find_cache_entry(cache, const char *);
258
259/* read/write operations used on common entries */
260extern int cache_read(cache_entry, const char *, size_t, char *, size_t *);
261extern int cache_write(cache_entry, const char *, size_t, char const *, size_t);
262
263/* read/write operations used on multipart entries */
264extern cache_mp_write_session open_cache_mp_write_session(cache_entry);
265extern int cache_mp_write(cache_mp_write_session, char *, size_t);
266extern void abandon_cache_mp_write_session(cache_mp_write_session);
267extern void close_cache_mp_write_session(cache_mp_write_session);
268
269extern cache_mp_read_session open_cache_mp_read_session(cache_entry);
270extern int cache_mp_read(cache_mp_read_session, char *, size_t *);
271extern void close_cache_mp_read_session(cache_mp_read_session);
272
273/* transformation routines */
274extern int transform_cache_entry(cache_entry, enum cache_transformation_t);
275extern int transform_cache_entry_part(cache_entry, enum cache_transformation_t,
276	const char *, size_t, enum part_position_t);
277
278#endif
279