Back to index

openldap  2.4.31
thread.c
Go to the documentation of this file.
00001 /* thread.c - deal with thread subsystem */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2001-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2001-2003 Pierangelo Masarati.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by Pierangelo Masarati for inclusion
00019  * in OpenLDAP Software.
00020  */
00021 
00022 #include "portable.h"
00023 
00024 #include <stdio.h>
00025 #include <ac/string.h>
00026 
00027 #include "slap.h"
00028 #include "back-monitor.h"
00029 
00030 #include <ldap_rq.h>
00031 
00032 #ifndef NO_THREADS
00033 typedef enum {
00034        MT_UNKNOWN,
00035        MT_RUNQUEUE,
00036        MT_TASKLIST,
00037 
00038        MT_LAST
00039 } monitor_thread_t;
00040 
00041 static struct {
00042        struct berval               rdn;
00043        struct berval               desc;
00044        struct berval               nrdn;
00045        ldap_pvt_thread_pool_param_t       param;
00046        monitor_thread_t            mt;
00047 }             mt[] = {
00048        { BER_BVC( "cn=Max" ),
00049               BER_BVC("Maximum number of threads as configured"),
00050               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_MAX,           MT_UNKNOWN },
00051        { BER_BVC( "cn=Max Pending" ),
00052               BER_BVC("Maximum number of pending threads"),
00053               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_MAX_PENDING,   MT_UNKNOWN },
00054        { BER_BVC( "cn=Open" ),            
00055               BER_BVC("Number of open threads"),
00056               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_OPEN,   MT_UNKNOWN },
00057        { BER_BVC( "cn=Starting" ), 
00058               BER_BVC("Number of threads being started"),
00059               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_STARTING,      MT_UNKNOWN },
00060        { BER_BVC( "cn=Active" ),   
00061               BER_BVC("Number of active threads"),
00062               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_ACTIVE, MT_UNKNOWN },
00063        { BER_BVC( "cn=Pending" ),  
00064               BER_BVC("Number of pending threads"),
00065               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_PENDING,       MT_UNKNOWN },
00066        { BER_BVC( "cn=Backload" ), 
00067               BER_BVC("Number of active plus pending threads"),
00068               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD,      MT_UNKNOWN },
00069 #if 0  /* not meaningful right now */
00070        { BER_BVC( "cn=Active Max" ),
00071               BER_BVNULL,
00072               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_ACTIVE_MAX,    MT_UNKNOWN },
00073        { BER_BVC( "cn=Pending Max" ),
00074               BER_BVNULL,
00075               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_PENDING_MAX,   MT_UNKNOWN },
00076        { BER_BVC( "cn=Backload Max" ),
00077               BER_BVNULL,
00078               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD_MAX,MT_UNKNOWN },
00079 #endif
00080        { BER_BVC( "cn=State" ),
00081               BER_BVC("Thread pool state"),
00082               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_STATE,  MT_UNKNOWN },
00083 
00084        { BER_BVC( "cn=Runqueue" ),
00085               BER_BVC("Queue of running threads - besides those handling operations"),
00086               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN,       MT_RUNQUEUE },
00087        { BER_BVC( "cn=Tasklist" ),
00088               BER_BVC("List of running plus standby threads - besides those handling operations"),
00089               BER_BVNULL,   LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN,       MT_TASKLIST },
00090 
00091        { BER_BVNULL }
00092 };
00093 
00094 static int 
00095 monitor_subsys_thread_update( 
00096        Operation            *op,
00097        SlapReply            *rs,
00098        Entry                *e );
00099 #endif /* ! NO_THREADS */
00100 
00101 /*
00102  * initializes log subentry
00103  */
00104 int
00105 monitor_subsys_thread_init(
00106        BackendDB            *be,
00107        monitor_subsys_t     *ms )
00108 {
00109 #ifndef NO_THREADS
00110        monitor_info_t       *mi;
00111        monitor_entry_t      *mp;
00112        Entry         *e, **ep, *e_thread;
00113        int           i;
00114 
00115        ms->mss_update = monitor_subsys_thread_update;
00116 
00117        mi = ( monitor_info_t * )be->be_private;
00118 
00119        if ( monitor_cache_get( mi, &ms->mss_ndn, &e_thread ) ) {
00120               Debug( LDAP_DEBUG_ANY,
00121                      "monitor_subsys_thread_init: unable to get entry \"%s\"\n",
00122                      ms->mss_dn.bv_val, 
00123                      0, 0 );
00124               return( -1 );
00125        }
00126 
00127        mp = ( monitor_entry_t * )e_thread->e_private;
00128        mp->mp_children = NULL;
00129        ep = &mp->mp_children;
00130 
00131        for ( i = 0; !BER_BVISNULL( &mt[ i ].rdn ); i++ ) {
00132               static char   buf[ BACKMONITOR_BUFSIZE ];
00133               int           count = -1;
00134               char          *state = NULL;
00135               struct berval bv = BER_BVNULL;
00136 
00137               /*
00138                * Max
00139                */
00140               e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn,
00141                      &mt[ i ].rdn,
00142                      mi->mi_oc_monitoredObject, mi, NULL, NULL );
00143               if ( e == NULL ) {
00144                      Debug( LDAP_DEBUG_ANY,
00145                             "monitor_subsys_thread_init: "
00146                             "unable to create entry \"%s,%s\"\n",
00147                             mt[ i ].rdn.bv_val,
00148                             ms->mss_ndn.bv_val, 0 );
00149                      return( -1 );
00150               }
00151 
00152               /* NOTE: reference to the normalized DN of the entry,
00153                * under the assumption it's not modified */
00154               dnRdn( &e->e_nname, &mt[ i ].nrdn );
00155 
00156               switch ( mt[ i ].param ) {
00157               case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
00158                      break;
00159 
00160               case LDAP_PVT_THREAD_POOL_PARAM_STATE:
00161                      if ( ldap_pvt_thread_pool_query( &connection_pool,
00162                             mt[ i ].param, (void *)&state ) == 0 )
00163                      {
00164                             ber_str2bv( state, 0, 0, &bv );
00165 
00166                      } else {
00167                             BER_BVSTR( &bv, "unknown" );
00168                      }
00169                      break;
00170 
00171               default:
00172                      /* NOTE: in case of error, it'll be set to -1 */
00173                      (void)ldap_pvt_thread_pool_query( &connection_pool,
00174                             mt[ i ].param, (void *)&count );
00175                      bv.bv_val = buf;
00176                      bv.bv_len = snprintf( buf, sizeof( buf ), "%d", count );
00177                      break;
00178               }
00179 
00180               if ( !BER_BVISNULL( &bv ) ) {
00181                      attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
00182               }
00183 
00184               if ( !BER_BVISNULL( &mt[ i ].desc ) ) {
00185                      attr_merge_normalize_one( e,
00186                             slap_schema.si_ad_description,
00187                             &mt[ i ].desc, NULL );
00188               }
00189        
00190               mp = monitor_entrypriv_create();
00191               if ( mp == NULL ) {
00192                      return -1;
00193               }
00194               e->e_private = ( void * )mp;
00195               mp->mp_info = ms;
00196               mp->mp_flags = ms->mss_flags \
00197                      | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
00198 
00199               if ( monitor_cache_add( mi, e ) ) {
00200                      Debug( LDAP_DEBUG_ANY,
00201                             "monitor_subsys_thread_init: "
00202                             "unable to add entry \"%s,%s\"\n",
00203                             mt[ i ].rdn.bv_val,
00204                             ms->mss_dn.bv_val, 0 );
00205                      return( -1 );
00206               }
00207        
00208               *ep = e;
00209               ep = &mp->mp_next;
00210        }
00211 
00212        monitor_cache_release( mi, e_thread );
00213 
00214 #endif /* ! NO_THREADS */
00215        return( 0 );
00216 }
00217 
00218 #ifndef NO_THREADS
00219 static int 
00220 monitor_subsys_thread_update( 
00221        Operation            *op,
00222        SlapReply            *rs,
00223        Entry                *e )
00224 {
00225        monitor_info_t       *mi = ( monitor_info_t * )op->o_bd->be_private;
00226        Attribute            *a;
00227        BerVarray            vals = NULL;
00228        char                 buf[ BACKMONITOR_BUFSIZE ];
00229        struct berval        rdn, bv;
00230        int                  which, i;
00231        struct re_s          *re;
00232        int                  count = -1;
00233        char                 *state = NULL;
00234 
00235        assert( mi != NULL );
00236 
00237        dnRdn( &e->e_nname, &rdn );
00238 
00239        for ( i = 0; !BER_BVISNULL( &mt[ i ].nrdn ); i++ ) {
00240               if ( dn_match( &mt[ i ].nrdn, &rdn ) ) {
00241                      break;
00242               }
00243        }
00244 
00245        which = i;
00246        if ( BER_BVISNULL( &mt[ which ].nrdn ) ) {
00247               return SLAP_CB_CONTINUE;
00248        }
00249 
00250        a = attr_find( e->e_attrs, mi->mi_ad_monitoredInfo );
00251 
00252        switch ( mt[ which ].param ) {
00253        case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
00254               switch ( mt[ which ].mt ) {
00255               case MT_RUNQUEUE:
00256                      if ( a != NULL ) {
00257                             if ( a->a_nvals != a->a_vals ) {
00258                                    ber_bvarray_free( a->a_nvals );
00259                             }
00260                             ber_bvarray_free( a->a_vals );
00261                             a->a_vals = NULL;
00262                             a->a_nvals = NULL;
00263                             a->a_numvals = 0;
00264                      }
00265 
00266                      i = 0;
00267                      bv.bv_val = buf;
00268                      ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
00269                      LDAP_STAILQ_FOREACH( re, &slapd_rq.run_list, rnext ) {
00270                             bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)",
00271                                    i, re->tname, re->tspec );
00272                             if ( bv.bv_len < sizeof( buf ) ) {
00273                                    value_add_one( &vals, &bv );
00274                             }
00275                             i++;
00276                      }
00277                      ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
00278        
00279                      if ( vals ) {
00280                             attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL );
00281                             ber_bvarray_free( vals );
00282 
00283                      } else {
00284                             attr_delete( &e->e_attrs, mi->mi_ad_monitoredInfo );
00285                      }
00286                      break;
00287 
00288               case MT_TASKLIST:
00289                      if ( a != NULL ) {
00290                             if ( a->a_nvals != a->a_vals ) {
00291                                    ber_bvarray_free( a->a_nvals );
00292                             }
00293                             ber_bvarray_free( a->a_vals );
00294                             a->a_vals = NULL;
00295                             a->a_nvals = NULL;
00296                             a->a_numvals = 0;
00297                      }
00298        
00299                      i = 0;
00300                      bv.bv_val = buf;
00301                      ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
00302                      LDAP_STAILQ_FOREACH( re, &slapd_rq.task_list, tnext ) {
00303                             bv.bv_len = snprintf( buf, sizeof( buf ), "{%d}%s(%s)",
00304                                    i, re->tname, re->tspec );
00305                             if ( bv.bv_len < sizeof( buf ) ) {
00306                                    value_add_one( &vals, &bv );
00307                             }
00308                             i++;
00309                      }
00310                      ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
00311        
00312                      if ( vals ) {
00313                             attr_merge_normalize( e, mi->mi_ad_monitoredInfo, vals, NULL );
00314                             ber_bvarray_free( vals );
00315 
00316                      } else {
00317                             attr_delete( &e->e_attrs, mi->mi_ad_monitoredInfo );
00318                      }
00319                      break;
00320 
00321               default:
00322                      assert( 0 );
00323               }
00324               break;
00325 
00326        case LDAP_PVT_THREAD_POOL_PARAM_STATE:
00327               if ( a == NULL ) {
00328                      return rs->sr_err = LDAP_OTHER;
00329               }
00330               if ( ldap_pvt_thread_pool_query( &connection_pool,
00331                      mt[ i ].param, (void *)&state ) == 0 )
00332               {
00333                      ber_str2bv( state, 0, 0, &bv );
00334                      ber_bvreplace( &a->a_vals[ 0 ], &bv );
00335               }
00336               break;
00337 
00338        default:
00339               if ( a == NULL ) {
00340                      return rs->sr_err = LDAP_OTHER;
00341               }
00342               if ( ldap_pvt_thread_pool_query( &connection_pool,
00343                      mt[ i ].param, (void *)&count ) == 0 )
00344               {
00345                      bv.bv_val = buf;
00346                      bv.bv_len = snprintf( buf, sizeof( buf ), "%d", count );
00347                      if ( bv.bv_len < sizeof( buf ) ) {
00348                             ber_bvreplace( &a->a_vals[ 0 ], &bv );
00349                      }
00350               }
00351               break;
00352        }
00353 
00354        /* FIXME: touch modifyTimestamp? */
00355 
00356        return SLAP_CB_CONTINUE;
00357 }
00358 #endif /* ! NO_THREADS */