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