xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-monitor/thread.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: thread.c,v 1.3 2021/08/14 16:15:00 christos Exp $	*/
2 
3 /* thread.c - deal with thread subsystem */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2001-2021 The OpenLDAP Foundation.
8  * Portions Copyright 2001-2003 Pierangelo Masarati.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was initially developed by Pierangelo Masarati for inclusion
21  * in OpenLDAP Software.
22  */
23 
24 #include <sys/cdefs.h>
25 __RCSID("$NetBSD: thread.c,v 1.3 2021/08/14 16:15:00 christos Exp $");
26 
27 #include "portable.h"
28 
29 #include <stdio.h>
30 #include <ac/string.h>
31 
32 #include "slap.h"
33 #include "back-monitor.h"
34 
35 #include <ldap_rq.h>
36 
37 typedef enum {
38 	MT_UNKNOWN,
39 	MT_RUNQUEUE,
40 	MT_TASKLIST,
41 
42 	MT_LAST
43 } monitor_thread_t;
44 
45 static struct {
46 	struct berval			rdn;
47 	struct berval			desc;
48 	struct berval			nrdn;
49 	ldap_pvt_thread_pool_param_t	param;
50 	monitor_thread_t		mt;
51 }		mt[] = {
52 	{ BER_BVC( "cn=Max" ),
53 		BER_BVC("Maximum number of threads as configured"),
54 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_MAX,		MT_UNKNOWN },
55 	{ BER_BVC( "cn=Max Pending" ),
56 		BER_BVC("Maximum number of pending threads"),
57 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_MAX_PENDING,	MT_UNKNOWN },
58 	{ BER_BVC( "cn=Open" ),
59 		BER_BVC("Number of open threads"),
60 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_OPEN,	MT_UNKNOWN },
61 	{ BER_BVC( "cn=Starting" ),
62 		BER_BVC("Number of threads being started"),
63 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_STARTING,	MT_UNKNOWN },
64 	{ BER_BVC( "cn=Active" ),
65 		BER_BVC("Number of active threads"),
66 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_ACTIVE,	MT_UNKNOWN },
67 	{ BER_BVC( "cn=Pending" ),
68 		BER_BVC("Number of pending threads"),
69 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_PENDING,	MT_UNKNOWN },
70 	{ BER_BVC( "cn=Backload" ),
71 		BER_BVC("Number of active plus pending threads"),
72 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD,	MT_UNKNOWN },
73 #if 0	/* not meaningful right now */
74 	{ BER_BVC( "cn=Active Max" ),
75 		BER_BVNULL,
76 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_ACTIVE_MAX,	MT_UNKNOWN },
77 	{ BER_BVC( "cn=Pending Max" ),
78 		BER_BVNULL,
79 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_PENDING_MAX,	MT_UNKNOWN },
80 	{ BER_BVC( "cn=Backload Max" ),
81 		BER_BVNULL,
82 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD_MAX,MT_UNKNOWN },
83 #endif
84 	{ BER_BVC( "cn=State" ),
85 		BER_BVC("Thread pool state"),
86 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_STATE,	MT_UNKNOWN },
87 
88 	{ BER_BVC( "cn=Runqueue" ),
89 		BER_BVC("Queue of running threads - besides those handling operations"),
90 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN,	MT_RUNQUEUE },
91 	{ BER_BVC( "cn=Tasklist" ),
92 		BER_BVC("List of running plus standby threads - besides those handling operations"),
93 		BER_BVNULL,	LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN,	MT_TASKLIST },
94 
95 	{ BER_BVNULL }
96 };
97 
98 static int
99 monitor_subsys_thread_update(
100 	Operation		*op,
101 	SlapReply		*rs,
102 	Entry 			*e );
103 
104 /*
105  * initializes log subentry
106  */
107 int
monitor_subsys_thread_init(BackendDB * be,monitor_subsys_t * ms)108 monitor_subsys_thread_init(
109 	BackendDB       	*be,
110 	monitor_subsys_t	*ms )
111 {
112 	monitor_info_t	*mi;
113 	monitor_entry_t	*mp;
114 	Entry		*e, **ep, *e_thread;
115 	int		i;
116 
117 	ms->mss_update = monitor_subsys_thread_update;
118 
119 	mi = ( monitor_info_t * )be->be_private;
120 
121 	if ( monitor_cache_get( mi, &ms->mss_ndn, &e_thread ) ) {
122 		Debug( LDAP_DEBUG_ANY,
123 			"monitor_subsys_thread_init: unable to get entry \"%s\"\n",
124 			ms->mss_dn.bv_val );
125 		return( -1 );
126 	}
127 
128 	mp = ( monitor_entry_t * )e_thread->e_private;
129 	mp->mp_children = NULL;
130 	ep = &mp->mp_children;
131 
132 	for ( i = 0; !BER_BVISNULL( &mt[ i ].rdn ); i++ ) {
133 		static char	buf[ BACKMONITOR_BUFSIZE ];
134 		int		count = -1;
135 		char		*state = NULL;
136 		struct berval	bv = BER_BVNULL;
137 
138 		/*
139 		 * Max
140 		 */
141 		e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn,
142 			&mt[ i ].rdn,
143 			mi->mi_oc_monitoredObject, NULL, NULL );
144 		if ( e == NULL ) {
145 			Debug( LDAP_DEBUG_ANY,
146 				"monitor_subsys_thread_init: "
147 				"unable to create entry \"%s,%s\"\n",
148 				mt[ i ].rdn.bv_val,
149 				ms->mss_ndn.bv_val );
150 			return( -1 );
151 		}
152 
153 		/* NOTE: reference to the normalized DN of the entry,
154 		 * under the assumption it's not modified */
155 		dnRdn( &e->e_nname, &mt[ i ].nrdn );
156 
157 		switch ( mt[ i ].param ) {
158 		case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
159 			break;
160 
161 		case LDAP_PVT_THREAD_POOL_PARAM_STATE:
162 			if ( ldap_pvt_thread_pool_query( &connection_pool,
163 				mt[ i ].param, (void *)&state ) == 0 )
164 			{
165 				ber_str2bv( state, 0, 0, &bv );
166 
167 			} else {
168 				BER_BVSTR( &bv, "unknown" );
169 			}
170 			break;
171 
172 		default:
173 			/* NOTE: in case of error, it'll be set to -1 */
174 			(void)ldap_pvt_thread_pool_query( &connection_pool,
175 				mt[ i ].param, (void *)&count );
176 			bv.bv_val = buf;
177 			bv.bv_len = snprintf( buf, sizeof( buf ), "%d", count );
178 			break;
179 		}
180 
181 		if ( !BER_BVISNULL( &bv ) ) {
182 			attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
183 		}
184 
185 		if ( !BER_BVISNULL( &mt[ i ].desc ) ) {
186 			attr_merge_normalize_one( e,
187 				slap_schema.si_ad_description,
188 				&mt[ i ].desc, NULL );
189 		}
190 
191 		mp = monitor_entrypriv_create();
192 		if ( mp == NULL ) {
193 			return -1;
194 		}
195 		e->e_private = ( void * )mp;
196 		mp->mp_info = ms;
197 		mp->mp_flags = ms->mss_flags \
198 			| MONITOR_F_SUB | MONITOR_F_PERSISTENT;
199 
200 		if ( monitor_cache_add( mi, e ) ) {
201 			Debug( LDAP_DEBUG_ANY,
202 				"monitor_subsys_thread_init: "
203 				"unable to add entry \"%s,%s\"\n",
204 				mt[ i ].rdn.bv_val,
205 				ms->mss_dn.bv_val );
206 			return( -1 );
207 		}
208 
209 		*ep = e;
210 		ep = &mp->mp_next;
211 	}
212 
213 	monitor_cache_release( mi, e_thread );
214 
215 	return( 0 );
216 }
217 
218 static int
monitor_subsys_thread_update(Operation * op,SlapReply * rs,Entry * e)219 monitor_subsys_thread_update(
220 	Operation		*op,
221 	SlapReply		*rs,
222 	Entry 			*e )
223 {
224 	monitor_info_t	*mi = ( monitor_info_t * )op->o_bd->be_private;
225 	Attribute		*a;
226 	BerVarray		vals = NULL;
227 	char 			buf[ BACKMONITOR_BUFSIZE ];
228 	struct berval		rdn, bv;
229 	int			which, i;
230 	struct re_s		*re;
231 	int			count = -1;
232 	char			*state = NULL;
233 
234 	assert( mi != NULL );
235 
236 	dnRdn( &e->e_nname, &rdn );
237 
238 	for ( i = 0; !BER_BVISNULL( &mt[ i ].nrdn ); i++ ) {
239 		if ( dn_match( &mt[ i ].nrdn, &rdn ) ) {
240 			break;
241 		}
242 	}
243 
244 	which = i;
245 	if ( BER_BVISNULL( &mt[ which ].nrdn ) ) {
246 		return SLAP_CB_CONTINUE;
247 	}
248 
249 	a = attr_find( e->e_attrs, mi->mi_ad_monitoredInfo );
250 
251 	switch ( mt[ which ].param ) {
252 	case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
253 		switch ( mt[ which ].mt ) {
254 		case MT_RUNQUEUE:
255 			if ( a != NULL ) {
256 				if ( a->a_nvals != a->a_vals ) {
257 					ber_bvarray_free( a->a_nvals );
258 				}
259 				ber_bvarray_free( a->a_vals );
260 				a->a_vals = NULL;
261 				a->a_nvals = NULL;
262 				a->a_numvals = 0;
263 			}
264 
265 			i = 0;
266 			bv.bv_val = buf;
267 			ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
268 			LDAP_STAILQ_FOREACH( re, &slapd_rq.run_list, rnext ) {
269 				bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)",
270 					i, re->tname, re->tspec );
271 				if ( bv.bv_len < sizeof( buf ) ) {
272 					value_add_one( &vals, &bv );
273 				}
274 				i++;
275 			}
276 			ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
277 
278 			if ( vals ) {
279 				attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL );
280 				ber_bvarray_free( vals );
281 
282 			} else {
283 				attr_delete( &e->e_attrs, mi->mi_ad_monitoredInfo );
284 			}
285 			break;
286 
287 		case MT_TASKLIST:
288 			if ( a != NULL ) {
289 				if ( a->a_nvals != a->a_vals ) {
290 					ber_bvarray_free( a->a_nvals );
291 				}
292 				ber_bvarray_free( a->a_vals );
293 				a->a_vals = NULL;
294 				a->a_nvals = NULL;
295 				a->a_numvals = 0;
296 			}
297 
298 			i = 0;
299 			bv.bv_val = buf;
300 			ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
301 			LDAP_STAILQ_FOREACH( re, &slapd_rq.task_list, tnext ) {
302 				bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)",
303 					i, re->tname, re->tspec );
304 				if ( bv.bv_len < sizeof( buf ) ) {
305 					value_add_one( &vals, &bv );
306 				}
307 				i++;
308 			}
309 			ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
310 
311 			if ( vals ) {
312 				attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL );
313 				ber_bvarray_free( vals );
314 
315 			} else {
316 				attr_delete( &e->e_attrs, mi->mi_ad_monitoredInfo );
317 			}
318 			break;
319 
320 		default:
321 			assert( 0 );
322 		}
323 		break;
324 
325 	case LDAP_PVT_THREAD_POOL_PARAM_STATE:
326 		if ( a == NULL ) {
327 			return rs->sr_err = LDAP_OTHER;
328 		}
329 		if ( ldap_pvt_thread_pool_query( &connection_pool,
330 			mt[ i ].param, (void *)&state ) == 0 )
331 		{
332 			ber_str2bv( state, 0, 0, &bv );
333 			ber_bvreplace( &a->a_vals[ 0 ], &bv );
334 		}
335 		break;
336 
337 	default:
338 		if ( a == NULL ) {
339 			return rs->sr_err = LDAP_OTHER;
340 		}
341 		if ( ldap_pvt_thread_pool_query( &connection_pool,
342 			mt[ i ].param, (void *)&count ) == 0 )
343 		{
344 			bv.bv_val = buf;
345 			bv.bv_len = snprintf( buf, sizeof( buf ), "%d", count );
346 			if ( bv.bv_len < sizeof( buf ) ) {
347 				ber_bvreplace( &a->a_vals[ 0 ], &bv );
348 			}
349 		}
350 		break;
351 	}
352 
353 	/* FIXME: touch modifyTimestamp? */
354 
355 	return SLAP_CB_CONTINUE;
356 }
357