106a99fe3SHajimu UMEMOTO /*- 206a99fe3SHajimu UMEMOTO * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru> 306a99fe3SHajimu UMEMOTO * All rights reserved. 406a99fe3SHajimu UMEMOTO * 506a99fe3SHajimu UMEMOTO * Redistribution and use in source and binary forms, with or without 606a99fe3SHajimu UMEMOTO * modification, are permitted provided that the following conditions 706a99fe3SHajimu UMEMOTO * are met: 806a99fe3SHajimu UMEMOTO * 1. Redistributions of source code must retain the above copyright 906a99fe3SHajimu UMEMOTO * notice, this list of conditions and the following disclaimer. 1006a99fe3SHajimu UMEMOTO * 2. Redistributions in binary form must reproduce the above copyright 1106a99fe3SHajimu UMEMOTO * notice, this list of conditions and the following disclaimer in the 1206a99fe3SHajimu UMEMOTO * documentation and/or other materials provided with the distribution. 1306a99fe3SHajimu UMEMOTO * 1406a99fe3SHajimu UMEMOTO * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1506a99fe3SHajimu UMEMOTO * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1606a99fe3SHajimu UMEMOTO * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1706a99fe3SHajimu UMEMOTO * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1806a99fe3SHajimu UMEMOTO * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1906a99fe3SHajimu UMEMOTO * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2006a99fe3SHajimu UMEMOTO * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2106a99fe3SHajimu UMEMOTO * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2206a99fe3SHajimu UMEMOTO * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2306a99fe3SHajimu UMEMOTO * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2406a99fe3SHajimu UMEMOTO * SUCH DAMAGE. 2506a99fe3SHajimu UMEMOTO */ 2606a99fe3SHajimu UMEMOTO 27db1bdf2bSMichael Bushkov #ifndef __NSCD_CACHELIB_H__ 28db1bdf2bSMichael Bushkov #define __NSCD_CACHELIB_H__ 2906a99fe3SHajimu UMEMOTO 3006a99fe3SHajimu UMEMOTO #include "hashtable.h" 3106a99fe3SHajimu UMEMOTO #include "cacheplcs.h" 3206a99fe3SHajimu UMEMOTO 3306a99fe3SHajimu UMEMOTO enum cache_entry_t { 3406a99fe3SHajimu UMEMOTO CET_COMMON = 0, /* cache item is atomic */ 3506a99fe3SHajimu UMEMOTO CET_MULTIPART /* cache item is formed part by part */ 3606a99fe3SHajimu UMEMOTO }; 3706a99fe3SHajimu UMEMOTO 3806a99fe3SHajimu UMEMOTO enum cache_transformation_t { 3906a99fe3SHajimu UMEMOTO CTT_FLUSH = 0, /* flush the cache - delete all obsolete items */ 4006a99fe3SHajimu UMEMOTO CTT_CLEAR = 1 /* delete all items in the cache */ 4106a99fe3SHajimu UMEMOTO }; 4206a99fe3SHajimu UMEMOTO 4306a99fe3SHajimu UMEMOTO /* cache deletion policy type enum */ 4406a99fe3SHajimu UMEMOTO enum cache_policy_t { 4506a99fe3SHajimu UMEMOTO CPT_FIFO = 0, /* first-in first-out */ 4606a99fe3SHajimu UMEMOTO CPT_LRU = 1, /* least recently used */ 4706a99fe3SHajimu UMEMOTO CPT_LFU = 2 /* least frequently used */ 4806a99fe3SHajimu UMEMOTO }; 4906a99fe3SHajimu UMEMOTO 5006a99fe3SHajimu UMEMOTO /* multipart sessions can be used for reading and writing */ 5106a99fe3SHajimu UMEMOTO enum cache_mp_session_t { 5206a99fe3SHajimu UMEMOTO CMPT_READ_SESSION, 5306a99fe3SHajimu UMEMOTO CMPT_WRITE_SESSION 5406a99fe3SHajimu UMEMOTO }; 5506a99fe3SHajimu UMEMOTO 5606a99fe3SHajimu UMEMOTO /* 5706a99fe3SHajimu UMEMOTO * When doing partial transformations of entries (which are applied for 5806a99fe3SHajimu UMEMOTO * elements with keys, that contain specified buffer in its left or 5906a99fe3SHajimu UMEMOTO * right part), this enum will show the needed position of the key part. 6006a99fe3SHajimu UMEMOTO */ 6106a99fe3SHajimu UMEMOTO enum part_position_t { 6206a99fe3SHajimu UMEMOTO KPPT_LEFT, 6306a99fe3SHajimu UMEMOTO KPPT_RIGHT 6406a99fe3SHajimu UMEMOTO }; 6506a99fe3SHajimu UMEMOTO 6606a99fe3SHajimu UMEMOTO /* num_levels attribute is obsolete, i think - user can always emulate it 6706a99fe3SHajimu UMEMOTO * by using one entry. 6806a99fe3SHajimu UMEMOTO * get_time_func is needed to have the clocks-independent counter 6906a99fe3SHajimu UMEMOTO */ 70d2432adbSDag-Erling Smørgrav struct cache_params { 7106a99fe3SHajimu UMEMOTO void (*get_time_func)(struct timeval *); 7206a99fe3SHajimu UMEMOTO }; 7306a99fe3SHajimu UMEMOTO 7406a99fe3SHajimu UMEMOTO /* 7506a99fe3SHajimu UMEMOTO * base structure - normal_cache_entry_params and multipart_cache_entry_params 7606a99fe3SHajimu UMEMOTO * are "inherited" from it 7706a99fe3SHajimu UMEMOTO */ 78d2432adbSDag-Erling Smørgrav struct cache_entry_params { 7906a99fe3SHajimu UMEMOTO enum cache_entry_t entry_type; 8006a99fe3SHajimu UMEMOTO char *entry_name; 8106a99fe3SHajimu UMEMOTO }; 8206a99fe3SHajimu UMEMOTO 8306a99fe3SHajimu UMEMOTO /* params, used for most entries */ 84d2432adbSDag-Erling Smørgrav struct common_cache_entry_params { 8527f2bc9eSDag-Erling Smørgrav struct cache_entry_params cep; 8606a99fe3SHajimu UMEMOTO 8706a99fe3SHajimu UMEMOTO size_t cache_entries_size; 8806a99fe3SHajimu UMEMOTO 8906a99fe3SHajimu UMEMOTO size_t max_elemsize; /* if 0 then no check is made */ 9006a99fe3SHajimu UMEMOTO size_t satisf_elemsize; /* if entry size is exceeded, 9106a99fe3SHajimu UMEMOTO * this number of elements will be left, 9206a99fe3SHajimu UMEMOTO * others will be deleted */ 93*a397989dSStefan Eßer int confidence_threshold; /* number matching replies required */ 9406a99fe3SHajimu UMEMOTO struct timeval max_lifetime; /* if 0 then no check is made */ 9506a99fe3SHajimu UMEMOTO enum cache_policy_t policy; /* policy used for transformations */ 9606a99fe3SHajimu UMEMOTO }; 9706a99fe3SHajimu UMEMOTO 9806a99fe3SHajimu UMEMOTO /* params, used for multipart entries */ 99d2432adbSDag-Erling Smørgrav struct mp_cache_entry_params { 10027f2bc9eSDag-Erling Smørgrav struct cache_entry_params cep; 10106a99fe3SHajimu UMEMOTO 10206a99fe3SHajimu UMEMOTO /* unique fields */ 10306a99fe3SHajimu UMEMOTO size_t max_elemsize; /* if 0 then no check is made */ 10406a99fe3SHajimu UMEMOTO size_t max_sessions; /* maximum number of active sessions */ 10506a99fe3SHajimu UMEMOTO 10606a99fe3SHajimu UMEMOTO struct timeval max_lifetime; /* maximum elements lifetime */ 10706a99fe3SHajimu UMEMOTO }; 10806a99fe3SHajimu UMEMOTO 109d2432adbSDag-Erling Smørgrav struct cache_ht_item_data_ { 11006a99fe3SHajimu UMEMOTO /* key is the bytes sequence only - not the null-terminated string */ 11106a99fe3SHajimu UMEMOTO char *key; 11206a99fe3SHajimu UMEMOTO size_t key_size; 11306a99fe3SHajimu UMEMOTO 11406a99fe3SHajimu UMEMOTO char *value; 11506a99fe3SHajimu UMEMOTO size_t value_size; 11606a99fe3SHajimu UMEMOTO 11706a99fe3SHajimu UMEMOTO struct cache_policy_item_ *fifo_policy_item; 118*a397989dSStefan Eßer int confidence; /* incremented for each verification */ 11906a99fe3SHajimu UMEMOTO }; 12006a99fe3SHajimu UMEMOTO 121d2432adbSDag-Erling Smørgrav struct cache_ht_item_ { 12206a99fe3SHajimu UMEMOTO HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data; 12306a99fe3SHajimu UMEMOTO }; 12406a99fe3SHajimu UMEMOTO 125d2432adbSDag-Erling Smørgrav struct cache_entry_ { 12606a99fe3SHajimu UMEMOTO char *name; 12706a99fe3SHajimu UMEMOTO struct cache_entry_params *params; 12806a99fe3SHajimu UMEMOTO }; 12906a99fe3SHajimu UMEMOTO 130d2432adbSDag-Erling Smørgrav struct cache_common_entry_ { 13106a99fe3SHajimu UMEMOTO char *name; 13206a99fe3SHajimu UMEMOTO struct cache_entry_params *params; 13306a99fe3SHajimu UMEMOTO 13406a99fe3SHajimu UMEMOTO struct common_cache_entry_params common_params; 13506a99fe3SHajimu UMEMOTO 13606a99fe3SHajimu UMEMOTO HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items; 13706a99fe3SHajimu UMEMOTO size_t items_size; 13806a99fe3SHajimu UMEMOTO 13906a99fe3SHajimu UMEMOTO /* 14006a99fe3SHajimu UMEMOTO * Entry always has the FIFO policy, that is used to eliminate old 14106a99fe3SHajimu UMEMOTO * elements (the ones, with lifetime more than max_lifetime). Besides, 14206a99fe3SHajimu UMEMOTO * user can specify another policy to be applied, when there are too 14306a99fe3SHajimu UMEMOTO * many elements in the entry. So policies_size can be 1 or 2. 14406a99fe3SHajimu UMEMOTO */ 14506a99fe3SHajimu UMEMOTO struct cache_policy_ **policies; 14606a99fe3SHajimu UMEMOTO size_t policies_size; 14706a99fe3SHajimu UMEMOTO 14806a99fe3SHajimu UMEMOTO void (*get_time_func)(struct timeval *); 14906a99fe3SHajimu UMEMOTO }; 15006a99fe3SHajimu UMEMOTO 15106a99fe3SHajimu UMEMOTO struct cache_mp_data_item_ { 15206a99fe3SHajimu UMEMOTO char *value; 15306a99fe3SHajimu UMEMOTO size_t value_size; 15406a99fe3SHajimu UMEMOTO 15506a99fe3SHajimu UMEMOTO TAILQ_ENTRY(cache_mp_data_item_) entries; 15606a99fe3SHajimu UMEMOTO }; 15706a99fe3SHajimu UMEMOTO 158d2432adbSDag-Erling Smørgrav struct cache_mp_write_session_ { 15906a99fe3SHajimu UMEMOTO struct cache_mp_entry_ *parent_entry; 16006a99fe3SHajimu UMEMOTO 16106a99fe3SHajimu UMEMOTO /* 16206a99fe3SHajimu UMEMOTO * All items are accumulated in this queue. When the session is 16306a99fe3SHajimu UMEMOTO * committed, they all will be copied to the multipart entry. 16406a99fe3SHajimu UMEMOTO */ 16506a99fe3SHajimu UMEMOTO TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items; 16606a99fe3SHajimu UMEMOTO size_t items_size; 16706a99fe3SHajimu UMEMOTO 16806a99fe3SHajimu UMEMOTO TAILQ_ENTRY(cache_mp_write_session_) entries; 16906a99fe3SHajimu UMEMOTO }; 17006a99fe3SHajimu UMEMOTO 171d2432adbSDag-Erling Smørgrav struct cache_mp_read_session_ { 17206a99fe3SHajimu UMEMOTO struct cache_mp_entry_ *parent_entry; 17306a99fe3SHajimu UMEMOTO struct cache_mp_data_item_ *current_item; 17406a99fe3SHajimu UMEMOTO 17506a99fe3SHajimu UMEMOTO TAILQ_ENTRY(cache_mp_read_session_) entries; 17606a99fe3SHajimu UMEMOTO }; 17706a99fe3SHajimu UMEMOTO 178d2432adbSDag-Erling Smørgrav struct cache_mp_entry_ { 17906a99fe3SHajimu UMEMOTO char *name; 18006a99fe3SHajimu UMEMOTO struct cache_entry_params *params; 18106a99fe3SHajimu UMEMOTO 18206a99fe3SHajimu UMEMOTO struct mp_cache_entry_params mp_params; 18306a99fe3SHajimu UMEMOTO 18406a99fe3SHajimu UMEMOTO /* All opened write sessions */ 18506a99fe3SHajimu UMEMOTO TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head; 18606a99fe3SHajimu UMEMOTO size_t ws_size; 18706a99fe3SHajimu UMEMOTO 18806a99fe3SHajimu UMEMOTO /* All opened read sessions */ 18906a99fe3SHajimu UMEMOTO TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head; 19006a99fe3SHajimu UMEMOTO size_t rs_size; 19106a99fe3SHajimu UMEMOTO 19206a99fe3SHajimu UMEMOTO /* 19306a99fe3SHajimu UMEMOTO * completed_write_session is the committed write sessions. All read 19406a99fe3SHajimu UMEMOTO * sessions use data from it. If the completed_write_session is out of 19506a99fe3SHajimu UMEMOTO * date, but still in use by some of the read sessions, the newly 19606a99fe3SHajimu UMEMOTO * committed write session is stored in the pending_write_session. 19706a99fe3SHajimu UMEMOTO * In such a case, completed_write_session will be substituted with 19806a99fe3SHajimu UMEMOTO * pending_write_session as soon as it won't be used by any of 19906a99fe3SHajimu UMEMOTO * the read sessions. 20006a99fe3SHajimu UMEMOTO */ 20106a99fe3SHajimu UMEMOTO struct cache_mp_write_session_ *completed_write_session; 20206a99fe3SHajimu UMEMOTO struct cache_mp_write_session_ *pending_write_session; 20306a99fe3SHajimu UMEMOTO struct timeval creation_time; 20406a99fe3SHajimu UMEMOTO struct timeval last_request_time; 20506a99fe3SHajimu UMEMOTO 20606a99fe3SHajimu UMEMOTO void (*get_time_func)(struct timeval *); 20706a99fe3SHajimu UMEMOTO }; 20806a99fe3SHajimu UMEMOTO 209d2432adbSDag-Erling Smørgrav struct cache_ { 21006a99fe3SHajimu UMEMOTO struct cache_params params; 21106a99fe3SHajimu UMEMOTO 21206a99fe3SHajimu UMEMOTO struct cache_entry_ **entries; 21306a99fe3SHajimu UMEMOTO size_t entries_capacity; 21406a99fe3SHajimu UMEMOTO size_t entries_size; 21506a99fe3SHajimu UMEMOTO }; 21606a99fe3SHajimu UMEMOTO 21706a99fe3SHajimu UMEMOTO /* simple abstractions - for not to write "struct" every time */ 21806a99fe3SHajimu UMEMOTO typedef struct cache_ *cache; 21906a99fe3SHajimu UMEMOTO typedef struct cache_entry_ *cache_entry; 22006a99fe3SHajimu UMEMOTO typedef struct cache_mp_write_session_ *cache_mp_write_session; 22106a99fe3SHajimu UMEMOTO typedef struct cache_mp_read_session_ *cache_mp_read_session; 22206a99fe3SHajimu UMEMOTO 22306a99fe3SHajimu UMEMOTO #define INVALID_CACHE (NULL) 22406a99fe3SHajimu UMEMOTO #define INVALID_CACHE_ENTRY (NULL) 22506a99fe3SHajimu UMEMOTO #define INVALID_CACHE_MP_WRITE_SESSION (NULL) 22606a99fe3SHajimu UMEMOTO #define INVALID_CACHE_MP_READ_SESSION (NULL) 22706a99fe3SHajimu UMEMOTO 22806a99fe3SHajimu UMEMOTO /* 22906a99fe3SHajimu UMEMOTO * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety 23006a99fe3SHajimu UMEMOTO * externally, by yourself. 23106a99fe3SHajimu UMEMOTO */ 23206a99fe3SHajimu UMEMOTO 23306a99fe3SHajimu UMEMOTO /* cache initialization/destruction routines */ 234d2432adbSDag-Erling Smørgrav cache init_cache(struct cache_params const *); 235d2432adbSDag-Erling Smørgrav void destroy_cache(cache); 23606a99fe3SHajimu UMEMOTO 23706a99fe3SHajimu UMEMOTO /* cache entries manipulation routines */ 238d2432adbSDag-Erling Smørgrav int register_cache_entry(cache, struct cache_entry_params const *); 239d2432adbSDag-Erling Smørgrav int unregister_cache_entry(cache, const char *); 240d2432adbSDag-Erling Smørgrav cache_entry find_cache_entry(cache, const char *); 24106a99fe3SHajimu UMEMOTO 24206a99fe3SHajimu UMEMOTO /* read/write operations used on common entries */ 243d2432adbSDag-Erling Smørgrav int cache_read(cache_entry, const char *, size_t, char *, size_t *); 244d2432adbSDag-Erling Smørgrav int cache_write(cache_entry, const char *, size_t, char const *, size_t); 24506a99fe3SHajimu UMEMOTO 24606a99fe3SHajimu UMEMOTO /* read/write operations used on multipart entries */ 247d2432adbSDag-Erling Smørgrav cache_mp_write_session open_cache_mp_write_session(cache_entry); 248d2432adbSDag-Erling Smørgrav int cache_mp_write(cache_mp_write_session, char *, size_t); 249d2432adbSDag-Erling Smørgrav void abandon_cache_mp_write_session(cache_mp_write_session); 250d2432adbSDag-Erling Smørgrav void close_cache_mp_write_session(cache_mp_write_session); 25106a99fe3SHajimu UMEMOTO 252d2432adbSDag-Erling Smørgrav cache_mp_read_session open_cache_mp_read_session(cache_entry); 253d2432adbSDag-Erling Smørgrav int cache_mp_read(cache_mp_read_session, char *, size_t *); 254d2432adbSDag-Erling Smørgrav void close_cache_mp_read_session(cache_mp_read_session); 25506a99fe3SHajimu UMEMOTO 25606a99fe3SHajimu UMEMOTO /* transformation routines */ 257d2432adbSDag-Erling Smørgrav int transform_cache_entry(cache_entry, enum cache_transformation_t); 258d2432adbSDag-Erling Smørgrav int transform_cache_entry_part(cache_entry, enum cache_transformation_t, 25906a99fe3SHajimu UMEMOTO const char *, size_t, enum part_position_t); 26006a99fe3SHajimu UMEMOTO 26106a99fe3SHajimu UMEMOTO #endif 262