xref: /illumos-gate/usr/src/cmd/nscd/cache.h (revision bfed486ad8de8b8ebc6345a8e10accae08bf2f45)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _NSCD_H
27 #define	_NSCD_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 /*
32  * This is a private header file.  Applications should not directly include
33  * this file.
34  */
35 
36 #ifdef	__cplusplus
37 extern "C" {
38 #endif
39 
40 #include <sys/avl.h>
41 #include <thread.h>
42 #include <synch.h>
43 #include <nss_dbdefs.h>
44 #include "getxby_door.h"
45 #include "nscd_common.h"
46 #include "nscd_config.h"
47 
48 /*
49  * OR'D in by server to call self for updates
50  */
51 #define	UPDATEBIT	(1<<30)
52 #define	MASKUPDATEBIT(a) ((~UPDATEBIT)&(a))
53 
54 /*
55  * debug levels
56  */
57 #define	DBG_OFF		0
58 #define	DBG_CANT_FIND	2
59 #define	DBG_NETLOOKUPS	4
60 #define	DBG_ALL		6
61 
62 /*
63  * Max size name we allow to be passed to avoid
64  * buffer overflow problems
65  */
66 #define	NSCDMAXNAMELEN	255
67 
68 /*
69  * cached entry status
70  */
71 #define	ST_UPDATE_PENDING	0x1
72 #define	ST_LOOKUP_PENDING	0x2
73 #define	ST_PENDING		(ST_LOOKUP_PENDING | ST_UPDATE_PENDING)
74 #define	ST_NEW_ENTRY		0x4
75 #define	ST_DISCARD		0x8
76 
77 /*
78  * Cache eviction start and stop levels
79  */
80 #define	_NSC_EVICTION_START_LEVEL	90
81 #define	_NSC_EVICTION_SAFE_LEVEL	80
82 
83 /*
84  * other internal constants
85  */
86 #define	_NSC_MAX_DB		2
87 #define	_NSC_PUBLIC_ACCESS	-1
88 #define	_NSC_FILE_CHECK_TIME	0	/* check always for backwards compat */
89 
90 /*
91  * Macros used for logging purposes
92  */
93 #define	yes_no(flag)	(flag == nscd_true)?"yes":"no"
94 #define	check_null(str)	(str)?str:"<null>"
95 
96 /*
97  * Macros used by compare routines
98  */
99 #define	_NSC_INT_KEY_CMP(n1, n2) \
100 	(n1 > n2)?1:((n1 == n2)?0:-1)
101 
102 #define	_NSC_GET_HITRATE(sp) \
103 	sp->hitrate = sp->pos_misses + sp->neg_misses + \
104 		sp->pos_hits + sp->neg_hits; \
105 	if (sp->hitrate > 0.0) \
106 		sp->hitrate = (100.0 * \
107 			((double)sp->pos_hits + \
108 			(double)sp->neg_hits)) / sp->hitrate;
109 
110 /*
111  * nsc_lookup action
112  */
113 typedef enum {
114 	_NSC_NSLOOKUP = 0,
115 	_NSC_WAIT,
116 	_NSC_USECACHED
117 } nsc_action_t;
118 
119 /*
120  *  What each entry in the nameserver cache looks like.
121  */
122 
123 typedef struct nsc_entry_stat {
124 	uint_t		hits;		/* number of hits */
125 	uint8_t		status;		/* activity status */
126 	time_t		timestamp;	/* expiry time */
127 	int 		refcount;	/* reference count */
128 } nsc_entry_stat_t;
129 
130 typedef struct nsc_entry {
131 	avl_node_t		avl_link;	/* libavl requirement */
132 	struct nsc_entry 	*qnext;		/* next on pqueue */
133 	struct nsc_entry 	*qprev;		/* prev on pqueue */
134 	nsc_entry_stat_t	stats;		/* entry's statistics */
135 	nss_XbyY_key_t		key;		/* entry's key */
136 	void			*buffer;	/* data buffer */
137 	size_t			bufsize;	/* data buffer length */
138 } nsc_entry_t;
139 
140 typedef struct nsc_keephot {
141 	void	*ptr;
142 	uint_t	num;
143 } nsc_keephot_t;
144 
145 /*
146  * Structure to handle waiting for pending name service requests
147  */
148 typedef struct waiter {
149 	cond_t		w_waitcv;
150 	uint8_t		w_signaled;
151 	nsc_entry_t	*w_key;
152 	struct waiter	*w_next, *w_prev;
153 } waiter_t;
154 
155 /*
156  * Macros used by hash table
157  *
158  * _NSC_HTSIZE_PRIMES are prime numbers that are used as hash table
159  * sizes when hash table type is nsc_ht_prime. For hash tables of
160  * type nsc_ht_power2, the size is automatically calculated.
161  * Number of primes listed below is _NSC_HTSIZE_NUM_SLOTS + 1.
162  * Each number (except the first) is a prime closest to a
163  * power of 2 in increasing order. Ex: 509 is the closest prime to
164  * 512 (2**9), 1021 is closest to 1024 (2**10), and so on.
165  * The first prime is chosen as 211 for historical reasons.
166  */
167 #define	_NSC_INIT_HTSIZE_PRIME	211
168 #define	_NSC_INIT_HTSIZE_POWER2	256
169 #define	_NSC_INIT_HTSIZE_SLOT_VALUE	2896
170 #define	_NSC_HTSIZE_NUM_SLOTS	10
171 #define	_NSC_HTSIZE_PRIMES	211, 509, 1021, 2053, 4099, 8191, \
172 				16381, 32771, 65537, 131071, 262147
173 
174 #define	_NSC_DB_CES_KEY(ptr) \
175 		((ptr)->db_type == nsc_key_ces)
176 #define	_NSC_DB_CIS_KEY(ptr) \
177 		((ptr)->db_type == nsc_key_cis)
178 #define	_NSC_DB_STR_KEY(ptr) \
179 		_NSC_DB_CES_KEY(ptr) || _NSC_DB_CIS_KEY(ptr)
180 #define	_NSC_DB_INT_KEY(ptr) \
181 		((ptr)->db_type == nsc_key_int)
182 
183 /*
184  * cache backend param group (global)
185  */
186 #define	NSCD_CFG_GROUP_INFO_GLOBAL_CACHE	{1, 0x0001}
187 typedef struct nscd_cfg_global_cache {
188 	nscd_cfg_group_info_t	gi;	/* config requirement */
189 	nscd_bool_t	enable;
190 } nscd_cfg_global_cache_t;
191 
192 #define	NSCD_CFG_GLOBAL_CACHE_DEFAULTS \
193 	{ NSCD_CFG_GROUP_INFO_GLOBAL_CACHE, nscd_true }
194 
195 /*
196  * cache backend param group (per database)
197  */
198 #define	NSCD_CFG_GROUP_INFO_CACHE	{12, 0x0fff}
199 typedef struct nscd_cfg_cache {
200 	nscd_cfg_group_info_t	gi;	/* config requirement */
201 	nscd_bool_t	enable;		/* if false return NOSERVER */
202 	nscd_bool_t	per_user;	/* if true per user access */
203 	nscd_bool_t	avoid_ns;	/* if true avoid name service */
204 	nscd_bool_t	check_files;	/* if true check file */
205 	int		check_interval;	/* check interval */
206 	int		pos_ttl;	/* time to live for +ve entries */
207 	int		neg_ttl;	/* time to live for -ve entries */
208 	int		keephot;	/* keep hot count */
209 	int		hint_size;	/* size to return for a GETHINTS */
210 	ulong_t		maxentries;	/* maximum entries allowed */
211 	int		suggestedsize;	/* obsolete */
212 	nscd_bool_t	old_data_ok;	/* obsolete */
213 } nscd_cfg_cache_t;
214 
215 #define	NSCD_CFG_CACHE_DEFAULTS \
216 	{ \
217 		NSCD_CFG_GROUP_INFO_CACHE, \
218 		nscd_true, nscd_false, nscd_false, nscd_true, \
219 		_NSC_FILE_CHECK_TIME, 600, 10, 0, 1 << 11, 0, \
220 		0,  nscd_false \
221 	}
222 
223 /*
224  * cache backend stat group (per database)
225  */
226 #define	NSCD_CFG_STAT_GROUP_INFO_CACHE	{9, 0x01ff}
227 typedef struct nscd_cfg_stat_cache {
228 	nscd_cfg_group_info_t	gi;	/* config requirement */
229 	ulong_t	pos_hits;		/* hits on +ve entries */
230 	ulong_t	neg_hits;		/* hits on -ve entries */
231 	ulong_t	pos_misses;		/* misses on +ve entries */
232 	ulong_t	neg_misses;		/* misses on -ve entries */
233 	ulong_t	entries;		/* count of cache entries */
234 	ulong_t	drop_count;		/* cache queries dropped */
235 	ulong_t	wait_count;		/* cache queries queued */
236 	ulong_t	invalidate_count;	/* count for cache invalidation */
237 	double	hitrate;		/* computed from other fields */
238 } nscd_cfg_stat_cache_t;
239 
240 typedef struct nsc_db {
241 	/*
242 	 * Data
243 	 */
244 	avl_tree_t	tree;
245 	nsc_entry_t	**htable;
246 	nsc_entry_t	*qhead;
247 	nsc_entry_t	*qtail;
248 	nsc_entry_t	*reap_node;
249 	int 		callnumber;
250 	int		dbop;
251 	char 		*name;
252 	mutex_t		db_mutex;
253 	waiter_t	db_wait;	/* lookup wait CV */
254 	int		htsize;
255 	enum hash_type {
256 		nsc_ht_default = 0,
257 		nsc_ht_prime = 1,
258 		nsc_ht_power2 = 2
259 	} hash_type;
260 	enum db_type {
261 		nsc_key_ces = 0,
262 		nsc_key_cis = 1,
263 		nsc_key_int = 2,
264 		nsc_key_other = 3
265 	} db_type;
266 	/*
267 	 * Methods
268 	 */
269 	uint_t (*gethash)(nss_XbyY_key_t *, int);
270 	int (*compar)(const void *, const void *);
271 	void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *);
272 	/*
273 	 * Config
274 	 */
275 	nscd_cfg_cache_t	cfg;
276 	time_t			cfg_mtime;
277 } nsc_db_t;
278 
279 
280 typedef struct nsc_ctx {
281 	char 		*dbname;		/* cache name */
282 	nscd_cfg_stat_cache_t	stats;		/* statistics */
283 	nscd_cfg_cache_t	cfg;		/* configs */
284 	time_t		cfg_mtime;		/* config last modified time */
285 	rwlock_t	cfg_rwlp;		/* config rwlock */
286 	mutex_t		stats_mutex;		/* stats mutex */
287 	mutex_t		file_mutex;		/* file mutex */
288 	time_t		file_mtime;		/* file last modified time */
289 	time_t		file_chktime; 		/* file last checked time */
290 	off_t		file_size;		/* file size at last check */
291 	ino_t		file_ino;		/* file inode at last check */
292 	const char 	*file_name;		/* filename for check_files */
293 	int		db_count;		/* number of caches */
294 	nsc_db_t 	*nsc_db[_NSC_MAX_DB];	/* caches */
295 	sema_t		throttle_sema;		/* throttle lookups */
296 	sema_t		revalidate_sema;	/* revalidation threads */
297 	nscd_bool_t	revalidate_on;		/* reval. thread started */
298 	nscd_bool_t	reaper_on;		/* reaper thread started */
299 } nsc_ctx_t;
300 
301 typedef struct nsc_lookup_args {
302 	nsc_ctx_t	*ctx;
303 	nsc_db_t	*nscdb;
304 	void		*buffer;
305 	size_t		bufsize;
306 } nsc_lookup_args_t;
307 
308 #define	CACHE_CTX_COUNT	20
309 
310 /* Context initialization */
311 extern void passwd_init_ctx(nsc_ctx_t *);
312 extern void group_init_ctx(nsc_ctx_t *);
313 extern void host_init_ctx(nsc_ctx_t *);
314 extern void ipnode_init_ctx(nsc_ctx_t *);
315 extern void exec_init_ctx(nsc_ctx_t *);
316 extern void prof_init_ctx(nsc_ctx_t *);
317 extern void user_init_ctx(nsc_ctx_t *);
318 extern void ether_init_ctx(nsc_ctx_t *);
319 extern void rpc_init_ctx(nsc_ctx_t *);
320 extern void proto_init_ctx(nsc_ctx_t *);
321 extern void net_init_ctx(nsc_ctx_t *);
322 extern void bootp_init_ctx(nsc_ctx_t *);
323 extern void auuser_init_ctx(nsc_ctx_t *);
324 extern void auth_init_ctx(nsc_ctx_t *);
325 extern void serv_init_ctx(nsc_ctx_t *);
326 extern void netmask_init_ctx(nsc_ctx_t *);
327 extern void printer_init_ctx(nsc_ctx_t *);
328 extern void project_init_ctx(nsc_ctx_t *);
329 extern void tnrhtp_init_ctx(nsc_ctx_t *);
330 extern void tnrhdb_init_ctx(nsc_ctx_t *);
331 
332 /* Functions used to throttle threads */
333 extern int nscd_wait(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *);
334 extern int nscd_signal(nsc_ctx_t *, nsc_db_t *, nsc_entry_t *);
335 
336 /* Cache creation and initialization */
337 extern nscd_rc_t init_cache();
338 extern nsc_db_t *make_cache(enum db_type, int, char *,
339 	int (*compar) (const void *, const void *),
340 	void (*getlogstr)(char *, char *, size_t, nss_XbyY_args_t *),
341 	uint_t (*gethash)(nss_XbyY_key_t *, int),
342 	enum hash_type, int);
343 
344 /* Cache backend lookup */
345 extern void nsc_lookup(nsc_lookup_args_t *, int);
346 
347 /* Cache backend info */
348 extern void nsc_info(nsc_ctx_t *, char *, nscd_cfg_cache_t cfg[],
349 		nscd_cfg_stat_cache_t stats[]);
350 #ifdef NSCD_DEBUG
351 extern int nsc_dump(char *, int);
352 #endif	/* NSCD_DEBUG */
353 
354 /* Cache invalidate */
355 extern void nsc_invalidate(nsc_ctx_t *, char *, nsc_ctx_t **);
356 
357 /* Keep hot functions */
358 extern nsc_keephot_t *maken(int);
359 extern void *insertn(nsc_keephot_t *, uint_t, void *);
360 
361 /* hash related routines */
362 extern uint_t cis_gethash(const char *, int);
363 extern uint_t ces_gethash(const char *, int);
364 extern uint_t db_gethash(const void *, int, int);
365 
366 extern void leave(int n);
367 extern int get_cache_idx(char *);
368 
369 #ifdef	__cplusplus
370 }
371 #endif
372 
373 #endif	/* _NSCD_H */
374