]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/thread.c
a7dbb5920a62344667c52d5a3d92879ab3a5ad39
[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                         ldap_pvt_thread_pool_query( &connection_pool,
133                                 mt[ i ].param, (void *)&state );
134                         ber_str2bv( state, 0, 0, &bv );
135                         break;
136
137                 default:
138                         ldap_pvt_thread_pool_query( &connection_pool,
139                                 mt[ i ].param, (void *)&count );
140                         bv.bv_val = buf;
141                         bv.bv_len = snprintf( buf, sizeof( buf ), "%d", count );
142                         break;
143                 }
144
145                 if ( !BER_BVISNULL( &bv ) ) {
146                         attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
147                 }
148         
149                 mp = monitor_entrypriv_create();
150                 if ( mp == NULL ) {
151                         return -1;
152                 }
153                 e->e_private = ( void * )mp;
154                 mp->mp_info = ms;
155                 mp->mp_flags = ms->mss_flags \
156                         | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
157
158                 if ( monitor_cache_add( mi, e ) ) {
159                         Debug( LDAP_DEBUG_ANY,
160                                 "monitor_subsys_thread_init: "
161                                 "unable to add entry \"%s,%s\"\n",
162                                 mt[ i ].rdn.bv_val,
163                                 ms->mss_ndn.bv_val, 0 );
164                         return( -1 );
165                 }
166         
167                 *ep = e;
168                 ep = &mp->mp_next;
169         }
170
171         monitor_cache_release( mi, e_thread );
172
173         return( 0 );
174 }
175
176 static int 
177 monitor_subsys_thread_update( 
178         Operation               *op,
179         SlapReply               *rs,
180         Entry                   *e )
181 {
182         monitor_info_t  *mi = ( monitor_info_t * )op->o_bd->be_private;
183         Attribute               *a;
184         BerVarray               vals = NULL;
185         char                    buf[ BACKMONITOR_BUFSIZE ];
186         struct berval           rdn, bv;
187         int                     which, i;
188         struct re_s             *re;
189         int                     count = -1;
190         char                    *state = NULL;
191
192         assert( mi != NULL );
193
194         dnRdn( &e->e_nname, &rdn );
195
196         for ( i = 0; !BER_BVISNULL( &mt[ i ].nrdn ); i++ ) {
197                 if ( dn_match( &mt[ i ].nrdn, &rdn ) ) {
198                         which = i;
199                         break;
200                 }
201         }
202
203         if ( BER_BVISNULL( &mt[ which ].nrdn ) ) {
204                 return SLAP_CB_CONTINUE;
205         }
206
207         a = attr_find( e->e_attrs, mi->mi_ad_monitoredInfo );
208
209         switch ( mt[ which ].param ) {
210         case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
211                 switch ( mt[ which ].mt ) {
212                 case MT_RUNQUEUE:
213                         if ( a != NULL ) {
214                                 if ( a->a_nvals != a->a_vals ) {
215                                         ber_bvarray_free( a->a_nvals );
216                                 }
217                                 ber_bvarray_free( a->a_vals );
218                                 a->a_vals = NULL;
219                                 a->a_nvals = NULL;
220                         }
221
222                         i = 0;
223                         bv.bv_val = buf;
224                         ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
225                         LDAP_STAILQ_FOREACH( re, &slapd_rq.run_list, rnext ) {
226                                 bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)",
227                                         i, re->tname, re->tspec );
228                                 if ( bv.bv_len < sizeof( buf ) ) {
229                                         value_add_one( &vals, &bv );
230                                 }
231                                 i++;
232                         }
233                         ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
234         
235                         if ( vals ) {
236                                 attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL );
237                                 ber_bvarray_free( vals );
238                         }
239                         break;
240
241                 case MT_TASKLIST:
242                         if ( a != NULL ) {
243                                 if ( a->a_nvals != a->a_vals ) {
244                                         ber_bvarray_free( a->a_nvals );
245                                 }
246                                 ber_bvarray_free( a->a_vals );
247                                 a->a_vals = NULL;
248                                 a->a_nvals = NULL;
249                         }
250         
251                         i = 0;
252                         bv.bv_val = buf;
253                         ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
254                         LDAP_STAILQ_FOREACH( re, &slapd_rq.task_list, tnext ) {
255                                 bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)",
256                                         i, re->tname, re->tspec );
257                                 if ( bv.bv_len < sizeof( buf ) ) {
258                                         value_add_one( &vals, &bv );
259                                 }
260                                 i++;
261                         }
262                         ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
263         
264                         if ( vals ) {
265                                 attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL );
266                                 ber_bvarray_free( vals );
267                         }
268                         break;
269
270                 default:
271                         assert( 0 );
272                 }
273                 break;
274
275         case LDAP_PVT_THREAD_POOL_PARAM_STATE:
276                 if ( a == NULL ) {
277                         return rs->sr_err = LDAP_OTHER;
278                 }
279                 ldap_pvt_thread_pool_query( &connection_pool,
280                         mt[ i ].param, (void *)&state );
281                 ber_str2bv( state, 0, 0, &bv );
282                 ber_bvreplace( &a->a_vals[ 0 ], &bv );
283                 break;
284
285         default:
286                 if ( a == NULL ) {
287                         return rs->sr_err = LDAP_OTHER;
288                 }
289                 ldap_pvt_thread_pool_query( &connection_pool,
290                         mt[ i ].param, (void *)&count );
291                 bv.bv_val = buf;
292                 bv.bv_len = snprintf( buf, sizeof( buf ), "%d", count );
293                 if ( bv.bv_len >= sizeof( buf ) ) {
294                         /* FIXME? */
295                         break;
296                 }
297                 ber_bvreplace( &a->a_vals[ 0 ], &bv );
298                 break;
299         }
300
301         /* FIXME: touch modifyTimestamp? */
302
303         return SLAP_CB_CONTINUE;
304 }
305