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