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 35enum cache_entry_t { 36 CET_COMMON = 0, /* cache item is atomic */ 37 CET_MULTIPART /* cache item is formed part by part */ 38}; 39 40enum 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 */ 46enum 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 */ 53enum 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 */ 63enum 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 */ 72struct 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 */ 80struct cache_entry_params { 81 enum cache_entry_t entry_type; 82 char *entry_name; 83}; 84 85/* params, used for most entries */ 86struct 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 */ 101struct 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 111struct 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 123struct cache_ht_item_ { 124 HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data; 125}; 126 127struct cache_entry_ { 128 char *name; 129 struct cache_entry_params *params; 130}; 131 132struct 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 153struct cache_mp_data_item_ { 154 char *value; 155 size_t value_size; 156 157 TAILQ_ENTRY(cache_mp_data_item_) entries; 158}; 159 160struct 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 173struct 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 180struct 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 211struct 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 */ 220typedef struct cache_ *cache; 221typedef struct cache_entry_ *cache_entry; 222typedef struct cache_mp_write_session_ *cache_mp_write_session; 223typedef 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 */ 236cache init_cache(struct cache_params const *); 237void destroy_cache(cache); 238 239/* cache entries manipulation routines */ 240int register_cache_entry(cache, struct cache_entry_params const *); 241int unregister_cache_entry(cache, const char *); 242cache_entry find_cache_entry(cache, const char *); 243 244/* read/write operations used on common entries */ 245int cache_read(cache_entry, const char *, size_t, char *, size_t *); 246int cache_write(cache_entry, const char *, size_t, char const *, size_t); 247 248/* read/write operations used on multipart entries */ 249cache_mp_write_session open_cache_mp_write_session(cache_entry); 250int cache_mp_write(cache_mp_write_session, char *, size_t); 251void abandon_cache_mp_write_session(cache_mp_write_session); 252void close_cache_mp_write_session(cache_mp_write_session); 253 254cache_mp_read_session open_cache_mp_read_session(cache_entry); 255int cache_mp_read(cache_mp_read_session, char *, size_t *); 256void close_cache_mp_read_session(cache_mp_read_session); 257 258/* transformation routines */ 259int transform_cache_entry(cache_entry, enum cache_transformation_t); 260int transform_cache_entry_part(cache_entry, enum cache_transformation_t, 261 const char *, size_t, enum part_position_t); 262 263#endif 264