2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #ifndef __NSCD_CACHELIB_H__
30 #define __NSCD_CACHELIB_H__
32 #include "hashtable.h"
33 #include "cacheplcs.h"
36 CET_COMMON = 0, /* cache item is atomic */
37 CET_MULTIPART /* cache item is formed part by part */
40 enum cache_transformation_t {
41 CTT_FLUSH = 0, /* flush the cache - delete all obsolete items */
42 CTT_CLEAR = 1 /* delete all items in the cache */
45 /* cache deletion policy type enum */
47 CPT_FIFO = 0, /* first-in first-out */
48 CPT_LRU = 1, /* least recently used */
49 CPT_LFU = 2 /* least frequently used */
52 /* multipart sessions can be used for reading and writing */
53 enum cache_mp_session_t {
59 * When doing partial transformations of entries (which are applied for
60 * elements with keys, that contain specified buffer in its left or
61 * right part), this enum will show the needed position of the key part.
63 enum part_position_t {
68 /* num_levels attribute is obsolete, i think - user can always emulate it
70 * get_time_func is needed to have the clocks-independent counter
73 void (*get_time_func)(struct timeval *);
77 * base structure - normal_cache_entry_params and multipart_cache_entry_params
78 * are "inherited" from it
80 struct cache_entry_params {
81 enum cache_entry_t entry_type;
85 /* params, used for most entries */
86 struct common_cache_entry_params {
87 struct cache_entry_params cep;
89 size_t cache_entries_size;
91 size_t max_elemsize; /* if 0 then no check is made */
92 size_t satisf_elemsize; /* if entry size is exceeded,
93 * this number of elements will be left,
94 * others will be deleted */
95 int confidence_threshold; /* number matching replies required */
96 struct timeval max_lifetime; /* if 0 then no check is made */
97 enum cache_policy_t policy; /* policy used for transformations */
100 /* params, used for multipart entries */
101 struct mp_cache_entry_params {
102 struct cache_entry_params cep;
105 size_t max_elemsize; /* if 0 then no check is made */
106 size_t max_sessions; /* maximum number of active sessions */
108 struct timeval max_lifetime; /* maximum elements lifetime */
111 struct cache_ht_item_data_ {
112 /* key is the bytes sequence only - not the null-terminated string */
119 struct cache_policy_item_ *fifo_policy_item;
120 int confidence; /* incremented for each verification */
123 struct cache_ht_item_ {
124 HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data;
127 struct cache_entry_ {
129 struct cache_entry_params *params;
132 struct cache_common_entry_ {
134 struct cache_entry_params *params;
136 struct common_cache_entry_params common_params;
138 HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items;
142 * Entry always has the FIFO policy, that is used to eliminate old
143 * elements (the ones, with lifetime more than max_lifetime). Besides,
144 * user can specify another policy to be applied, when there are too
145 * many elements in the entry. So policies_size can be 1 or 2.
147 struct cache_policy_ **policies;
148 size_t policies_size;
150 void (*get_time_func)(struct timeval *);
153 struct cache_mp_data_item_ {
157 TAILQ_ENTRY(cache_mp_data_item_) entries;
160 struct cache_mp_write_session_ {
161 struct cache_mp_entry_ *parent_entry;
164 * All items are accumulated in this queue. When the session is
165 * committed, they all will be copied to the multipart entry.
167 TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items;
170 TAILQ_ENTRY(cache_mp_write_session_) entries;
173 struct cache_mp_read_session_ {
174 struct cache_mp_entry_ *parent_entry;
175 struct cache_mp_data_item_ *current_item;
177 TAILQ_ENTRY(cache_mp_read_session_) entries;
180 struct cache_mp_entry_ {
182 struct cache_entry_params *params;
184 struct mp_cache_entry_params mp_params;
186 /* All opened write sessions */
187 TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head;
190 /* All opened read sessions */
191 TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head;
195 * completed_write_session is the committed write sessions. All read
196 * sessions use data from it. If the completed_write_session is out of
197 * date, but still in use by some of the read sessions, the newly
198 * committed write session is stored in the pending_write_session.
199 * In such a case, completed_write_session will be substituted with
200 * pending_write_session as soon as it won't be used by any of
203 struct cache_mp_write_session_ *completed_write_session;
204 struct cache_mp_write_session_ *pending_write_session;
205 struct timeval creation_time;
206 struct timeval last_request_time;
208 void (*get_time_func)(struct timeval *);
212 struct cache_params params;
214 struct cache_entry_ **entries;
215 size_t entries_capacity;
219 /* simple abstractions - for not to write "struct" every time */
220 typedef struct cache_ *cache;
221 typedef struct cache_entry_ *cache_entry;
222 typedef struct cache_mp_write_session_ *cache_mp_write_session;
223 typedef struct cache_mp_read_session_ *cache_mp_read_session;
225 #define INVALID_CACHE (NULL)
226 #define INVALID_CACHE_ENTRY (NULL)
227 #define INVALID_CACHE_MP_WRITE_SESSION (NULL)
228 #define INVALID_CACHE_MP_READ_SESSION (NULL)
231 * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety
232 * externally, by yourself.
235 /* cache initialization/destruction routines */
236 cache init_cache(struct cache_params const *);
237 void destroy_cache(cache);
239 /* cache entries manipulation routines */
240 int register_cache_entry(cache, struct cache_entry_params const *);
241 int unregister_cache_entry(cache, const char *);
242 cache_entry find_cache_entry(cache, const char *);
244 /* read/write operations used on common entries */
245 int cache_read(cache_entry, const char *, size_t, char *, size_t *);
246 int cache_write(cache_entry, const char *, size_t, char const *, size_t);
248 /* read/write operations used on multipart entries */
249 cache_mp_write_session open_cache_mp_write_session(cache_entry);
250 int cache_mp_write(cache_mp_write_session, char *, size_t);
251 void abandon_cache_mp_write_session(cache_mp_write_session);
252 void close_cache_mp_write_session(cache_mp_write_session);
254 cache_mp_read_session open_cache_mp_read_session(cache_entry);
255 int cache_mp_read(cache_mp_read_session, char *, size_t *);
256 void close_cache_mp_read_session(cache_mp_read_session);
258 /* transformation routines */
259 int transform_cache_entry(cache_entry, enum cache_transformation_t);
260 int transform_cache_entry_part(cache_entry, enum cache_transformation_t,
261 const char *, size_t, enum part_position_t);