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