]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/thread.c
add tasklist monitoring; review runqueue monitoring
[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-2006 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 static int 
33 monitor_subsys_thread_update( 
34         Operation               *op,
35         SlapReply               *rs,
36         Entry                   *e );
37
38 /*
39  * initializes log subentry
40  */
41 int
42 monitor_subsys_thread_init(
43         BackendDB               *be,
44         monitor_subsys_t        *ms
45 )
46 {
47         monitor_info_t  *mi;
48         monitor_entry_t *mp;
49         Entry           *e, **ep, *e_thread;
50         static char     buf[ BACKMONITOR_BUFSIZE ];
51         struct berval bv;
52
53         ms->mss_update = monitor_subsys_thread_update;
54
55         mi = ( monitor_info_t * )be->be_private;
56
57         if ( monitor_cache_get( mi, &ms->mss_ndn, &e_thread ) ) {
58                 Debug( LDAP_DEBUG_ANY,
59                         "monitor_subsys_thread_init: unable to get entry \"%s\"\n",
60                         ms->mss_ndn.bv_val, 
61                         0, 0 );
62                 return( -1 );
63         }
64
65         mp = ( monitor_entry_t * )e_thread->e_private;
66         mp->mp_children = NULL;
67         ep = &mp->mp_children;
68
69         /*
70          * Max
71          */
72         BER_BVSTR( &bv, "cn=Max" );
73         e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
74                 mi->mi_oc_monitoredObject, mi, NULL, NULL );
75         if ( e == NULL ) {
76                 Debug( LDAP_DEBUG_ANY,
77                         "monitor_subsys_thread_init: "
78                         "unable to create entry \"cn=Max,%s\"\n",
79                         ms->mss_ndn.bv_val, 0, 0 );
80                 return( -1 );
81         }
82         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", connection_pool_max );
83         bv.bv_val = buf;
84         attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
85         
86         mp = monitor_entrypriv_create();
87         if ( mp == NULL ) {
88                 return -1;
89         }
90         e->e_private = ( void * )mp;
91         mp->mp_info = ms;
92         mp->mp_flags = ms->mss_flags \
93                 | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
94
95         if ( monitor_cache_add( mi, e ) ) {
96                 Debug( LDAP_DEBUG_ANY,
97                         "monitor_subsys_thread_init: "
98                         "unable to add entry \"cn=Max,%s\"\n",
99                         ms->mss_ndn.bv_val, 0, 0 );
100                 return( -1 );
101         }
102         
103         *ep = e;
104         ep = &mp->mp_next;
105
106         /*
107          * Backload
108          */
109         BER_BVSTR( &bv, "cn=Backload" );
110         e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
111                 mi->mi_oc_monitoredObject, mi, NULL, NULL );
112         if ( e == NULL ) {
113                 Debug( LDAP_DEBUG_ANY,
114                         "monitor_subsys_thread_init: "
115                         "unable to create entry \"cn=Backload,%s\"\n",
116                         ms->mss_ndn.bv_val, 0, 0 );
117                 return( -1 );
118         }
119         BER_BVSTR( &bv, "0" );
120         attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
121
122         mp = monitor_entrypriv_create();
123         if ( mp == NULL ) {
124                 return -1;
125         }
126         e->e_private = ( void * )mp;
127         mp->mp_info = ms;
128         mp->mp_flags = ms->mss_flags \
129                 | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
130
131         if ( monitor_cache_add( mi, e ) ) {
132                 Debug( LDAP_DEBUG_ANY,
133                         "monitor_subsys_thread_init: "
134                         "unable to add entry \"cn=Backload,%s\"\n",
135                         ms->mss_ndn.bv_val, 0, 0 );
136                 return( -1 );
137         }
138         
139         *ep = e;
140         ep = &mp->mp_next;
141
142         /*
143          * Runqueue runners
144          */
145         BER_BVSTR( &bv, "cn=Runqueue" );
146         e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
147                 mi->mi_oc_monitoredObject, mi, NULL, NULL );
148         if ( e == NULL ) {
149                 Debug( LDAP_DEBUG_ANY,
150                         "monitor_subsys_thread_init: "
151                         "unable to create entry \"cn=Runqueue,%s\"\n",
152                         ms->mss_ndn.bv_val, 0, 0 );
153                 return( -1 );
154         }
155         BER_BVSTR( &bv, "0" );
156         attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
157
158         mp = monitor_entrypriv_create();
159         if ( mp == NULL ) {
160                 return -1;
161         }
162         e->e_private = ( void * )mp;
163         mp->mp_info = ms;
164         mp->mp_flags = ms->mss_flags \
165                 | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
166
167         if ( monitor_cache_add( mi, e ) ) {
168                 Debug( LDAP_DEBUG_ANY,
169                         "monitor_subsys_thread_init: "
170                         "unable to add entry \"cn=Runqueue,%s\"\n",
171                         ms->mss_ndn.bv_val, 0, 0 );
172                 return( -1 );
173         }
174         
175         *ep = e;
176         ep = &mp->mp_next;
177
178         /*
179          * Tasklist
180          */
181         BER_BVSTR( &bv, "cn=Tasklist" );
182         e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
183                 mi->mi_oc_monitoredObject, mi, NULL, NULL );
184         if ( e == NULL ) {
185                 Debug( LDAP_DEBUG_ANY,
186                         "monitor_subsys_thread_init: "
187                         "unable to create entry \"%s,%s\"\n",
188                         bv.bv_val, ms->mss_ndn.bv_val, 0 );
189                 return( -1 );
190         }
191         BER_BVSTR( &bv, "0" );
192         attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
193
194         mp = monitor_entrypriv_create();
195         if ( mp == NULL ) {
196                 return -1;
197         }
198         e->e_private = ( void * )mp;
199         mp->mp_info = ms;
200         mp->mp_flags = ms->mss_flags \
201                 | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
202
203         if ( monitor_cache_add( mi, e ) ) {
204                 Debug( LDAP_DEBUG_ANY,
205                         "monitor_subsys_thread_init: "
206                         "unable to add entry \"%s\"\n",
207                         e->e_name.bv_val, 0, 0 );
208                 return( -1 );
209         }
210         
211         *ep = e;
212         ep = &mp->mp_next;
213
214         monitor_cache_release( mi, e_thread );
215
216         return( 0 );
217 }
218
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         char                    buf[ BACKMONITOR_BUFSIZE ];
228         enum {
229                 MT_UNKNOWN,
230                 MT_BACKLOAD,
231                 MT_RUNQUEUE,
232                 MT_TASKLIST,
233                 MT_MAX                          /* unused */
234         };
235         static slap_verbmasks   mt[] = {
236                 { BER_BVC( "cn=backload" ),     MT_BACKLOAD     },
237                 { BER_BVC( "cn=runqueue" ),     MT_RUNQUEUE     },
238                 { BER_BVC( "cn=tasklist" ),     MT_TASKLIST     },
239                 { BER_BVC( "cn=max" ),          MT_UNKNOWN      },
240                 { BER_BVNULL,                   MT_UNKNOWN      }
241         };
242         struct berval           rdn, bv;
243         ber_len_t               len;
244         int                     which, i;
245         struct re_s             *re;
246
247         assert( mi != NULL );
248
249         dnRdn( &e->e_nname, &rdn );
250
251         which = bverb_to_mask( &rdn, mt );
252         if ( BER_BVISNULL( &mt[ which ].word )
253                 || mt[ which ].mask == MT_UNKNOWN )
254         {
255                 return SLAP_CB_CONTINUE;
256         }
257
258         a = attr_find( e->e_attrs, mi->mi_ad_monitoredInfo );
259         if ( a == NULL ) {
260                 return rs->sr_err = LDAP_OTHER;
261         }
262
263         switch ( mt[ which ].mask ) {
264         case MT_BACKLOAD:
265                 snprintf( buf, sizeof( buf ), "%d", 
266                         ldap_pvt_thread_pool_backload( &connection_pool ) );
267                 len = strlen( buf );
268                 if ( len > a->a_vals[ 0 ].bv_len ) {
269                         a->a_vals[ 0 ].bv_val = ber_memrealloc( a->a_vals[ 0 ].bv_val, len + 1 );
270                 }
271                 a->a_vals[ 0 ].bv_len = len;
272                 AC_MEMCPY( a->a_vals[ 0 ].bv_val, buf, len + 1 );
273                 break;
274
275         case MT_RUNQUEUE:
276                 for ( i = 0; !BER_BVISNULL( &a->a_vals[ i ] ); i++ ) {
277                         ch_free( a->a_vals[ i ].bv_val );
278                         BER_BVZERO( &a->a_vals[ i ] );
279                 }
280                 if ( a->a_nvals != a->a_vals ) {
281                         ber_bvarray_free( a->a_nvals );
282                 }
283                 a->a_nvals = NULL;
284                 bv.bv_val = buf;
285                 ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
286                 i = 0;
287                 LDAP_STAILQ_FOREACH( re, &slapd_rq.run_list, rnext ) {
288                         bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)",
289                                 i, re->tname, re->tspec );
290                         if ( bv.bv_len < sizeof( buf ) ) {
291                                 value_add_one( &a->a_vals, &bv );
292                         }
293                         i++;
294                 }
295                 ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
296
297                 /* don't leave 'round attributes with no values */
298                 if ( BER_BVISNULL( &a->a_vals[ 0 ] ) ) {
299                         BER_BVSTR( &bv, "{0}()" );
300                         value_add_one( &a->a_vals, &bv );
301                 }
302                 a->a_nvals = a->a_vals;
303                 break;
304
305         case MT_TASKLIST:
306                 for ( i = 0; !BER_BVISNULL( &a->a_vals[ i ] ); i++ ) {
307                         ch_free( a->a_vals[ i ].bv_val );
308                         BER_BVZERO( &a->a_vals[ i ] );
309                 }
310                 if ( a->a_nvals != a->a_vals ) {
311                         ber_bvarray_free( a->a_nvals );
312                 }
313                 a->a_nvals = NULL;
314                 bv.bv_val = buf;
315                 ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
316                 i = 0;
317                 LDAP_STAILQ_FOREACH( re, &slapd_rq.task_list, rnext ) {
318                         bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)",
319                                 i, re->tname, re->tspec );
320                         if ( bv.bv_len < sizeof( buf ) ) {
321                                 value_add_one( &a->a_vals, &bv );
322                         }
323                         i++;
324                 }
325                 ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
326
327                 /* don't leave 'round attributes with no values */
328                 if ( BER_BVISNULL( &a->a_vals[ 0 ] ) ) {
329                         BER_BVSTR( &bv, "{0}()" );
330                         value_add_one( &a->a_vals, &bv );
331                 }
332                 a->a_nvals = a->a_vals;
333                 break;
334         }
335
336         /* FIXME: touch modifyTimestamp? */
337
338         return SLAP_CB_CONTINUE;
339 }
340