]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/nscd/cachelib.h
zfs: merge openzfs/zfs@9198de8f1
[FreeBSD/FreeBSD.git] / usr.sbin / nscd / cachelib.h
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
27 #ifndef __NSCD_CACHELIB_H__
28 #define __NSCD_CACHELIB_H__
29
30 #include "hashtable.h"
31 #include "cacheplcs.h"
32
33 enum cache_entry_t      {
34         CET_COMMON = 0, /* cache item is atomic */
35         CET_MULTIPART   /* cache item is formed part by part */
36 };
37
38 enum cache_transformation_t {
39         CTT_FLUSH = 0,  /* flush the cache - delete all obsolete items */
40         CTT_CLEAR = 1   /* delete all items in the cache */
41 };
42
43 /* cache deletion policy type enum */
44 enum cache_policy_t {
45         CPT_FIFO = 0,   /* first-in first-out */
46         CPT_LRU = 1,    /* least recently used */
47         CPT_LFU = 2     /* least frequently used */
48 };
49
50 /* multipart sessions can be used for reading and writing */
51 enum cache_mp_session_t {
52         CMPT_READ_SESSION,
53         CMPT_WRITE_SESSION
54 };
55
56 /*
57  * When doing partial transformations of entries (which are applied for
58  * elements with keys, that contain specified buffer in its left or
59  * right part), this enum will show the needed position of the key part.
60  */
61 enum part_position_t {
62         KPPT_LEFT,
63         KPPT_RIGHT
64 };
65
66 /* num_levels attribute is obsolete, i think - user can always emulate it
67  * by using one entry.
68  * get_time_func is needed to have the clocks-independent counter
69  */
70 struct cache_params {
71         void    (*get_time_func)(struct timeval *);
72 };
73
74 /*
75  * base structure - normal_cache_entry_params and multipart_cache_entry_params
76  * are "inherited" from it
77  */
78 struct cache_entry_params {
79         enum cache_entry_t entry_type;
80         char    *entry_name;
81 };
82
83 /* params, used for most entries */
84 struct common_cache_entry_params {
85         struct cache_entry_params cep;
86
87         size_t  cache_entries_size;
88
89         size_t  max_elemsize;           /* if 0 then no check is made */
90         size_t  satisf_elemsize;        /* if entry size is exceeded,
91                                          * this number of elements will be left,
92                                          * others will be deleted */
93         int     confidence_threshold;   /* number matching replies required */
94         struct timeval  max_lifetime;   /* if 0 then no check is made */
95         enum cache_policy_t policy;     /* policy used for transformations */
96 };
97
98 /* params, used for multipart entries */
99 struct  mp_cache_entry_params {
100         struct cache_entry_params cep;
101
102         /* unique fields */
103         size_t  max_elemsize;   /* if 0 then no check is made */
104         size_t  max_sessions;   /* maximum number of active sessions */
105
106         struct timeval  max_lifetime;   /* maximum elements lifetime */
107 };
108
109 struct cache_ht_item_data_ {
110         /* key is the bytes sequence only - not the null-terminated string */
111         char    *key;
112         size_t  key_size;
113
114         char    *value;
115         size_t  value_size;
116
117         struct cache_policy_item_ *fifo_policy_item;
118         int     confidence;     /* incremented for each verification */
119 };
120
121 struct cache_ht_item_ {
122         HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data;
123 };
124
125 struct cache_entry_ {
126         char    *name;
127         struct cache_entry_params *params;
128 };
129
130 struct cache_common_entry_ {
131         char    *name;
132         struct cache_entry_params *params;
133
134         struct common_cache_entry_params common_params;
135
136         HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items;
137         size_t items_size;
138
139         /*
140          * Entry always has the FIFO policy, that is used to eliminate old
141          * elements (the ones, with lifetime more than max_lifetime). Besides,
142          * user can specify another policy to be applied, when there are too
143          * many elements in the entry. So policies_size can be 1 or 2.
144          */
145         struct cache_policy_ **policies;
146         size_t policies_size;
147
148         void    (*get_time_func)(struct timeval *);
149 };
150
151 struct cache_mp_data_item_ {
152         char    *value;
153         size_t  value_size;
154
155         TAILQ_ENTRY(cache_mp_data_item_) entries;
156 };
157
158 struct cache_mp_write_session_ {
159         struct cache_mp_entry_  *parent_entry;
160
161         /*
162          * All items are accumulated in this queue. When the session is
163          * committed, they all will be copied to the multipart entry.
164          */
165         TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items;
166         size_t  items_size;
167
168         TAILQ_ENTRY(cache_mp_write_session_) entries;
169 };
170
171 struct cache_mp_read_session_ {
172         struct cache_mp_entry_ *parent_entry;
173         struct cache_mp_data_item_ *current_item;
174
175         TAILQ_ENTRY(cache_mp_read_session_) entries;
176 };
177
178 struct cache_mp_entry_ {
179         char    *name;
180         struct cache_entry_params *params;
181
182         struct mp_cache_entry_params mp_params;
183
184         /* All opened write sessions */
185         TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head;
186         size_t  ws_size;
187
188         /* All opened read sessions */
189         TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head;
190         size_t  rs_size;
191
192         /*
193          * completed_write_session is the committed write sessions. All read
194          * sessions use data from it. If the completed_write_session is out of
195          * date, but still in use by some of the read sessions, the newly
196          * committed write session is stored in the pending_write_session.
197          * In such a case, completed_write_session will be substituted with
198          * pending_write_session as soon as it won't be used by any of
199          * the read sessions.
200          */
201         struct cache_mp_write_session_  *completed_write_session;
202         struct cache_mp_write_session_  *pending_write_session;
203         struct timeval  creation_time;
204         struct timeval  last_request_time;
205
206         void    (*get_time_func)(struct timeval *);
207 };
208
209 struct cache_ {
210         struct cache_params params;
211
212         struct cache_entry_ **entries;
213         size_t  entries_capacity;
214         size_t  entries_size;
215 };
216
217 /* simple abstractions - for not to write "struct" every time */
218 typedef struct cache_           *cache;
219 typedef struct cache_entry_     *cache_entry;
220 typedef struct cache_mp_write_session_  *cache_mp_write_session;
221 typedef struct cache_mp_read_session_   *cache_mp_read_session;
222
223 #define INVALID_CACHE           (NULL)
224 #define INVALID_CACHE_ENTRY     (NULL)
225 #define INVALID_CACHE_MP_WRITE_SESSION  (NULL)
226 #define INVALID_CACHE_MP_READ_SESSION   (NULL)
227
228 /*
229  * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety
230  * externally, by yourself.
231  */
232
233 /* cache initialization/destruction routines */
234 cache init_cache(struct cache_params const *);
235 void destroy_cache(cache);
236
237 /* cache entries manipulation routines */
238 int register_cache_entry(cache, struct cache_entry_params const *);
239 int unregister_cache_entry(cache, const char *);
240 cache_entry find_cache_entry(cache, const char *);
241
242 /* read/write operations used on common entries */
243 int cache_read(cache_entry, const char *, size_t, char *, size_t *);
244 int cache_write(cache_entry, const char *, size_t, char const *, size_t);
245
246 /* read/write operations used on multipart entries */
247 cache_mp_write_session open_cache_mp_write_session(cache_entry);
248 int cache_mp_write(cache_mp_write_session, char *, size_t);
249 void abandon_cache_mp_write_session(cache_mp_write_session);
250 void close_cache_mp_write_session(cache_mp_write_session);
251
252 cache_mp_read_session open_cache_mp_read_session(cache_entry);
253 int cache_mp_read(cache_mp_read_session, char *, size_t *);
254 void close_cache_mp_read_session(cache_mp_read_session);
255
256 /* transformation routines */
257 int transform_cache_entry(cache_entry, enum cache_transformation_t);
258 int transform_cache_entry_part(cache_entry, enum cache_transformation_t,
259         const char *, size_t, enum part_position_t);
260
261 #endif