nscd_smfmonitor.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 <stdlib.h>
29#include <libscf.h>
30#include <string.h>
31#include "nscd_switch.h"
32#include "nscd_log.h"
33#include "nscd_door.h"
34
35extern int	_whoami;
36
37/*
38 * Service states monitored by nscd. Protected by
39 * readers/writer lock nscd_smf_service_state_lock
40 */
41nscd_smf_state_t *nscd_smf_service_state;
42static rwlock_t nscd_smf_service_state_lock = DEFAULTRWLOCK;
43/*
44 * init service state table
45 */
46nscd_rc_t
47_nscd_alloc_service_state_table()
48{
49	int i;
50
51	nscd_smf_service_state = calloc(NSCD_NUM_SMF_FMRI,
52		sizeof (nscd_smf_state_t));
53
54	if (nscd_smf_service_state == NULL)
55		return (NSCD_NO_MEMORY);
56
57	for (i = 1; i < NSCD_NUM_SMF_FMRI; i++)
58		NSCD_SMF_SVC_STATE(i) = NSCD_SVC_STATE_UNINITED;
59
60	return (NSCD_SUCCESS);
61}
62
63static int
64query_smf_state(int srci)
65{
66
67	int	ret = NSCD_SVC_STATE_UNINITED;
68	char	*state = NULL;
69	char	*me = "query_smf_state";
70
71	state = smf_get_state(NSCD_SMF_SVC_FMRI(srci));
72	if (state == NULL)
73		return (ret);
74
75	_NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_DEBUG)
76		(me, "%s -- %s\n", state, NSCD_SMF_SVC_FMRI(srci));
77
78	(void) rw_wrlock(&nscd_smf_service_state_lock);
79
80	if (nscd_smf_service_state[srci].src_name == NULL)
81		nscd_smf_service_state[srci].src_name =
82			NSCD_NSW_SRC_NAME(srci);
83
84	if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0)
85		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_UNINIT;
86	else if (strcmp(state, SCF_STATE_STRING_MAINT) == 0)
87		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_MAINT;
88	else if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0)
89		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_OFFLINE;
90	else if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
91		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_DISABLED;
92	else if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0)
93		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_ONLINE;
94	else if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)
95		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_DEGRADED;
96
97	ret = NSCD_SMF_SVC_STATE(srci);
98	(void) rw_unlock(&nscd_smf_service_state_lock);
99
100	free(state);
101	return (ret);
102}
103
104/* ARGSUSED */
105static void *
106set_smf_state(void *arg)
107{
108
109	int	i;
110	int	st;
111
112	/*
113	 * the forker nscd needs not monitor the state
114	 * of the client services
115	 */
116	if (_whoami == NSCD_FORKER)
117		thr_exit(0);
118
119	/*CONSTCOND*/
120	while (1) {
121
122		/* skip the first service which is nscd */
123		for (i = 1; i < NSCD_NUM_SMF_FMRI; i++) {
124			st = query_smf_state(i);
125			if (st == NSCD_SVC_STATE_UNINITED)
126				break;
127		}
128
129		(void) sleep(NSCD_SW_CFG_G.check_smf_state_interval_g);
130	}
131	/* NOTREACHED */
132	/*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
133}
134
135nscd_rc_t
136_nscd_init_smf_monitor() {
137
138	int	errnum;
139	char	*me = "_nscd_init_smf_monitor";
140
141	_NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_DEBUG)
142	(me, "initializing the smf monitor\n");
143
144	/*
145	 * start a thread to check the state of the client services
146	 */
147	if (thr_create(NULL, NULL, set_smf_state,
148		NULL, THR_DETACHED, NULL) != 0) {
149		errnum = errno;
150		_NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_ERROR)
151		(me, "thr_create: %s\n", strerror(errnum));
152		return (NSCD_THREAD_CREATE_ERROR);
153	}
154
155	return (NSCD_SUCCESS);
156}
157
158int
159_nscd_get_smf_state(int srci, int dbi, int recheck)
160{
161	int	s;
162	char	*n;
163
164	n = NSCD_NSW_SRC_NAME(srci);
165
166	/* the files, compat, and dns backends are always available */
167	if ((*n == 'f' || *n == 'c' || *n == 'd') &&
168		(strcmp(NSCD_NSW_SRC_NAME(srci), "files") == 0 ||
169		strcmp(NSCD_NSW_SRC_NAME(srci), "compat") == 0 ||
170		strcmp(NSCD_NSW_SRC_NAME(srci), "dns") == 0)) {
171		return (SCF_STATE_ONLINE);
172	}
173
174	/*
175	 * for the printer database and user backend, treat the
176	 * backend as a unsupported one, as nscd can not access
177	 * the home directory of the user
178	 */
179	if (*n == 'u' && strcmp(NSCD_NSW_SRC_NAME(srci), "user") == 0) {
180		if (strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_PRINTERS) == 0)
181			return (NSCD_SVC_STATE_UNKNOWN_SRC);
182		else
183			return (SCF_STATE_ONLINE);
184	}
185
186	/*
187	 * unknown backend is not supported by nscd,
188	 * tell the switch engine to return NSS_TRYLOCAL
189	 * via rc NSCD_SVC_STATE_UNKNOWN_SRC
190	 */
191	if (srci >= _nscd_cfg_num_nsw_src)
192		return (NSCD_SVC_STATE_UNKNOWN_SRC);
193
194	if (recheck == 1)
195		return (query_smf_state(srci));
196
197	(void) rw_rdlock(&nscd_smf_service_state_lock);
198	s = NSCD_SMF_SVC_STATE(srci);
199	(void) rw_unlock(&nscd_smf_service_state_lock);
200
201	/*
202	 * if the state has been queried at least once but is
203	 * still not online, query one more time
204	 */
205	if (s != NSCD_SVC_STATE_UNINITED && s < SCF_STATE_ONLINE)
206		s = query_smf_state(srci);
207
208	return (s);
209}
210