diff options
Diffstat (limited to 'usr.sbin/nscd/cachelib.h')
-rw-r--r-- | usr.sbin/nscd/cachelib.h | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/usr.sbin/nscd/cachelib.h b/usr.sbin/nscd/cachelib.h new file mode 100644 index 0000000..d67e830 --- /dev/null +++ b/usr.sbin/nscd/cachelib.h @@ -0,0 +1,281 @@ +/*- + * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __CACHED_CACHELIB_H__ +#define __CACHED_CACHELIB_H__ + +#include <sys/queue.h> +#include <sys/time.h> +#include <stdlib.h> +#include "hashtable.h" +#include "cacheplcs.h" + +enum cache_entry_t { + CET_COMMON = 0, /* cache item is atomic */ + CET_MULTIPART /* cache item is formed part by part */ +}; + +enum cache_transformation_t { + CTT_FLUSH = 0, /* flush the cache - delete all obsolete items */ + CTT_CLEAR = 1 /* delete all items in the cache */ +}; + +/* cache deletion policy type enum */ +enum cache_policy_t { + CPT_FIFO = 0, /* first-in first-out */ + CPT_LRU = 1, /* least recently used */ + CPT_LFU = 2 /* least frequently used */ +}; + +/* multipart sessions can be used for reading and writing */ +enum cache_mp_session_t { + CMPT_READ_SESSION, + CMPT_WRITE_SESSION +}; + +/* + * When doing partial transformations of entries (which are applied for + * elements with keys, that contain specified buffer in its left or + * right part), this enum will show the needed position of the key part. + */ +enum part_position_t { + KPPT_LEFT, + KPPT_RIGHT +}; + +/* num_levels attribute is obsolete, i think - user can always emulate it + * by using one entry. + * get_time_func is needed to have the clocks-independent counter + */ +struct cache_params +{ + void (*get_time_func)(struct timeval *); +}; + +/* + * base structure - normal_cache_entry_params and multipart_cache_entry_params + * are "inherited" from it + */ +struct cache_entry_params +{ + enum cache_entry_t entry_type; + char *entry_name; +}; + +/* params, used for most entries */ +struct common_cache_entry_params +{ + /* inherited fields */ + enum cache_entry_t entry_type; + + /* unique fields */ + char *entry_name; + size_t cache_entries_size; + + size_t max_elemsize; /* if 0 then no check is made */ + size_t satisf_elemsize; /* if entry size is exceeded, + * this number of elements will be left, + * others will be deleted */ + struct timeval max_lifetime; /* if 0 then no check is made */ + enum cache_policy_t policy; /* policy used for transformations */ +}; + +/* params, used for multipart entries */ +struct mp_cache_entry_params +{ + /* inherited fields */ + enum cache_entry_t entry_type; + char *entry_name; + + /* unique fields */ + size_t max_elemsize; /* if 0 then no check is made */ + size_t max_sessions; /* maximum number of active sessions */ + + struct timeval max_lifetime; /* maximum elements lifetime */ +}; + +struct cache_ht_item_data_ +{ + /* key is the bytes sequence only - not the null-terminated string */ + char *key; + size_t key_size; + + char *value; + size_t value_size; + + struct cache_policy_item_ *fifo_policy_item; +}; + +struct cache_ht_item_ +{ + HASHTABLE_ENTRY_HEAD(ht_item_, struct cache_ht_item_data_) data; +}; + +struct cache_entry_ +{ + char *name; + struct cache_entry_params *params; +}; + +struct cache_common_entry_ +{ + char *name; + struct cache_entry_params *params; + + struct common_cache_entry_params common_params; + + HASHTABLE_HEAD(cache_ht_, cache_ht_item_) items; + size_t items_size; + + /* + * Entry always has the FIFO policy, that is used to eliminate old + * elements (the ones, with lifetime more than max_lifetime). Besides, + * user can specify another policy to be applied, when there are too + * many elements in the entry. So policies_size can be 1 or 2. + */ + struct cache_policy_ **policies; + size_t policies_size; + + void (*get_time_func)(struct timeval *); +}; + +struct cache_mp_data_item_ { + char *value; + size_t value_size; + + TAILQ_ENTRY(cache_mp_data_item_) entries; +}; + +struct cache_mp_write_session_ +{ + struct cache_mp_entry_ *parent_entry; + + /* + * All items are accumulated in this queue. When the session is + * committed, they all will be copied to the multipart entry. + */ + TAILQ_HEAD(cache_mp_data_item_head, cache_mp_data_item_) items; + size_t items_size; + + TAILQ_ENTRY(cache_mp_write_session_) entries; +}; + +struct cache_mp_read_session_ +{ + struct cache_mp_entry_ *parent_entry; + struct cache_mp_data_item_ *current_item; + + TAILQ_ENTRY(cache_mp_read_session_) entries; +}; + +struct cache_mp_entry_ +{ + char *name; + struct cache_entry_params *params; + + struct mp_cache_entry_params mp_params; + + /* All opened write sessions */ + TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head; + size_t ws_size; + + /* All opened read sessions */ + TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head; + size_t rs_size; + + /* + * completed_write_session is the committed write sessions. All read + * sessions use data from it. If the completed_write_session is out of + * date, but still in use by some of the read sessions, the newly + * committed write session is stored in the pending_write_session. + * In such a case, completed_write_session will be substituted with + * pending_write_session as soon as it won't be used by any of + * the read sessions. + */ + struct cache_mp_write_session_ *completed_write_session; + struct cache_mp_write_session_ *pending_write_session; + struct timeval creation_time; + struct timeval last_request_time; + + void (*get_time_func)(struct timeval *); +}; + +struct cache_ +{ + struct cache_params params; + + struct cache_entry_ **entries; + size_t entries_capacity; + size_t entries_size; +}; + +/* simple abstractions - for not to write "struct" every time */ +typedef struct cache_ *cache; +typedef struct cache_entry_ *cache_entry; +typedef struct cache_mp_write_session_ *cache_mp_write_session; +typedef struct cache_mp_read_session_ *cache_mp_read_session; + +#define INVALID_CACHE (NULL) +#define INVALID_CACHE_ENTRY (NULL) +#define INVALID_CACHE_MP_WRITE_SESSION (NULL) +#define INVALID_CACHE_MP_READ_SESSION (NULL) + +/* + * NOTE: all cache operations are thread-unsafe. You must ensure thread-safety + * externally, by yourself. + */ + +/* cache initialization/destruction routines */ +extern cache init_cache(struct cache_params const *); +extern void destroy_cache(cache); + +/* cache entries manipulation routines */ +extern int register_cache_entry(cache, struct cache_entry_params const *); +extern int unregister_cache_entry(cache, const char *); +extern cache_entry find_cache_entry(cache, const char *); + +/* read/write operations used on common entries */ +extern int cache_read(cache_entry, const char *, size_t, char *, size_t *); +extern int cache_write(cache_entry, const char *, size_t, char const *, size_t); + +/* read/write operations used on multipart entries */ +extern cache_mp_write_session open_cache_mp_write_session(cache_entry); +extern int cache_mp_write(cache_mp_write_session, char *, size_t); +extern void abandon_cache_mp_write_session(cache_mp_write_session); +extern void close_cache_mp_write_session(cache_mp_write_session); + +extern cache_mp_read_session open_cache_mp_read_session(cache_entry); +extern int cache_mp_read(cache_mp_read_session, char *, size_t *); +extern void close_cache_mp_read_session(cache_mp_read_session); + +/* transformation routines */ +extern int transform_cache_entry(cache_entry, enum cache_transformation_t); +extern int transform_cache_entry_part(cache_entry, enum cache_transformation_t, + const char *, size_t, enum part_position_t); + +#endif |