nscd_nswstate.c revision 2830:5228d1267a01
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 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <assert.h>
31#include <string.h>
32#include "nscd_switch.h"
33#include "nscd_log.h"
34
35/*
36 * nscd_nsw_state_t list for each nss database. Protected
37 * by the readers/writer lock nscd_nsw_state_base_lock.
38 */
39nscd_nsw_state_base_t **nscd_nsw_state_base;
40static rwlock_t nscd_nsw_state_base_lock = DEFAULTRWLOCK;
41
42static void
43_nscd_free_nsw_state(
44	nscd_nsw_state_t	*s)
45{
46
47	int			i;
48	char			*me = "_nscd_free_nsw_state";
49
50	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
51	(me, "freeing nsw state = %p\n", s);
52
53	if (s == NULL)
54		return;
55
56	if (s->nsw_cfg_p != NULL)
57		/*
58		 * an nsw state without base does not reference
59		 * count the nsw config data (ie not using a
60		 * shared one), so the one created for it should
61		 * be freed
62		 */
63		if ((*s->nsw_cfg_p)->nobase != 1)
64			_nscd_release((nscd_acc_data_t *)s->nsw_cfg_p);
65		else
66			_nscd_free_nsw_config(*s->nsw_cfg_p);
67
68	if (s->be_db_pp != NULL) {
69		for (i = 0; i < s->max_src; i++) {
70			if (s->be_db_pp[i] == NULL)
71				continue;
72			_nscd_release((nscd_acc_data_t *)s->be_db_pp[i]);
73			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
74			(me, "release db be ptr %p\n", s->be_db_pp[i]);
75		}
76		free(s->be_db_pp);
77	}
78
79	if (s->be != NULL) {
80		for (i = 0; i < s->max_src; i++) {
81			if (s->be[i] == NULL)
82				continue;
83			if (s->getent == 1)
84				(void) NSS_INVOKE_DBOP(s->be[i],
85					NSS_DBOP_ENDENT, 0);
86			(void) NSS_INVOKE_DBOP(s->be[i],
87				NSS_DBOP_DESTRUCTOR, 0);
88		}
89		free(s->be);
90	}
91
92	s->base = NULL;
93
94	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
95	(me, "nsw state %p freed \n", s);
96
97	free(s);
98}
99
100static void
101_nscd_free_nsw_state_base(
102	nscd_acc_data_t		*data)
103{
104	nscd_nsw_state_base_t	*base = (nscd_nsw_state_base_t *)data;
105	nscd_nsw_state_t	*s, *ts;
106	int			i;
107	char			*me = "_nscd_free_nsw_state_base";
108
109	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
110	(me, "freeing db state base %p\n", base);
111
112	if (base == NULL)
113		return;
114
115	for (i = 0; i < 2; i++) {
116		if (i == 1)
117			s = base->nsw_state.first;
118		else
119			s = base->nsw_state_thr.first;
120
121		while (s != NULL) {
122			ts = s->next;
123			_nscd_free_nsw_state(s);
124			s = ts;
125		}
126	}
127
128	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
129	(me, "nsw state base %p freed \n", base);
130}
131
132void
133_nscd_free_all_nsw_state_base()
134{
135	nscd_nsw_state_base_t	*base;
136	int			i;
137	char			*me = "_nscd_free_all_nsw_state_base";
138
139	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
140	(me, "freeing all db state base\n");
141
142	(void) rw_wrlock(&nscd_nsw_state_base_lock);
143	for (i = 0; i < NSCD_NUM_DB; i++) {
144
145		base = nscd_nsw_state_base[i];
146		_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
147			NSCD_LOG_LEVEL_DEBUG)
148		(me, "freeing db state base (%d) %p \n", i, base);
149
150		if (base == NULL)
151			continue;
152
153		nscd_nsw_state_base[i] = (nscd_nsw_state_base_t *)
154			_nscd_set((nscd_acc_data_t *)base, NULL);
155	}
156	(void) rw_unlock(&nscd_nsw_state_base_lock);
157}
158
159static nscd_nsw_state_t *
160_nscd_create_nsw_state(
161	nscd_nsw_params_t	*params)
162{
163	nscd_nsw_state_t	*s;
164	nscd_nsw_config_t	*nsw_cfg;
165	nscd_db_t		**be_db_p, *be_db;
166	int			i, nobe = 1;
167	char			*me = "_nscd_create_nsw_state";
168
169
170	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
171	(me, "creating nsw state...\n");
172
173	s = calloc(1, sizeof (nscd_nsw_state_t));
174	if (s == NULL) {
175		if ((*s->nsw_cfg_p)->nobase  != 1)
176			_nscd_release((nscd_acc_data_t *)params->nswcfg);
177		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
178		(me, "not able to allocate a nsw state\n");
179		return (NULL);
180	} else
181		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
182		(me, "nsw state %p allocated\n", s);
183
184	s->dbi = params->dbi;
185	s->next = NULL;
186
187	nsw_cfg = *params->nswcfg;
188
189	s->nsw_cfg_p = params->nswcfg;
190	s->config = nsw_cfg->nsw_config;
191	s->max_src = nsw_cfg->max_src;
192	s->p = params->p;
193
194	s->be = calloc(s->max_src, sizeof (nss_backend_t **));
195	if (s->be == NULL) {
196		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
197		(me, "not able to allocate s->be\n");
198
199		_nscd_free_nsw_state(s);
200		return (NULL);
201	} else {
202		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
203		(me, "db be array %p allocated\n", s->be);
204	}
205
206	s->be_db_pp = calloc(s->max_src, sizeof (nscd_db_t ***));
207	if (s->be_db_pp == NULL) {
208		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
209		(me, "not able to allocate s->be_db_pp\n");
210		_nscd_free_nsw_state(s);
211		return (NULL);
212	} else {
213		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
214		(me, "be_db_pp array %p allocated\n", s->be_db_pp);
215	}
216
217	/* create the source:database backends */
218	for (i = 0;  i < s->max_src;  i++) {
219		nss_backend_t		*be;
220		int			srci;
221		char			*srcn;
222		const char		*dbn;
223		struct __nsw_lookup_v1	*lkp;
224		const nscd_db_entry_t	*dbe;
225		nscd_be_info_t		*be_info;
226
227		if (i == 0)
228			lkp = s->config->lookups;
229		else
230			lkp = lkp->next;
231		if (lkp == NULL) {
232			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
233			(me, "error: lkp is NULL\n");
234			_nscd_free_nsw_state(s);
235			return (NULL);
236		}
237
238		srci = nsw_cfg->src_idx[i];
239		srcn = lkp->service_name;
240		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
241		(me, "source name = %s, index = %d\n", srcn, srci);
242
243		be_db_p = (nscd_db_t **)_nscd_get(
244				(nscd_acc_data_t *)nscd_src_backend_db[srci]);
245		if (be_db_p == NULL) {
246			_nscd_free_nsw_state(s);
247			return (NULL);
248		}
249		be_db = *be_db_p;
250		s->be_db_pp[i] = be_db_p;
251		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
252		(me, "be db ptr array %p referenced\n", be_db_p);
253
254		be_info = NULL;
255		be = NULL;
256		dbn = params->p.name;
257		dbe = _nscd_get_db_entry(be_db, NSCD_DATA_BACKEND_INFO,
258			(const char *)dbn, NSCD_GET_FIRST_DB_ENTRY, 0);
259		if (dbe != NULL)
260			be_info = (nscd_be_info_t *)*(dbe->data_array);
261
262		if (be_info == NULL || be_info->be_constr == NULL) {
263			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
264			(me, "no backend info or be_constr is NULL "
265			    "for <%s : %s>\n", NSCD_NSW_SRC_NAME(srci),
266				dbn);
267		} else
268			be = (be_info->be_constr)(dbn,
269				NSCD_NSW_SRC_NAME(srci), 0);
270
271		if (be == NULL) {
272			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
273			(me, "not able to init be for <%s : %s>\n",
274			NSCD_NSW_SRC_NAME(srci), dbn);
275
276			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
277			(me, "releasing db be ptr %p\n", be_db_p);
278
279			_nscd_release((nscd_acc_data_t *)be_db_p);
280			s->be_db_pp[i] = NULL;
281
282			continue;
283		}
284
285		s->be[i] = be;
286		nobe = 0;
287	}
288
289	if (nobe == 1) {
290		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
291		(me, "NO backend found, returning NULL\n");
292
293		_nscd_free_nsw_state(s);
294		return (NULL);
295	}
296
297	return (s);
298}
299
300static nscd_rc_t
301_get_nsw_state_int(
302	nss_db_root_t		*rootp,
303	nscd_nsw_params_t	*params,
304	thread_t		*tid)
305{
306
307	nscd_nsw_state_t	*ret = NULL;
308	nscd_nsw_config_t	**nswcfg;
309	nscd_nsw_state_base_t	*base;
310	nscd_state_ctrl_t	*ctrl_p;
311	int			thread_only = 0, wait_cond = 0;
312	char			*me = "_get_nsw_state_int";
313	int			dbi;
314	nscd_rc_t		rc;
315
316	dbi = params->dbi;
317
318	/*
319	 * no nsw state will be reused, if asked to use
320	 * default config. So create the new structures
321	 * used by the switch engine and the new nsw state
322	 */
323	if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
324		rc = _nscd_create_sw_struct(dbi, (char *)params->p.name,
325			(char *)params->p.default_config, NULL, params);
326		if (rc != NSCD_SUCCESS)
327			return (rc);
328
329		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
330		(me, "no base nsw config created for %s (sources: %s)\n",
331				params->p.name, params->p.default_config);
332
333		ret = _nscd_create_nsw_state(params);
334		if (ret == NULL)
335			return (NSCD_CREATE_NSW_STATE_FAILED);
336		rootp->s = (struct nss_db_state *)ret;
337		return (NSCD_SUCCESS);
338	}
339
340	/*
341	 * if getting a nsw state for a request from the compat
342	 * backend, create the new switch structures if this
343	 * is the first time around for a passwd, shadow, group,
344	 * audit_user, or user_attr database
345	 */
346	if (params->compati != -1) {
347
348		nscd_nsw_config_t	**nswcfg1;
349		int			i = params->compati;
350
351		nswcfg = (nscd_nsw_config_t **)_nscd_get(
352			(nscd_acc_data_t *)nscd_nsw_config[i]);
353
354		/*
355		 * if nsw data structures not created yet, get the
356		 * config string from the passwd_compat or
357		 * group_compat DB and create the structures
358		 */
359		if (nswcfg == NULL) {
360			nswcfg1 = (nscd_nsw_config_t **)_nscd_get(
361			(nscd_acc_data_t *)nscd_nsw_config[params->cfgdbi]);
362			if (nswcfg1 == NULL) {
363				_NSCD_LOG(NSCD_LOG_NSW_STATE,
364					NSCD_LOG_LEVEL_ERROR)
365				(me, "no nsw config for %s\n",
366					params->p.name);
367				return (NSCD_CREATE_NSW_STATE_FAILED);
368			}
369
370			rc = _nscd_create_sw_struct(i, params->p.name,
371				(*nswcfg1)->nsw_cfg_str, NULL, params);
372			_nscd_release((nscd_acc_data_t *)nswcfg1);
373			if (rc != NSCD_SUCCESS)
374				return (rc);
375
376			_NSCD_LOG(NSCD_LOG_NSW_STATE,
377				NSCD_LOG_LEVEL_DEBUG)
378				(me, "nsw config created for %s (%s)\n",
379				params->p.name, (*nswcfg1)->nsw_cfg_str);
380		} else
381			_nscd_release((nscd_acc_data_t *)nswcfg);
382	}
383
384	(void) rw_rdlock(&nscd_nsw_state_base_lock);
385	base = nscd_nsw_state_base[dbi];
386	(void) rw_unlock(&nscd_nsw_state_base_lock);
387	if (base == NULL)
388		assert(base != NULL);
389
390	/*
391	 * If list is not empty, return the first one on list.
392	 * Otherwise, create and return a new db state if the
393	 * limit is not reached. if reacehed, wait for the 'one
394	 * is available' signal.
395	 */
396	assert(base == (nscd_nsw_state_base_t *)_nscd_mutex_lock(
397		(nscd_acc_data_t *)base));
398
399	if (tid == NULL) {
400		ctrl_p = &base->nsw_state;
401	} else {
402		thread_only = 1;
403		ctrl_p = &base->nsw_state_thr;
404
405		_NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
406			_nscd_logit(me, "per thread nsw state info: \n");
407			_nscd_logit(me, "tid = %d\n", *tid);
408			_nscd_logit(me, "tid in base = %d\n", base->tid);
409			_nscd_logit(me, "number of free nsw_state = %d\n",
410				ctrl_p->free);
411			_nscd_logit(me, "number of nsw state allocated = %d\n",
412				ctrl_p->allocated);
413			_nscd_logit(me, "first nsw state on list = %p\n",
414				ctrl_p->first);
415			_nscd_logit(me, "number of waiter = %d\n",
416				ctrl_p->waiter);
417		}
418	}
419
420	if (ctrl_p->first == NULL && ctrl_p->allocated == ctrl_p->max)
421		wait_cond = 1;
422	else if (thread_only && base->used_by_thr && base->tid != *tid)
423		wait_cond = 1;
424
425	if (wait_cond) {
426
427		ctrl_p->waiter++;
428
429		while (wait_cond) {
430			if (!thread_only)
431				_NSCD_LOG(NSCD_LOG_NSW_STATE,
432					NSCD_LOG_LEVEL_DEBUG)
433				(me, "waiting for nsw state signal\n");
434			else
435				_NSCD_LOG(NSCD_LOG_NSW_STATE,
436					NSCD_LOG_LEVEL_DEBUG)
437				(me, "waiting for per thread "
438				    "nsw state signal\n");
439
440			if (thread_only) {
441				_nscd_cond_wait((nscd_acc_data_t *)base,
442					&base->thr_cond);
443
444				if (base->used_by_thr == 0 &&
445					ctrl_p->first != NULL)
446					wait_cond = 0;
447			} else {
448				_nscd_cond_wait((nscd_acc_data_t *)base, NULL);
449
450				if (ctrl_p->first != NULL)
451					wait_cond = 0;
452			}
453
454			if (!thread_only)
455				_NSCD_LOG(NSCD_LOG_NSW_STATE,
456					NSCD_LOG_LEVEL_DEBUG)
457				(me, "woke from cond wait ...wait_cond = %d\n",
458					wait_cond);
459			else
460
461				_NSCD_LOG(NSCD_LOG_NSW_STATE,
462					NSCD_LOG_LEVEL_DEBUG)
463				(me, "woke from cond wait (per thread) "
464					"...wait_cond = %d\n", wait_cond);
465
466		}
467
468		ctrl_p->waiter--;
469	}
470
471	if (ctrl_p->first == NULL) {
472		int	geti;
473
474		/*
475		 * for lookup calls from the compat backend
476		 * uses the switch policy for passwd_compat
477		 * or group_compat
478		 */
479		if (params->compati != -1)
480			geti = params->compati;
481		else
482			geti = params->dbi;
483
484		params->nswcfg = (nscd_nsw_config_t **)_nscd_get(
485			(nscd_acc_data_t *)nscd_nsw_config[geti]);
486		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
487		(me, "got a nsw config %p for index %d\n",
488			params->nswcfg, geti);
489
490		ctrl_p->first = _nscd_create_nsw_state(params);
491		if (ctrl_p->first != NULL) {
492			ctrl_p->first->base = base;
493
494			if (tid == NULL) {
495				_NSCD_LOG(NSCD_LOG_NSW_STATE,
496					NSCD_LOG_LEVEL_DEBUG)
497				(me, "got a new nsw_state %p\n", ctrl_p->first);
498			} else {
499				_NSCD_LOG(NSCD_LOG_NSW_STATE,
500					NSCD_LOG_LEVEL_DEBUG)
501				(me, "got a new per thread nsw_state %p\n",
502				ctrl_p->first);
503			}
504			ctrl_p->allocated++;
505			ctrl_p->free++;
506		} else {
507			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
508				(me, "error: unable to obtain a nsw state\n");
509			_nscd_mutex_unlock((nscd_acc_data_t *)base);
510			return (NSCD_CREATE_NSW_STATE_FAILED);
511		}
512	}
513
514	ret = ctrl_p->first;
515	ctrl_p->first = ret->next;
516	ret->next = NULL;
517	ctrl_p->free--;
518	if (thread_only) {
519		base->tid = *tid;
520		base->used_by_thr = 1;
521
522		_NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
523			_nscd_logit(me, "\t\t\tgot a per thread nsw "
524			    "state %p: \n", ret);
525			_nscd_logit(me, "tid = %d\n", *tid);
526			_nscd_logit(me, "tid in base = %d\n", base->tid);
527			_nscd_logit(me, "number of free nsw_state = %d\n",
528				ctrl_p->free);
529			_nscd_logit(me, "number od nsw state allocated = %d\n",
530				ctrl_p->allocated);
531			_nscd_logit(me, "first nsw state on list = %p\n",
532				ctrl_p->first);
533			_nscd_logit(me, "number of waiter = %d\n",
534				ctrl_p->waiter);
535		}
536	}
537	else
538		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
539		(me, "got old nsw state %p\n", ret);
540
541	_nscd_mutex_unlock((nscd_acc_data_t *)base);
542
543	rootp->s = (struct nss_db_state *)ret;
544
545	return (NSCD_SUCCESS);
546}
547
548nscd_rc_t
549_nscd_get_nsw_state(
550	nss_db_root_t		*rootp,
551	nscd_nsw_params_t	*params)
552{
553	return (_get_nsw_state_int(rootp, params, NULL));
554}
555
556nscd_rc_t
557_nscd_get_nsw_state_thread(
558	nss_db_root_t		*rootp,
559	nscd_nsw_params_t	*params)
560{
561	thread_t	tid = thr_self();
562	return (_get_nsw_state_int(rootp, params, &tid));
563}
564
565
566static void
567_put_nsw_state_int(
568	nscd_nsw_state_t	*s,
569	thread_t		*tid)
570{
571
572	nscd_nsw_state_base_t	*base;
573	nscd_state_ctrl_t	*ctrl_p;
574	int			thread_only = 0;
575	char			*me = "_put_nsw_state_int";
576
577	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
578	(me, "put back a nsw state\n");
579
580	if (s == NULL) {
581		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
582		(me, "nsw state is NULL, nothing to put back\n");
583		return;
584	}
585
586	/*
587	 * no need to put back if the nsw state is not on any base
588	 * but need to free the resources used
589	 */
590	if ((*s->nsw_cfg_p)->nobase  == 1) {
591		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
592		(me, "no base nsw state, freeing resources ...\n");
593
594		_nscd_free_nsw_state(s);
595		return;
596	}
597
598	if (tid != NULL)
599		thread_only = 1;
600
601	base = s->base;
602
603	if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) {
604		/* base has been freed, free this db state */
605		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
606		(me, "nsw state base has been freed, freeing %p\n", s);
607		_nscd_free_nsw_state(s);
608		return;
609	}
610
611	if (thread_only)
612		ctrl_p = &base->nsw_state_thr;
613	else
614		ctrl_p = &base->nsw_state;
615
616	_NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
617		_nscd_logit(me, "before returning the nsw state: \n");
618		_nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
619		_nscd_logit(me, "tid in base = %d\n", base->tid);
620		_nscd_logit(me, "number of free nsw_state = %d\n",
621			ctrl_p->free);
622		_nscd_logit(me, "number od nsw state allocated = %d\n",
623			ctrl_p->allocated);
624		_nscd_logit(me, "first nsw state on list = %p\n",
625			ctrl_p->first);
626		_nscd_logit(me, "number of waiter = %d\n",
627			ctrl_p->waiter);
628	}
629
630	if (ctrl_p->first != NULL) {
631		s->next = ctrl_p->first;
632		ctrl_p->first = s;
633	} else {
634		ctrl_p->first = s;
635		s->next = NULL;
636	}
637	ctrl_p->free++;
638
639	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
640	(me, "signaling waiter thread_only = %d..\n", thread_only);
641
642	if (thread_only && ctrl_p->free == ctrl_p->allocated) {
643		assert(ctrl_p->first != NULL);
644		base->used_by_thr = 0;
645		if (ctrl_p->waiter > 0) {
646			(void) cond_signal(&base->thr_cond);
647		}
648	}
649
650	if (!thread_only && ctrl_p->waiter > 0) {
651
652		_nscd_cond_signal((nscd_acc_data_t *)base);
653	}
654
655	_NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
656		_nscd_logit(me, "after the nsw state is returned: \n");
657		_nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
658		_nscd_logit(me, "tid in base = %d\n", base->tid);
659		_nscd_logit(me, "number of free nsw_state = %d\n",
660			ctrl_p->free);
661		_nscd_logit(me, "number od nsw state allocated = %d\n",
662			ctrl_p->allocated);
663		_nscd_logit(me, "first nsw state on list = %p\n",
664			ctrl_p->first);
665		_nscd_logit(me, "tnumber of waiter = %d\n",
666			ctrl_p->waiter);
667	}
668
669	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
670	(me, "done putting back nsw state %p, thread_only = %d\n",
671			s, thread_only);
672
673	_nscd_mutex_unlock((nscd_acc_data_t *)base);
674
675}
676
677void
678_nscd_put_nsw_state(
679	nscd_nsw_state_t	*s)
680{
681	_put_nsw_state_int(s, NULL);
682}
683
684void
685_nscd_put_nsw_state_thread(
686	nscd_nsw_state_t	*s)
687{
688	thread_t		tid = thr_self();
689	_put_nsw_state_int(s, &tid);
690}
691
692nscd_rc_t
693_nscd_init_nsw_state_base(
694	int			dbi,
695	int			lock)
696{
697	nscd_nsw_state_base_t	*base = NULL;
698	char			*me = "_nscd_init_nsw_state_base";
699
700	if (lock)
701		(void) rw_rdlock(&nscd_nsw_state_base_lock);
702
703	base = (nscd_nsw_state_base_t *)_nscd_alloc(
704		NSCD_DATA_NSW_STATE_BASE,
705		sizeof (nscd_nsw_state_base_t),
706		_nscd_free_nsw_state_base,
707		NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND);
708
709	if (base == NULL) {
710		_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
711			NSCD_LOG_LEVEL_ERROR)
712		(me, "not able to allocate a nsw state base\n");
713		if (lock)
714			(void) rw_unlock(&nscd_nsw_state_base_lock);
715		return (NSCD_NO_MEMORY);
716	}
717	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
718			NSCD_LOG_LEVEL_DEBUG)
719		(me, "nsw state base %p allocated\n", base);
720
721	/*
722	 * initialize and activate the new nss_nsw_state base
723	 */
724	base->dbi = dbi;
725	base->nsw_state.max = NSCD_SW_CFG(dbi).max_nsw_state_per_db;
726	base->nsw_state_thr.max = NSCD_SW_CFG(dbi).max_nsw_state_per_thread;
727
728	nscd_nsw_state_base[dbi] = (nscd_nsw_state_base_t *)_nscd_set(
729		(nscd_acc_data_t *)nscd_nsw_state_base[dbi],
730		(nscd_acc_data_t *)base);
731
732	if (lock)
733		(void) rw_unlock(&nscd_nsw_state_base_lock);
734
735	return (NSCD_SUCCESS);
736}
737
738nscd_rc_t
739_nscd_init_all_nsw_state_base()
740{
741	int			i;
742	nscd_rc_t		rc;
743	char			*me = "_nscd_init_all_nsw_state_base";
744
745	(void) rw_rdlock(&nscd_nsw_state_base_lock);
746
747	for (i = 0; i < NSCD_NUM_DB; i++) {
748
749		rc = _nscd_init_nsw_state_base(i, 0);
750
751		if (rc != NSCD_SUCCESS) {
752			_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
753				NSCD_LOG_LEVEL_ERROR)
754			(me, "not able to initialize a nsw db state "
755				"base (%d)\n", i);
756
757			(void) rw_unlock(&nscd_nsw_state_base_lock);
758			return (rc);
759		}
760	}
761	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
762			NSCD_LOG_LEVEL_DEBUG)
763	(me, "all nsw state base initialized\n");
764
765	(void) rw_unlock(&nscd_nsw_state_base_lock);
766
767	return (NSCD_SUCCESS);
768}
769
770nscd_rc_t
771_nscd_alloc_nsw_state_base()
772{
773
774	(void) rw_rdlock(&nscd_nsw_state_base_lock);
775
776	nscd_nsw_state_base = calloc(NSCD_NUM_DB,
777		sizeof (nscd_nsw_state_base_t *));
778	if (nscd_nsw_state_base == NULL) {
779		(void) rw_unlock(&nscd_nsw_state_base_lock);
780		return (NSCD_NO_MEMORY);
781	}
782
783	(void) rw_rdlock(&nscd_nsw_state_base_lock);
784
785	return (NSCD_SUCCESS);
786}
787