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$
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 */
72194112Sdesstruct cache_params {
73158115Sume	void	(*get_time_func)(struct timeval *);
74158115Sume};
75158115Sume
76158115Sume/*
77158115Sume * base structure - normal_cache_entry_params and multipart_cache_entry_params
78158115Sume * are "inherited" from it
79158115Sume */
80194112Sdesstruct cache_entry_params {
81158115Sume	enum cache_entry_t entry_type;
82158115Sume	char	*entry_name;
83158115Sume};
84158115Sume
85158115Sume/* params, used for most entries */
86194112Sdesstruct common_cache_entry_params {
87194097Sdes	struct cache_entry_params cep;
88158115Sume
89158115Sume	size_t	cache_entries_size;
90158115Sume
91158115Sume	size_t	max_elemsize;		/* if 0 then no check is made */
92158115Sume	size_t	satisf_elemsize;	/* if entry size is exceeded,
93158115Sume					 * this number of elements will be left,
94158115Sume					 * others will be deleted */
95238094Sse	int	confidence_threshold;	/* number matching replies required */
96158115Sume	struct timeval	max_lifetime;	/* if 0 then no check is made */
97158115Sume	enum cache_policy_t policy;	/* policy used for transformations */
98158115Sume};
99158115Sume
100158115Sume/* params, used for multipart entries */
101194112Sdesstruct	mp_cache_entry_params {
102194097Sdes	struct cache_entry_params cep;
103158115Sume
104158115Sume	/* unique fields */
105158115Sume	size_t	max_elemsize;	/* if 0 then no check is made */
106158115Sume	size_t	max_sessions;	/* maximum number of active sessions */
107158115Sume
108158115Sume	struct timeval	max_lifetime;	/* maximum elements lifetime */
109158115Sume};
110158115Sume
111194112Sdesstruct cache_ht_item_data_ {
112158115Sume    	/* key is the bytes sequence only - not the null-terminated string */
113158115Sume	char	*key;
114158115Sume    	size_t	key_size;
115158115Sume
116158115Sume	char	*value;
117158115Sume	size_t	value_size;
118158115Sume
119158115Sume	struct cache_policy_item_ *fifo_policy_item;
120238094Sse	int	confidence;	/* incremented for each verification */
121158115Sume};
122158115Sume
123194112Sdesstruct cache_ht_item_ {
124158115Sume	HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data;
125158115Sume};
126158115Sume
127194112Sdesstruct cache_entry_ {
128158115Sume	char	*name;
129158115Sume	struct cache_entry_params *params;
130158115Sume};
131158115Sume
132194112Sdesstruct cache_common_entry_ {
133158115Sume	char	*name;
134158115Sume	struct cache_entry_params *params;
135158115Sume
136158115Sume	struct common_cache_entry_params common_params;
137158115Sume
138158115Sume	HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items;
139158115Sume	size_t items_size;
140158115Sume
141158115Sume	/*
142158115Sume	 * Entry always has the FIFO policy, that is used to eliminate old
143158115Sume	 * elements (the ones, with lifetime more than max_lifetime). Besides,
144158115Sume	 * user can specify another policy to be applied, when there are too
145158115Sume	 * many elements in the entry. So policies_size can be 1 or 2.
146158115Sume	 */
147158115Sume	struct cache_policy_ **policies;
148158115Sume	size_t policies_size;
149158115Sume
150158115Sume	void	(*get_time_func)(struct timeval *);
151158115Sume};
152158115Sume
153158115Sumestruct cache_mp_data_item_ {
154158115Sume	char	*value;
155158115Sume	size_t	value_size;
156158115Sume
157158115Sume	TAILQ_ENTRY(cache_mp_data_item_) entries;
158158115Sume};
159158115Sume
160194112Sdesstruct cache_mp_write_session_ {
161158115Sume	struct cache_mp_entry_	*parent_entry;
162158115Sume
163158115Sume	/*
164158115Sume	 * All items are accumulated in this queue. When the session is
165158115Sume	 * committed, they all will be copied to the multipart entry.
166158115Sume	 */
167158115Sume	TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items;
168158115Sume	size_t	items_size;
169158115Sume
170158115Sume	TAILQ_ENTRY(cache_mp_write_session_) entries;
171158115Sume};
172158115Sume
173194112Sdesstruct cache_mp_read_session_ {
174158115Sume	struct cache_mp_entry_ *parent_entry;
175158115Sume	struct cache_mp_data_item_ *current_item;
176158115Sume
177158115Sume	TAILQ_ENTRY(cache_mp_read_session_) entries;
178158115Sume};
179158115Sume
180194112Sdesstruct cache_mp_entry_ {
181158115Sume	char	*name;
182158115Sume	struct cache_entry_params *params;
183158115Sume
184158115Sume	struct mp_cache_entry_params mp_params;
185158115Sume
186158115Sume	/* All opened write sessions */
187158115Sume	TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head;
188158115Sume	size_t	ws_size;
189158115Sume
190158115Sume	/* All opened read sessions */
191158115Sume	TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head;
192158115Sume	size_t	rs_size;
193158115Sume
194158115Sume	/*
195158115Sume	 * completed_write_session is the committed write sessions. All read
196158115Sume	 * sessions use data from it. If the completed_write_session is out of
197158115Sume	 * date, but still in use by some of the read sessions, the newly
198158115Sume	 * committed write session is stored in the pending_write_session.
199158115Sume	 * In such a case, completed_write_session will be substituted with
200158115Sume	 * pending_write_session as soon as it won't be used by any of
201158115Sume	 * the read sessions.
202158115Sume	 */
203158115Sume	struct cache_mp_write_session_	*completed_write_session;
204158115Sume	struct cache_mp_write_session_	*pending_write_session;
205158115Sume	struct timeval	creation_time;
206158115Sume	struct timeval	last_request_time;
207158115Sume
208158115Sume	void	(*get_time_func)(struct timeval *);
209158115Sume};
210158115Sume
211194112Sdesstruct cache_ {
212158115Sume	struct cache_params params;
213158115Sume
214158115Sume	struct cache_entry_ **entries;
215158115Sume	size_t	entries_capacity;
216158115Sume	size_t	entries_size;
217158115Sume};
218158115Sume
219158115Sume/* simple abstractions - for not to write "struct" every time */
220158115Sumetypedef struct cache_		*cache;
221158115Sumetypedef struct cache_entry_	*cache_entry;
222158115Sumetypedef struct cache_mp_write_session_	*cache_mp_write_session;
223158115Sumetypedef struct cache_mp_read_session_	*cache_mp_read_session;
224158115Sume
225158115Sume#define INVALID_CACHE		(NULL)
226158115Sume#define INVALID_CACHE_ENTRY	(NULL)
227158115Sume#define INVALID_CACHE_MP_WRITE_SESSION	(NULL)
228158115Sume#define INVALID_CACHE_MP_READ_SESSION	(NULL)
229158115Sume
230158115Sume/*
231158115Sume * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety
232158115Sume * externally, by yourself.
233158115Sume */
234158115Sume
235158115Sume/* cache initialization/destruction routines */
236194112Sdescache init_cache(struct cache_params const *);
237194112Sdesvoid destroy_cache(cache);
238158115Sume
239158115Sume/* cache entries manipulation routines */
240194112Sdesint register_cache_entry(cache, struct cache_entry_params const *);
241194112Sdesint unregister_cache_entry(cache, const char *);
242194112Sdescache_entry find_cache_entry(cache, const char *);
243158115Sume
244158115Sume/* read/write operations used on common entries */
245194112Sdesint cache_read(cache_entry, const char *, size_t, char *, size_t *);
246194112Sdesint cache_write(cache_entry, const char *, size_t, char const *, size_t);
247158115Sume
248158115Sume/* read/write operations used on multipart entries */
249194112Sdescache_mp_write_session open_cache_mp_write_session(cache_entry);
250194112Sdesint cache_mp_write(cache_mp_write_session, char *, size_t);
251194112Sdesvoid abandon_cache_mp_write_session(cache_mp_write_session);
252194112Sdesvoid close_cache_mp_write_session(cache_mp_write_session);
253158115Sume
254194112Sdescache_mp_read_session open_cache_mp_read_session(cache_entry);
255194112Sdesint cache_mp_read(cache_mp_read_session, char *, size_t *);
256194112Sdesvoid close_cache_mp_read_session(cache_mp_read_session);
257158115Sume
258158115Sume/* transformation routines */
259194112Sdesint transform_cache_entry(cache_entry, enum cache_transformation_t);
260194112Sdesint transform_cache_entry_part(cache_entry, enum cache_transformation_t,
261158115Sume	const char *, size_t, enum part_position_t);
262158115Sume
263158115Sume#endif
264