1158115Sume/*- 2158115Sume * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru> 3158115Sume * All rights reserved. 4158115Sume * 5158115Sume * Redistribution and use in source and binary forms, with or without 6158115Sume * modification, are permitted provided that the following conditions 7158115Sume * are met: 8158115Sume * 1. Redistributions of source code must retain the above copyright 9158115Sume * notice, this list of conditions and the following disclaimer. 10158115Sume * 2. Redistributions in binary form must reproduce the above copyright 11158115Sume * notice, this list of conditions and the following disclaimer in the 12158115Sume * documentation and/or other materials provided with the distribution. 13158115Sume * 14158115Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15158115Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16158115Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17158115Sume * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18158115Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19158115Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20158115Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21158115Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22158115Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23158115Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24158115Sume * SUCH DAMAGE. 25158115Sume * 26158115Sume * $FreeBSD$ 27158115Sume */ 28158115Sume 29171795Sbushman#ifndef __NSCD_CACHELIB_H__ 30171795Sbushman#define __NSCD_CACHELIB_H__ 31158115Sume 32158115Sume#include "hashtable.h" 33158115Sume#include "cacheplcs.h" 34158115Sume 35158115Sumeenum cache_entry_t { 36158115Sume CET_COMMON = 0, /* cache item is atomic */ 37158115Sume CET_MULTIPART /* cache item is formed part by part */ 38158115Sume}; 39158115Sume 40158115Sumeenum cache_transformation_t { 41158115Sume CTT_FLUSH = 0, /* flush the cache - delete all obsolete items */ 42158115Sume CTT_CLEAR = 1 /* delete all items in the cache */ 43158115Sume}; 44158115Sume 45158115Sume/* cache deletion policy type enum */ 46158115Sumeenum cache_policy_t { 47158115Sume CPT_FIFO = 0, /* first-in first-out */ 48158115Sume CPT_LRU = 1, /* least recently used */ 49158115Sume CPT_LFU = 2 /* least frequently used */ 50158115Sume}; 51158115Sume 52158115Sume/* multipart sessions can be used for reading and writing */ 53158115Sumeenum cache_mp_session_t { 54158115Sume CMPT_READ_SESSION, 55158115Sume CMPT_WRITE_SESSION 56158115Sume}; 57158115Sume 58158115Sume/* 59158115Sume * When doing partial transformations of entries (which are applied for 60158115Sume * elements with keys, that contain specified buffer in its left or 61158115Sume * right part), this enum will show the needed position of the key part. 62158115Sume */ 63158115Sumeenum part_position_t { 64158115Sume KPPT_LEFT, 65158115Sume KPPT_RIGHT 66158115Sume}; 67158115Sume 68158115Sume/* num_levels attribute is obsolete, i think - user can always emulate it 69158115Sume * by using one entry. 70158115Sume * get_time_func is needed to have the clocks-independent counter 71158115Sume */ 72194112Sdesstruct cache_params { 73158115Sume void (*get_time_func)(struct timeval *); 74158115Sume}; 75158115Sume 76158115Sume/* 77158115Sume * base structure - normal_cache_entry_params and multipart_cache_entry_params 78158115Sume * are "inherited" from it 79158115Sume */ 80194112Sdesstruct cache_entry_params { 81158115Sume enum cache_entry_t entry_type; 82158115Sume char *entry_name; 83158115Sume}; 84158115Sume 85158115Sume/* params, used for most entries */ 86194112Sdesstruct common_cache_entry_params { 87194097Sdes struct cache_entry_params cep; 88158115Sume 89158115Sume size_t cache_entries_size; 90158115Sume 91158115Sume size_t max_elemsize; /* if 0 then no check is made */ 92158115Sume size_t satisf_elemsize; /* if entry size is exceeded, 93158115Sume * this number of elements will be left, 94158115Sume * others will be deleted */ 95238094Sse int confidence_threshold; /* number matching replies required */ 96158115Sume struct timeval max_lifetime; /* if 0 then no check is made */ 97158115Sume enum cache_policy_t policy; /* policy used for transformations */ 98158115Sume}; 99158115Sume 100158115Sume/* params, used for multipart entries */ 101194112Sdesstruct mp_cache_entry_params { 102194097Sdes struct cache_entry_params cep; 103158115Sume 104158115Sume /* unique fields */ 105158115Sume size_t max_elemsize; /* if 0 then no check is made */ 106158115Sume size_t max_sessions; /* maximum number of active sessions */ 107158115Sume 108158115Sume struct timeval max_lifetime; /* maximum elements lifetime */ 109158115Sume}; 110158115Sume 111194112Sdesstruct cache_ht_item_data_ { 112158115Sume /* key is the bytes sequence only - not the null-terminated string */ 113158115Sume char *key; 114158115Sume size_t key_size; 115158115Sume 116158115Sume char *value; 117158115Sume size_t value_size; 118158115Sume 119158115Sume struct cache_policy_item_ *fifo_policy_item; 120238094Sse int confidence; /* incremented for each verification */ 121158115Sume}; 122158115Sume 123194112Sdesstruct cache_ht_item_ { 124158115Sume HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data; 125158115Sume}; 126158115Sume 127194112Sdesstruct cache_entry_ { 128158115Sume char *name; 129158115Sume struct cache_entry_params *params; 130158115Sume}; 131158115Sume 132194112Sdesstruct cache_common_entry_ { 133158115Sume char *name; 134158115Sume struct cache_entry_params *params; 135158115Sume 136158115Sume struct common_cache_entry_params common_params; 137158115Sume 138158115Sume HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items; 139158115Sume size_t items_size; 140158115Sume 141158115Sume /* 142158115Sume * Entry always has the FIFO policy, that is used to eliminate old 143158115Sume * elements (the ones, with lifetime more than max_lifetime). Besides, 144158115Sume * user can specify another policy to be applied, when there are too 145158115Sume * many elements in the entry. So policies_size can be 1 or 2. 146158115Sume */ 147158115Sume struct cache_policy_ **policies; 148158115Sume size_t policies_size; 149158115Sume 150158115Sume void (*get_time_func)(struct timeval *); 151158115Sume}; 152158115Sume 153158115Sumestruct cache_mp_data_item_ { 154158115Sume char *value; 155158115Sume size_t value_size; 156158115Sume 157158115Sume TAILQ_ENTRY(cache_mp_data_item_) entries; 158158115Sume}; 159158115Sume 160194112Sdesstruct cache_mp_write_session_ { 161158115Sume struct cache_mp_entry_ *parent_entry; 162158115Sume 163158115Sume /* 164158115Sume * All items are accumulated in this queue. When the session is 165158115Sume * committed, they all will be copied to the multipart entry. 166158115Sume */ 167158115Sume TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items; 168158115Sume size_t items_size; 169158115Sume 170158115Sume TAILQ_ENTRY(cache_mp_write_session_) entries; 171158115Sume}; 172158115Sume 173194112Sdesstruct cache_mp_read_session_ { 174158115Sume struct cache_mp_entry_ *parent_entry; 175158115Sume struct cache_mp_data_item_ *current_item; 176158115Sume 177158115Sume TAILQ_ENTRY(cache_mp_read_session_) entries; 178158115Sume}; 179158115Sume 180194112Sdesstruct cache_mp_entry_ { 181158115Sume char *name; 182158115Sume struct cache_entry_params *params; 183158115Sume 184158115Sume struct mp_cache_entry_params mp_params; 185158115Sume 186158115Sume /* All opened write sessions */ 187158115Sume TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head; 188158115Sume size_t ws_size; 189158115Sume 190158115Sume /* All opened read sessions */ 191158115Sume TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head; 192158115Sume size_t rs_size; 193158115Sume 194158115Sume /* 195158115Sume * completed_write_session is the committed write sessions. All read 196158115Sume * sessions use data from it. If the completed_write_session is out of 197158115Sume * date, but still in use by some of the read sessions, the newly 198158115Sume * committed write session is stored in the pending_write_session. 199158115Sume * In such a case, completed_write_session will be substituted with 200158115Sume * pending_write_session as soon as it won't be used by any of 201158115Sume * the read sessions. 202158115Sume */ 203158115Sume struct cache_mp_write_session_ *completed_write_session; 204158115Sume struct cache_mp_write_session_ *pending_write_session; 205158115Sume struct timeval creation_time; 206158115Sume struct timeval last_request_time; 207158115Sume 208158115Sume void (*get_time_func)(struct timeval *); 209158115Sume}; 210158115Sume 211194112Sdesstruct cache_ { 212158115Sume struct cache_params params; 213158115Sume 214158115Sume struct cache_entry_ **entries; 215158115Sume size_t entries_capacity; 216158115Sume size_t entries_size; 217158115Sume}; 218158115Sume 219158115Sume/* simple abstractions - for not to write "struct" every time */ 220158115Sumetypedef struct cache_ *cache; 221158115Sumetypedef struct cache_entry_ *cache_entry; 222158115Sumetypedef struct cache_mp_write_session_ *cache_mp_write_session; 223158115Sumetypedef struct cache_mp_read_session_ *cache_mp_read_session; 224158115Sume 225158115Sume#define INVALID_CACHE (NULL) 226158115Sume#define INVALID_CACHE_ENTRY (NULL) 227158115Sume#define INVALID_CACHE_MP_WRITE_SESSION (NULL) 228158115Sume#define INVALID_CACHE_MP_READ_SESSION (NULL) 229158115Sume 230158115Sume/* 231158115Sume * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety 232158115Sume * externally, by yourself. 233158115Sume */ 234158115Sume 235158115Sume/* cache initialization/destruction routines */ 236194112Sdescache init_cache(struct cache_params const *); 237194112Sdesvoid destroy_cache(cache); 238158115Sume 239158115Sume/* cache entries manipulation routines */ 240194112Sdesint register_cache_entry(cache, struct cache_entry_params const *); 241194112Sdesint unregister_cache_entry(cache, const char *); 242194112Sdescache_entry find_cache_entry(cache, const char *); 243158115Sume 244158115Sume/* read/write operations used on common entries */ 245194112Sdesint cache_read(cache_entry, const char *, size_t, char *, size_t *); 246194112Sdesint cache_write(cache_entry, const char *, size_t, char const *, size_t); 247158115Sume 248158115Sume/* read/write operations used on multipart entries */ 249194112Sdescache_mp_write_session open_cache_mp_write_session(cache_entry); 250194112Sdesint cache_mp_write(cache_mp_write_session, char *, size_t); 251194112Sdesvoid abandon_cache_mp_write_session(cache_mp_write_session); 252194112Sdesvoid close_cache_mp_write_session(cache_mp_write_session); 253158115Sume 254194112Sdescache_mp_read_session open_cache_mp_read_session(cache_entry); 255194112Sdesint cache_mp_read(cache_mp_read_session, char *, size_t *); 256194112Sdesvoid close_cache_mp_read_session(cache_mp_read_session); 257158115Sume 258158115Sume/* transformation routines */ 259194112Sdesint transform_cache_entry(cache_entry, enum cache_transformation_t); 260194112Sdesint transform_cache_entry_part(cache_entry, enum cache_transformation_t, 261158115Sume const char *, size_t, enum part_position_t); 262158115Sume 263158115Sume#endif 264