cache.h revision 12788:c71b0e8f856c
1109998Smarkm/* 2109998Smarkm * CDDL HEADER START 3109998Smarkm * 4109998Smarkm * The contents of this file are subject to the terms of the 5109998Smarkm * Common Development and Distribution License (the "License"). 6109998Smarkm * You may not use this file except in compliance with the License. 7109998Smarkm * 8109998Smarkm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9280304Sjkim * or http://www.opensolaris.org/os/licensing. 10109998Smarkm * See the License for the specific language governing permissions 11109998Smarkm * and limitations under the License. 12109998Smarkm * 13109998Smarkm * When distributing Covered Code, include this CDDL HEADER in each 14109998Smarkm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15109998Smarkm * If applicable, add the following below this CDDL HEADER, with the 16109998Smarkm * fields enclosed by brackets "[]" replaced with your own identifying 17109998Smarkm * information: Portions Copyright [yyyy] [name of copyright owner] 18109998Smarkm * 19109998Smarkm * CDDL HEADER END 20109998Smarkm */ 21109998Smarkm/* 22109998Smarkm * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 23109998Smarkm */ 24109998Smarkm 25109998Smarkm#ifndef _NSCD_H 26109998Smarkm#define _NSCD_H 27109998Smarkm 28109998Smarkm/* 29109998Smarkm * This is a private header file. Applications should not directly include 30109998Smarkm * this file. 31109998Smarkm */ 32109998Smarkm 33109998Smarkm#ifdef __cplusplus 34109998Smarkmextern "C" { 35109998Smarkm#endif 36109998Smarkm 37109998Smarkm#include <sys/avl.h> 38109998Smarkm#include <thread.h> 39109998Smarkm#include <synch.h> 40109998Smarkm#include <nss_dbdefs.h> 41109998Smarkm#include "getxby_door.h" 42109998Smarkm#include "nscd_common.h" 43109998Smarkm#include "nscd_config.h" 44109998Smarkm 45109998Smarkm/* 46109998Smarkm * OR'D in by server to call self for updates 47109998Smarkm */ 48109998Smarkm#define UPDATEBIT (1<<30) 49109998Smarkm#define MASKUPDATEBIT(a) ((~UPDATEBIT)&(a)) 50109998Smarkm 51109998Smarkm/* 52109998Smarkm * debug levels 53109998Smarkm */ 54109998Smarkm#define DBG_OFF 0 55160814Ssimon#define DBG_CANT_FIND 2 56109998Smarkm#define DBG_NETLOOKUPS 4 57160814Ssimon#define DBG_ALL 6 58109998Smarkm 59109998Smarkm/* 60109998Smarkm * Max size name we allow to be passed to avoid 61280304Sjkim * buffer overflow problems 62280304Sjkim */ 63280304Sjkim#define NSCDMAXNAMELEN 255 64280304Sjkim 65280304Sjkim/* 66280304Sjkim * cached entry status 67280304Sjkim */ 68280304Sjkim#define ST_UPDATE_PENDING 0x1 69280304Sjkim#define ST_LOOKUP_PENDING 0x2 70280304Sjkim#define ST_PENDING (ST_LOOKUP_PENDING | ST_UPDATE_PENDING) 71280304Sjkim#define ST_NEW_ENTRY 0x4 72280304Sjkim#define ST_DISCARD 0x8 73109998Smarkm 74238405Sjkim/* 75238405Sjkim * Cache eviction start and stop levels 76160814Ssimon */ 77280304Sjkim#define _NSC_EVICTION_START_LEVEL 90 78280304Sjkim#define _NSC_EVICTION_SAFE_LEVEL 80 79280304Sjkim 80109998Smarkm/* 81280304Sjkim * other internal constants 82280304Sjkim */ 83280304Sjkim#define _NSC_MAX_DB 3 84280304Sjkim#define _NSC_PUBLIC_ACCESS -1 85238405Sjkim#define _NSC_FILE_CHECK_TIME 0 /* check always for backwards compat */ 86160814Ssimon 87109998Smarkm/* 88109998Smarkm * Macros used for logging purposes 89109998Smarkm */ 90109998Smarkm#define yes_no(flag) (flag == nscd_true)?"yes":"no" 91280304Sjkim#define check_null(str) (str)?str:"<null>" 92280304Sjkim 93280304Sjkim/* 94238405Sjkim * Macros used by compare routines 95109998Smarkm */ 96280304Sjkim#define _NSC_INT_KEY_CMP(n1, n2) \ 97280304Sjkim (n1 > n2)?1:((n1 == n2)?0:-1) 98280304Sjkim 99109998Smarkm#define _NSC_GET_HITRATE(sp) \ 100109998Smarkm sp->hitrate = sp->pos_misses + sp->neg_misses + \ 101109998Smarkm sp->pos_hits + sp->neg_hits; \ 102280304Sjkim if (sp->hitrate > 0.0) \ 103280304Sjkim sp->hitrate = (100.0 * \ 104280304Sjkim ((double)sp->pos_hits + \ 105238405Sjkim (double)sp->neg_hits)) / sp->hitrate; 106109998Smarkm 107280304Sjkim/* 108280304Sjkim * nsc_lookup action 109280304Sjkim */ 110280304Sjkimtypedef enum { 111238405Sjkim _NSC_NSLOOKUP = 0, 112238405Sjkim _NSC_WAIT, 113238405Sjkim _NSC_USECACHED 114109998Smarkm} nsc_action_t; 115280304Sjkim 116280304Sjkim/* 117238405Sjkim * What each entry in the nameserver cache looks like. 118280304Sjkim */ 119280304Sjkim 120280304Sjkimtypedef struct nsc_entry_stat { 121280304Sjkim uint_t hits; /* number of hits */ 122280304Sjkim uint8_t status; /* activity status */ 123280304Sjkim time_t timestamp; /* expiry time */ 124280304Sjkim int refcount; /* reference count */ 125280304Sjkim} nsc_entry_stat_t; 126280304Sjkim 127109998Smarkmtypedef struct nsc_entry { 128280304Sjkim avl_node_t avl_link; /* libavl requirement */ 129280304Sjkim struct nsc_entry *qnext; /* next on pqueue */ 130280304Sjkim struct nsc_entry *qprev; /* prev on pqueue */ 131280304Sjkim nsc_entry_stat_t stats; /* entry's statistics */ 132109998Smarkm nss_XbyY_key_t key; /* entry's key */ 133280304Sjkim void *buffer; /* data buffer */ 134280304Sjkim size_t bufsize; /* data buffer length */ 135280304Sjkim} nsc_entry_t; 136280304Sjkim 137280304Sjkimtypedef struct nsc_keephot { 138280304Sjkim void *ptr; 139280304Sjkim uint_t num; 140280304Sjkim} nsc_keephot_t; 141280304Sjkim 142280304Sjkim/* 143280304Sjkim * Structure to handle waiting for pending name service requests 144280304Sjkim */ 145280304Sjkimtypedef struct waiter { 146280304Sjkim cond_t w_waitcv; 147280304Sjkim uint8_t w_signaled; 148280304Sjkim nsc_entry_t *w_key; 149280304Sjkim struct waiter *w_next, *w_prev; 150280304Sjkim} waiter_t; 151280304Sjkim 152280304Sjkim/* 153280304Sjkim * Macros used by hash table 154280304Sjkim * 155280304Sjkim * _NSC_HTSIZE_PRIMES are prime numbers that are used as hash table 156280304Sjkim * sizes when hash table type is nsc_ht_prime. For hash tables of 157280304Sjkim * type nsc_ht_power2, the size is automatically calculated. 158280304Sjkim * Number of primes listed below is _NSC_HTSIZE_NUM_SLOTS + 1. 159280304Sjkim * Each number (except the first) is a prime closest to a 160280304Sjkim * power of 2 in increasing order. Ex: 509 is the closest prime to 161280304Sjkim * 512 (2**9), 1021 is closest to 1024 (2**10), and so on. 162280304Sjkim * The first prime is chosen as 211 for historical reasons. 163280304Sjkim */ 164280304Sjkim#define _NSC_INIT_HTSIZE_PRIME 211 165280304Sjkim#define _NSC_INIT_HTSIZE_POWER2 256 166280304Sjkim#define _NSC_INIT_HTSIZE_SLOT_VALUE 2896 167280304Sjkim#define _NSC_HTSIZE_NUM_SLOTS 10 168280304Sjkim#define _NSC_HTSIZE_PRIMES 211, 509, 1021, 2053, 4099, 8191, \ 169280304Sjkim 16381, 32771, 65537, 131071, 262147 170280304Sjkim 171280304Sjkim#define _NSC_DB_CES_KEY(ptr) \ 172280304Sjkim ((ptr)->db_type == nsc_key_ces) 173280304Sjkim#define _NSC_DB_CIS_KEY(ptr) \ 174280304Sjkim ((ptr)->db_type == nsc_key_cis) 175280304Sjkim#define _NSC_DB_STR_KEY(ptr) \ 176280304Sjkim _NSC_DB_CES_KEY(ptr) || _NSC_DB_CIS_KEY(ptr) 177280304Sjkim#define _NSC_DB_INT_KEY(ptr) \ 178280304Sjkim ((ptr)->db_type == nsc_key_int) 179280304Sjkim 180280304Sjkim/* 181280304Sjkim * cache backend param group (global) 182280304Sjkim */ 183280304Sjkim#define NSCD_CFG_GROUP_INFO_GLOBAL_CACHE {1, 0x0001} 184280304Sjkimtypedef struct nscd_cfg_global_cache { 185280304Sjkim nscd_cfg_group_info_t gi; /* config requirement */ 186280304Sjkim nscd_bool_t enable; 187280304Sjkim} nscd_cfg_global_cache_t; 188280304Sjkim 189280304Sjkim#define NSCD_CFG_GLOBAL_CACHE_DEFAULTS \ 190280304Sjkim { NSCD_CFG_GROUP_INFO_GLOBAL_CACHE, nscd_true } 191238405Sjkim 192280304Sjkim/* 193280304Sjkim * cache backend param group (per database) 194280304Sjkim */ 195280304Sjkim#define NSCD_CFG_GROUP_INFO_CACHE {12, 0x0fff} 196280304Sjkimtypedef struct nscd_cfg_cache { 197280304Sjkim nscd_cfg_group_info_t gi; /* config requirement */ 198280304Sjkim nscd_bool_t enable; /* if false return NOSERVER */ 199280304Sjkim nscd_bool_t per_user; /* if true per user access */ 200280304Sjkim nscd_bool_t avoid_ns; /* if true avoid name service */ 201280304Sjkim nscd_bool_t check_files; /* if true check file */ 202280304Sjkim int check_interval; /* check interval */ 203280304Sjkim int pos_ttl; /* time to live for +ve entries */ 204280304Sjkim int neg_ttl; /* time to live for -ve entries */ 205238405Sjkim int keephot; /* keep hot count */ 206238405Sjkim int hint_size; /* size to return for a GETHINTS */ 207109998Smarkm ulong_t maxentries; /* maximum entries allowed */ 208280304Sjkim int suggestedsize; /* obsolete */ 209280304Sjkim nscd_bool_t old_data_ok; /* obsolete */ 210280304Sjkim} nscd_cfg_cache_t; 211280304Sjkim 212280304Sjkim#define NSCD_CFG_CACHE_DEFAULTS \ 213280304Sjkim { \ 214280304Sjkim NSCD_CFG_GROUP_INFO_CACHE, \ 215280304Sjkim nscd_true, nscd_false, nscd_false, nscd_true, \ 216109998Smarkm _NSC_FILE_CHECK_TIME, 600, 10, 0, 1 << 11, 0, \ 217238405Sjkim 0, nscd_false \ 218280304Sjkim } 219280304Sjkim 220280304Sjkim/* 221280304Sjkim * cache backend stat group (per database) 222280304Sjkim */ 223280304Sjkim#define NSCD_CFG_STAT_GROUP_INFO_CACHE {9, 0x01ff} 224280304Sjkimtypedef struct nscd_cfg_stat_cache { 225238405Sjkim nscd_cfg_group_info_t gi; /* config requirement */ 226238405Sjkim ulong_t pos_hits; /* hits on +ve entries */ 227109998Smarkm ulong_t neg_hits; /* hits on -ve entries */ 228280304Sjkim ulong_t pos_misses; /* misses on +ve entries */ 229280304Sjkim ulong_t neg_misses; /* misses on -ve entries */ 230280304Sjkim ulong_t entries; /* count of cache entries */ 231280304Sjkim ulong_t drop_count; /* cache queries dropped */ 232280304Sjkim ulong_t wait_count; /* cache queries queued */ 233280304Sjkim ulong_t invalidate_count; /* count for cache invalidation */ 234280304Sjkim double hitrate; /* computed from other fields */ 235280304Sjkim} nscd_cfg_stat_cache_t; 236280304Sjkim 237280304Sjkimtypedef struct nsc_db { 238109998Smarkm /* 239160814Ssimon * Data 240109998Smarkm */ 241109998Smarkm avl_tree_t tree; 242109998Smarkm nsc_entry_t **htable; 243280304Sjkim nsc_entry_t *qhead; 244280304Sjkim nsc_entry_t *qtail; 245109998Smarkm nsc_entry_t *reap_node; 246280304Sjkim int callnumber; 247280304Sjkim int dbop; 248280304Sjkim char *name; 249280304Sjkim mutex_t db_mutex; 250109998Smarkm waiter_t db_wait; /* lookup wait CV */ 251280304Sjkim int htsize; 252109998Smarkm enum hash_type { 253280304Sjkim nsc_ht_default = 0, 254280304Sjkim nsc_ht_prime = 1, 255109998Smarkm nsc_ht_power2 = 2 256280304Sjkim } hash_type; 257280304Sjkim enum db_type { 258280304Sjkim nsc_key_ces = 0, 259280304Sjkim nsc_key_cis = 1, 260280304Sjkim nsc_key_int = 2, 261280304Sjkim nsc_key_other = 3 262280304Sjkim } db_type; 263280304Sjkim /* 264280304Sjkim * Methods 265280304Sjkim */ 266280304Sjkim uint_t (*gethash)(nss_XbyY_key_t *, int); 267280304Sjkim int (*compar)(const void *, const void *); 268280304Sjkim void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *); 269280304Sjkim /* 270280304Sjkim * Config 271109998Smarkm */ 272280304Sjkim nscd_cfg_cache_t cfg; 273280304Sjkim time_t cfg_mtime; 274109998Smarkm} nsc_db_t; 275280304Sjkim 276280304Sjkim 277280304Sjkimtypedef struct nsc_ctx { 278280304Sjkim char *dbname; /* cache name */ 279280304Sjkim nscd_cfg_stat_cache_t stats; /* statistics */ 280280304Sjkim nscd_cfg_cache_t cfg; /* configs */ 281280304Sjkim time_t cfg_mtime; /* config last modified time */ 282280304Sjkim rwlock_t cfg_rwlp; /* config rwlock */ 283280304Sjkim mutex_t stats_mutex; /* stats mutex */ 284280304Sjkim mutex_t file_mutex; /* file mutex */ 285109998Smarkm time_t file_mtime; /* file last modified time */ 286280304Sjkim time_t file_chktime; /* file last checked time */ 287280304Sjkim off_t file_size; /* file size at last check */ 288109998Smarkm ino_t file_ino; /* file inode at last check */ 289280304Sjkim const char *file_name; /* filename for check_files */ 290280304Sjkim int db_count; /* number of caches, max _NSC_MAX_DB */ 291280304Sjkim nsc_db_t *nsc_db[_NSC_MAX_DB]; /* caches */ 292280304Sjkim sema_t throttle_sema; /* throttle lookups */ 293280304Sjkim sema_t revalidate_sema; /* revalidation threads */ 294280304Sjkim nscd_bool_t revalidate_on; /* reval. thread started */ 295280304Sjkim nscd_bool_t reaper_on; /* reaper thread started */ 296280304Sjkim} nsc_ctx_t; 297280304Sjkim 298280304Sjkimtypedef struct nsc_lookup_args { 299280304Sjkim nsc_ctx_t *ctx; 300280304Sjkim nsc_db_t *nscdb; 301280304Sjkim void *buffer; 302280304Sjkim size_t bufsize; 303109998Smarkm} nsc_lookup_args_t; 304280304Sjkim 305280304Sjkim#define CACHE_CTX_COUNT 19 306109998Smarkm 307280304Sjkim/* Context initialization */ 308109998Smarkmextern void passwd_init_ctx(nsc_ctx_t *); 309280304Sjkimextern void group_init_ctx(nsc_ctx_t *); 310280304Sjkimextern void host_init_ctx(nsc_ctx_t *); 311109998Smarkmextern void ipnode_init_ctx(nsc_ctx_t *); 312280304Sjkimextern void exec_init_ctx(nsc_ctx_t *); 313280304Sjkimextern void prof_init_ctx(nsc_ctx_t *); 314280304Sjkimextern void user_init_ctx(nsc_ctx_t *); 315280304Sjkimextern void ether_init_ctx(nsc_ctx_t *); 316280304Sjkimextern void rpc_init_ctx(nsc_ctx_t *); 317280304Sjkimextern void proto_init_ctx(nsc_ctx_t *); 318280304Sjkimextern void net_init_ctx(nsc_ctx_t *); 319280304Sjkimextern void bootp_init_ctx(nsc_ctx_t *); 320280304Sjkimextern void auth_init_ctx(nsc_ctx_t *); 321280304Sjkimextern void serv_init_ctx(nsc_ctx_t *); 322109998Smarkmextern void netmask_init_ctx(nsc_ctx_t *); 323280304Sjkimextern void printer_init_ctx(nsc_ctx_t *); 324280304Sjkimextern void project_init_ctx(nsc_ctx_t *); 325280304Sjkimextern void tnrhtp_init_ctx(nsc_ctx_t *); 326280304Sjkimextern void tnrhdb_init_ctx(nsc_ctx_t *); 327280304Sjkim 328280304Sjkim/* Functions used to throttle threads */ 329109998Smarkmextern int nscd_wait(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *); 330280304Sjkimextern int nscd_signal(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *); 331280304Sjkim 332280304Sjkim/* Cache creation and initialization */ 333280304Sjkimextern nscd_rc_t init_cache(); 334280304Sjkimextern nsc_db_t *make_cache(enum db_type, int, char *, 335280304Sjkim int (*compar) (const void *, const void *), 336280304Sjkim void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *), 337280304Sjkim uint_t (*gethash)(nss_XbyY_key_t *, int), 338238405Sjkim enum hash_type, int); 339238405Sjkim 340238405Sjkim/* Cache backend lookup */ 341238405Sjkimextern void nsc_lookup(nsc_lookup_args_t *, int); 342280304Sjkim 343280304Sjkim/* Cache backend info */ 344280304Sjkimextern void nsc_info(nsc_ctx_t *, char *, nscd_cfg_cache_t cfg[], 345238405Sjkim nscd_cfg_stat_cache_t stats[]); 346280304Sjkim#ifdef NSCD_DEBUG 347280304Sjkimextern int nsc_dump(char *, int); 348238405Sjkim#endif /* NSCD_DEBUG */ 349280304Sjkim 350280304Sjkim/* Cache invalidate */ 351280304Sjkimextern void nsc_invalidate(nsc_ctx_t *, char *, nsc_ctx_t **); 352280304Sjkim 353280304Sjkim/* Keep hot functions */ 354284285Sjkimextern nsc_keephot_t *maken(int); 355284285Sjkimextern void *insertn(nsc_keephot_t *, uint_t, void *); 356284285Sjkim 357284285Sjkim/* hash related routines */ 358280304Sjkimextern uint_t cis_gethash(const char *, int); 359extern uint_t ces_gethash(const char *, int); 360extern uint_t db_gethash(const void *, int, int); 361 362extern void leave(int n); 363extern int get_cache_idx(char *); 364 365#ifdef __cplusplus 366} 367#endif 368 369#endif /* _NSCD_H */ 370