]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/thread.c
0537c9a130fd8c989ac6b87aaf7f331d3a0a0b1a
[openldap] / servers / slapd / back-monitor / thread.c
1 /* thread.c - deal with thread subsystem */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2001-2014 The OpenLDAP Foundation.
6  * Portions Copyright 2001-2003 Pierangelo Masarati.
7  * All rights reserved.
8  *
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.
12  *
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>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Pierangelo Masarati for inclusion
19  * in OpenLDAP Software.
20  */
21
22 #include "portable.h"
23
24 #include <stdio.h>
25 #include <ac/string.h>
26
27 #include "slap.h"
28 #include "back-monitor.h"
29
30 #include <ldap_rq.h>
31
32 #ifndef NO_THREADS
33 typedef enum {
34         MT_UNKNOWN,
35         MT_RUNQUEUE,
36         MT_TASKLIST,
37
38         MT_LAST
39 } monitor_thread_t;
40
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 },
83
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 },
90
91         { BER_BVNULL }
92 };
93
94 static int 
95 monitor_subsys_thread_update( 
96         Operation               *op,
97         SlapReply               *rs,
98         Entry                   *e );
99 #endif /* ! NO_THREADS */
100
101 /*
102  * initializes log subentry
103  */
104 int
105 monitor_subsys_thread_init(
106         BackendDB               *be,
107         monitor_subsys_t        *ms )
108 {
109 #ifndef NO_THREADS
110         monitor_info_t  *mi;
111         monitor_entry_t *mp;
112         Entry           *e, **ep, *e_thread;
113         int             i;
114
115         ms->mss_update = monitor_subsys_thread_update;
116
117         mi = ( monitor_info_t * )be->be_private;
118
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 );
125         }
126
127         mp = ( monitor_entry_t * )e_thread->e_private;
128         mp->mp_children = NULL;
129         ep = &mp->mp_children;
130
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;
136
137                 /*
138                  * Max
139                  */
140                 e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn,
141                         &mt[ i ].rdn,
142                         mi->mi_oc_monitoredObject, 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 );
150                 }
151
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 );
155
156                 switch ( mt[ i ].param ) {
157                 case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
158                         break;
159
160                 case LDAP_PVT_THREAD_POOL_PARAM_STATE:
161                         if ( ldap_pvt_thread_pool_query( &connection_pool,
162                                 mt[ i ].param, (void *)&state ) == 0 )
163                         {
164                                 ber_str2bv( state, 0, 0, &bv );
165
166                         } else {
167                                 BER_BVSTR( &bv, "unknown" );
168                         }
169                         break;
170
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;
178                 }
179
180                 if ( !BER_BVISNULL( &bv ) ) {
181                         attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
182                 }
183
184                 if ( !BER_BVISNULL( &mt[ i ].desc ) ) {
185                         attr_merge_normalize_one( e,
186                                 slap_schema.si_ad_description,
187                                 &mt[ i ].desc, NULL );
188                 }
189         
190                 mp = monitor_entrypriv_create();
191                 if ( mp == NULL ) {
192                         return -1;
193                 }
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;
198
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 );
206                 }
207         
208                 *ep = e;
209                 ep = &mp->mp_next;
210         }
211
212         monitor_cache_release( mi, e_thread );
213
214 #endif /* ! NO_THREADS */
215         return( 0 );
216 }
217
218 #ifndef NO_THREADS
219 static int 
220 monitor_subsys_thread_update( 
221         Operation               *op,
222         SlapReply               *rs,
223         Entry                   *e )
224 {
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;
234
235         assert( mi != NULL );
236
237         dnRdn( &e->e_nname, &rdn );
238
239         for ( i = 0; !BER_BVISNULL( &mt[ i ].nrdn ); i++ ) {
240                 if ( dn_match( &mt[ i ].nrdn, &rdn ) ) {
241                         break;
242                 }
243         }
244
245         which = i;
246         if ( BER_BVISNULL( &mt[ which ].nrdn ) ) {
247                 return SLAP_CB_CONTINUE;
248         }
249
250         a = attr_find( e->e_attrs, mi->mi_ad_monitoredInfo );
251
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 );
259                                 }
260                                 ber_bvarray_free( a->a_vals );
261                                 a->a_vals = NULL;
262                                 a->a_nvals = NULL;
263                                 a->a_numvals = 0;
264                         }
265
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 );
274                                 }
275                                 i++;
276                         }
277                         ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
278         
279                         if ( vals ) {
280                                 attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL );
281                                 ber_bvarray_free( vals );
282
283                         } else {
284                                 attr_delete( &e->e_attrs, mi->mi_ad_monitoredInfo );
285                         }
286                         break;
287
288                 case MT_TASKLIST:
289                         if ( a != NULL ) {
290                                 if ( a->a_nvals != a->a_vals ) {
291                                         ber_bvarray_free( a->a_nvals );
292                                 }
293                                 ber_bvarray_free( a->a_vals );
294                                 a->a_vals = NULL;
295                                 a->a_nvals = NULL;
296                                 a->a_numvals = 0;
297                         }
298         
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 );
307                                 }
308                                 i++;
309                         }
310                         ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
311         
312                         if ( vals ) {
313                                 attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL );
314                                 ber_bvarray_free( vals );
315
316                         } else {
317                                 attr_delete( &e->e_attrs, mi->mi_ad_monitoredInfo );
318                         }
319                         break;
320
321                 default:
322                         assert( 0 );
323                 }
324                 break;
325
326         case LDAP_PVT_THREAD_POOL_PARAM_STATE:
327                 if ( a == NULL ) {
328                         return rs->sr_err = LDAP_OTHER;
329                 }
330                 if ( ldap_pvt_thread_pool_query( &connection_pool,
331                         mt[ i ].param, (void *)&state ) == 0 )
332                 {
333                         ber_str2bv( state, 0, 0, &bv );
334                         ber_bvreplace( &a->a_vals[ 0 ], &bv );
335                 }
336                 break;
337
338         default:
339                 if ( a == NULL ) {
340                         return rs->sr_err = LDAP_OTHER;
341                 }
342                 if ( ldap_pvt_thread_pool_query( &connection_pool,
343                         mt[ i ].param, (void *)&count ) == 0 )
344                 {
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 );
349                         }
350                 }
351                 break;
352         }
353
354         /* FIXME: touch modifyTimestamp? */
355
356         return SLAP_CB_CONTINUE;
357 }
358 #endif /* ! NO_THREADS */