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