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 * $FreeBSD$ 27 */ 28 29 #ifndef __NSCD_CACHELIB_H__ 30 #define __NSCD_CACHELIB_H__ 31 32 #include "hashtable.h" 33 #include "cacheplcs.h" 34 35 enum cache_entry_t { 36 CET_COMMON = 0, /* cache item is atomic */ 37 CET_MULTIPART /* cache item is formed part by part */ 38 }; 39 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 */ 43 }; 44 45 /* cache deletion policy type enum */ 46 enum cache_policy_t { 47 CPT_FIFO = 0, /* first-in first-out */ 48 CPT_LRU = 1, /* least recently used */ 49 CPT_LFU = 2 /* least frequently used */ 50 }; 51 52 /* multipart sessions can be used for reading and writing */ 53 enum cache_mp_session_t { 54 CMPT_READ_SESSION, 55 CMPT_WRITE_SESSION 56 }; 57 58 /* 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. 62 */ 63 enum part_position_t { 64 KPPT_LEFT, 65 KPPT_RIGHT 66 }; 67 68 /* num_levels attribute is obsolete, i think - user can always emulate it 69 * by using one entry. 70 * get_time_func is needed to have the clocks-independent counter 71 */ 72 struct cache_params { 73 void (*get_time_func)(struct timeval *); 74 }; 75 76 /* 77 * base structure - normal_cache_entry_params and multipart_cache_entry_params 78 * are "inherited" from it 79 */ 80 struct cache_entry_params { 81 enum cache_entry_t entry_type; 82 char *entry_name; 83 }; 84 85 /* params, used for most entries */ 86 struct common_cache_entry_params { 87 struct cache_entry_params cep; 88 89 size_t cache_entries_size; 90 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 */ 98 }; 99 100 /* params, used for multipart entries */ 101 struct mp_cache_entry_params { 102 struct cache_entry_params cep; 103 104 /* unique fields */ 105 size_t max_elemsize; /* if 0 then no check is made */ 106 size_t max_sessions; /* maximum number of active sessions */ 107 108 struct timeval max_lifetime; /* maximum elements lifetime */ 109 }; 110 111 struct cache_ht_item_data_ { 112 /* key is the bytes sequence only - not the null-terminated string */ 113 char *key; 114 size_t key_size; 115 116 char *value; 117 size_t value_size; 118 119 struct cache_policy_item_ *fifo_policy_item; 120 int confidence; /* incremented for each verification */ 121 }; 122 123 struct cache_ht_item_ { 124 HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data; 125 }; 126 127 struct cache_entry_ { 128 char *name; 129 struct cache_entry_params *params; 130 }; 131 132 struct cache_common_entry_ { 133 char *name; 134 struct cache_entry_params *params; 135 136 struct common_cache_entry_params common_params; 137 138 HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items; 139 size_t items_size; 140 141 /* 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. 146 */ 147 struct cache_policy_ **policies; 148 size_t policies_size; 149 150 void (*get_time_func)(struct timeval *); 151 }; 152 153 struct cache_mp_data_item_ { 154 char *value; 155 size_t value_size; 156 157 TAILQ_ENTRY(cache_mp_data_item_) entries; 158 }; 159 160 struct cache_mp_write_session_ { 161 struct cache_mp_entry_ *parent_entry; 162 163 /* 164 * All items are accumulated in this queue. When the session is 165 * committed, they all will be copied to the multipart entry. 166 */ 167 TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items; 168 size_t items_size; 169 170 TAILQ_ENTRY(cache_mp_write_session_) entries; 171 }; 172 173 struct cache_mp_read_session_ { 174 struct cache_mp_entry_ *parent_entry; 175 struct cache_mp_data_item_ *current_item; 176 177 TAILQ_ENTRY(cache_mp_read_session_) entries; 178 }; 179 180 struct cache_mp_entry_ { 181 char *name; 182 struct cache_entry_params *params; 183 184 struct mp_cache_entry_params mp_params; 185 186 /* All opened write sessions */ 187 TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head; 188 size_t ws_size; 189 190 /* All opened read sessions */ 191 TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head; 192 size_t rs_size; 193 194 /* 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 201 * the read sessions. 202 */ 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; 207 208 void (*get_time_func)(struct timeval *); 209 }; 210 211 struct cache_ { 212 struct cache_params params; 213 214 struct cache_entry_ **entries; 215 size_t entries_capacity; 216 size_t entries_size; 217 }; 218 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; 224 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) 229 230 /* 231 * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety 232 * externally, by yourself. 233 */ 234 235 /* cache initialization/destruction routines */ 236 cache init_cache(struct cache_params const *); 237 void destroy_cache(cache); 238 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 *); 243 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); 247 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); 253 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); 257 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); 262 263 #endif 264