Back to index

openldap  2.4.31
monitor.c
Go to the documentation of this file.
00001 /* monitor.c - monitor bdb backend */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2000-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 #include <ac/string.h>
00021 #include <ac/unistd.h>
00022 #include <ac/stdlib.h>
00023 #include <ac/errno.h>
00024 #include <sys/stat.h>
00025 #include "lutil.h"
00026 #include "back-bdb.h"
00027 
00028 #include "../back-monitor/back-monitor.h"
00029 
00030 #include "config.h"
00031 
00032 static ObjectClass          *oc_olmBDBDatabase;
00033 
00034 static AttributeDescription *ad_olmBDBEntryCache,
00035        *ad_olmBDBDNCache, *ad_olmBDBIDLCache,
00036        *ad_olmDbDirectory;
00037 
00038 #ifdef BDB_MONITOR_IDX
00039 static int
00040 bdb_monitor_idx_entry_add(
00041        struct bdb_info      *bdb,
00042        Entry         *e );
00043 
00044 static AttributeDescription *ad_olmDbNotIndexed;
00045 #endif /* BDB_MONITOR_IDX */
00046 
00047 /*
00048  * NOTE: there's some confusion in monitor OID arc;
00049  * by now, let's consider:
00050  * 
00051  * Subsystems monitor attributes   1.3.6.1.4.1.4203.666.1.55.0
00052  * Databases monitor attributes           1.3.6.1.4.1.4203.666.1.55.0.1
00053  * BDB database monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1.1
00054  *
00055  * Subsystems monitor objectclasses       1.3.6.1.4.1.4203.666.3.16.0
00056  * Databases monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1
00057  * BDB database monitor objectclasses     1.3.6.1.4.1.4203.666.3.16.0.1.1
00058  */
00059 
00060 static struct {
00061        char                 *name;
00062        char                 *oid;
00063 }             s_oid[] = {
00064        { "olmBDBAttributes",                     "olmDatabaseAttributes:1" },
00065        { "olmBDBObjectClasses",           "olmDatabaseObjectClasses:1" },
00066 
00067        { NULL }
00068 };
00069 
00070 static struct {
00071        char                 *desc;
00072        AttributeDescription **ad;
00073 }             s_at[] = {
00074        { "( olmBDBAttributes:1 "
00075               "NAME ( 'olmBDBEntryCache' ) "
00076               "DESC 'Number of items in Entry Cache' "
00077               "SUP monitorCounter "
00078               "NO-USER-MODIFICATION "
00079               "USAGE dSAOperation )",
00080               &ad_olmBDBEntryCache },
00081 
00082        { "( olmBDBAttributes:2 "
00083               "NAME ( 'olmBDBDNCache' ) "
00084               "DESC 'Number of items in DN Cache' "
00085               "SUP monitorCounter "
00086               "NO-USER-MODIFICATION "
00087               "USAGE dSAOperation )",
00088               &ad_olmBDBDNCache },
00089 
00090        { "( olmBDBAttributes:3 "
00091               "NAME ( 'olmBDBIDLCache' ) "
00092               "DESC 'Number of items in IDL Cache' "
00093               "SUP monitorCounter "
00094               "NO-USER-MODIFICATION "
00095               "USAGE dSAOperation )",
00096               &ad_olmBDBIDLCache },
00097 
00098        { "( olmDatabaseAttributes:1 "
00099               "NAME ( 'olmDbDirectory' ) "
00100               "DESC 'Path name of the directory "
00101                      "where the database environment resides' "
00102               "SUP monitoredInfo "
00103               "NO-USER-MODIFICATION "
00104               "USAGE dSAOperation )",
00105               &ad_olmDbDirectory },
00106 
00107 #ifdef BDB_MONITOR_IDX
00108        { "( olmDatabaseAttributes:2 "
00109               "NAME ( 'olmDbNotIndexed' ) "
00110               "DESC 'Missing indexes resulting from candidate selection' "
00111               "SUP monitoredInfo "
00112               "NO-USER-MODIFICATION "
00113               "USAGE dSAOperation )",
00114               &ad_olmDbNotIndexed },
00115 #endif /* BDB_MONITOR_IDX */
00116 
00117        { NULL }
00118 };
00119 
00120 static struct {
00121        char          *desc;
00122        ObjectClass   **oc;
00123 }             s_oc[] = {
00124        /* augments an existing object, so it must be AUXILIARY
00125         * FIXME: derive from some ABSTRACT "monitoredEntity"? */
00126        { "( olmBDBObjectClasses:1 "
00127               "NAME ( 'olmBDBDatabase' ) "
00128               "SUP top AUXILIARY "
00129               "MAY ( "
00130                      "olmBDBEntryCache "
00131                      "$ olmBDBDNCache "
00132                      "$ olmBDBIDLCache "
00133                      "$ olmDbDirectory "
00134 #ifdef BDB_MONITOR_IDX
00135                      "$ olmDbNotIndexed "
00136 #endif /* BDB_MONITOR_IDX */
00137                      ") )",
00138               &oc_olmBDBDatabase },
00139 
00140        { NULL }
00141 };
00142 
00143 static int
00144 bdb_monitor_update(
00145        Operation     *op,
00146        SlapReply     *rs,
00147        Entry         *e,
00148        void          *priv )
00149 {
00150        struct bdb_info             *bdb = (struct bdb_info *) priv;
00151        Attribute            *a;
00152 
00153        char                 buf[ BUFSIZ ];
00154        struct berval        bv;
00155 
00156        assert( ad_olmBDBEntryCache != NULL );
00157 
00158        a = attr_find( e->e_attrs, ad_olmBDBEntryCache );
00159        assert( a != NULL );
00160        bv.bv_val = buf;
00161        bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_cursize );
00162        ber_bvreplace( &a->a_vals[ 0 ], &bv );
00163 
00164        a = attr_find( e->e_attrs, ad_olmBDBDNCache );
00165        assert( a != NULL );
00166        bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_cache.c_eiused );
00167        ber_bvreplace( &a->a_vals[ 0 ], &bv );
00168 
00169        a = attr_find( e->e_attrs, ad_olmBDBIDLCache );
00170        assert( a != NULL );
00171        bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", bdb->bi_idl_cache_size );
00172        ber_bvreplace( &a->a_vals[ 0 ], &bv );
00173        
00174 #ifdef BDB_MONITOR_IDX
00175        bdb_monitor_idx_entry_add( bdb, e );
00176 #endif /* BDB_MONITOR_IDX */
00177 
00178        return SLAP_CB_CONTINUE;
00179 }
00180 
00181 #if 0  /* uncomment if required */
00182 static int
00183 bdb_monitor_modify(
00184        Operation     *op,
00185        SlapReply     *rs,
00186        Entry         *e,
00187        void          *priv )
00188 {
00189        return SLAP_CB_CONTINUE;
00190 }
00191 #endif
00192 
00193 static int
00194 bdb_monitor_free(
00195        Entry         *e,
00196        void          **priv )
00197 {
00198        struct berval values[ 2 ];
00199        Modification  mod = { 0 };
00200 
00201        const char    *text;
00202        char          textbuf[ SLAP_TEXT_BUFLEN ];
00203 
00204        int           i, rc;
00205 
00206        /* NOTE: if slap_shutdown != 0, priv might have already been freed */
00207        *priv = NULL;
00208 
00209        /* Remove objectClass */
00210        mod.sm_op = LDAP_MOD_DELETE;
00211        mod.sm_desc = slap_schema.si_ad_objectClass;
00212        mod.sm_values = values;
00213        mod.sm_numvals = 1;
00214        values[ 0 ] = oc_olmBDBDatabase->soc_cname;
00215        BER_BVZERO( &values[ 1 ] );
00216 
00217        rc = modify_delete_values( e, &mod, 1, &text,
00218               textbuf, sizeof( textbuf ) );
00219        /* don't care too much about return code... */
00220 
00221        /* remove attrs */
00222        mod.sm_values = NULL;
00223        mod.sm_numvals = 0;
00224        for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
00225               mod.sm_desc = *s_at[ i ].ad;
00226               rc = modify_delete_values( e, &mod, 1, &text,
00227                      textbuf, sizeof( textbuf ) );
00228               /* don't care too much about return code... */
00229        }
00230        
00231        return SLAP_CB_CONTINUE;
00232 }
00233 
00234 #define       bdb_monitor_initialize      BDB_SYMBOL(monitor_initialize)
00235 
00236 /*
00237  * call from within bdb_initialize()
00238  */
00239 static int
00240 bdb_monitor_initialize( void )
00241 {
00242        int           i, code;
00243        ConfigArgs c;
00244        char   *argv[ 3 ];
00245 
00246        static int    bdb_monitor_initialized = 0;
00247 
00248        /* set to 0 when successfully initialized; otherwise, remember failure */
00249        static int    bdb_monitor_initialized_failure = 1;
00250 
00251        if ( bdb_monitor_initialized++ ) {
00252               return bdb_monitor_initialized_failure;
00253        }
00254 
00255        if ( backend_info( "monitor" ) == NULL ) {
00256               return -1;
00257        }
00258 
00259        /* register schema here */
00260 
00261        argv[ 0 ] = "back-bdb/back-hdb monitor";
00262        c.argv = argv;
00263        c.argc = 3;
00264        c.fname = argv[0];
00265 
00266        for ( i = 0; s_oid[ i ].name; i++ ) {
00267               c.lineno = i;
00268               argv[ 1 ] = s_oid[ i ].name;
00269               argv[ 2 ] = s_oid[ i ].oid;
00270 
00271               if ( parse_oidm( &c, 0, NULL ) != 0 ) {
00272                      Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
00273                             ": unable to add "
00274                             "objectIdentifier \"%s=%s\"\n",
00275                             s_oid[ i ].name, s_oid[ i ].oid, 0 );
00276                      return 2;
00277               }
00278        }
00279 
00280        for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
00281               code = register_at( s_at[ i ].desc, s_at[ i ].ad, 1 );
00282               if ( code != LDAP_SUCCESS ) {
00283                      Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
00284                             ": register_at failed for attributeType (%s)\n",
00285                             s_at[ i ].desc, 0, 0 );
00286                      return 3;
00287 
00288               } else {
00289                      (*s_at[ i ].ad)->ad_type->sat_flags |= SLAP_AT_HIDE;
00290               }
00291        }
00292 
00293        for ( i = 0; s_oc[ i ].desc != NULL; i++ ) {
00294               code = register_oc( s_oc[ i ].desc, s_oc[ i ].oc, 1 );
00295               if ( code != LDAP_SUCCESS ) {
00296                      Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_initialize)
00297                             ": register_oc failed for objectClass (%s)\n",
00298                             s_oc[ i ].desc, 0, 0 );
00299                      return 4;
00300 
00301               } else {
00302                      (*s_oc[ i ].oc)->soc_flags |= SLAP_OC_HIDE;
00303               }
00304        }
00305 
00306        return ( bdb_monitor_initialized_failure = LDAP_SUCCESS );
00307 }
00308 
00309 /*
00310  * call from within bdb_db_init()
00311  */
00312 int
00313 bdb_monitor_db_init( BackendDB *be )
00314 {
00315        struct bdb_info             *bdb = (struct bdb_info *) be->be_private;
00316 
00317        if ( bdb_monitor_initialize() == LDAP_SUCCESS ) {
00318               /* monitoring in back-bdb is on by default */
00319               SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_MONITORING;
00320        }
00321 
00322 #ifdef BDB_MONITOR_IDX
00323        bdb->bi_idx = NULL;
00324        ldap_pvt_thread_mutex_init( &bdb->bi_idx_mutex );
00325 #endif /* BDB_MONITOR_IDX */
00326 
00327        return 0;
00328 }
00329 
00330 /*
00331  * call from within bdb_db_open()
00332  */
00333 int
00334 bdb_monitor_db_open( BackendDB *be )
00335 {
00336        struct bdb_info             *bdb = (struct bdb_info *) be->be_private;
00337        Attribute            *a, *next;
00338        monitor_callback_t   *cb = NULL;
00339        int                  rc = 0;
00340        BackendInfo          *mi;
00341        monitor_extra_t             *mbe;
00342        struct berval dummy = BER_BVC("");
00343 
00344        if ( !SLAP_DBMONITORING( be ) ) {
00345               return 0;
00346        }
00347 
00348        mi = backend_info( "monitor" );
00349        if ( !mi || !mi->bi_extra ) {
00350               SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
00351               return 0;
00352        }
00353        mbe = mi->bi_extra;
00354 
00355        /* don't bother if monitor is not configured */
00356        if ( !mbe->is_configured() ) {
00357               static int warning = 0;
00358 
00359               if ( warning++ == 0 ) {
00360                      Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_db_open)
00361                             ": monitoring disabled; "
00362                             "configure monitor database to enable\n",
00363                             0, 0, 0 );
00364               }
00365 
00366               return 0;
00367        }
00368 
00369        /* alloc as many as required (plus 1 for objectClass) */
00370        a = attrs_alloc( 1 + 4 );
00371        if ( a == NULL ) {
00372               rc = 1;
00373               goto cleanup;
00374        }
00375 
00376        a->a_desc = slap_schema.si_ad_objectClass;
00377        attr_valadd( a, &oc_olmBDBDatabase->soc_cname, NULL, 1 );
00378        next = a->a_next;
00379 
00380        {
00381               struct berval bv = BER_BVC( "0" );
00382 
00383               next->a_desc = ad_olmBDBEntryCache;
00384               attr_valadd( next, &bv, NULL, 1 );
00385               next = next->a_next;
00386 
00387               next->a_desc = ad_olmBDBDNCache;
00388               attr_valadd( next, &bv, NULL, 1 );
00389               next = next->a_next;
00390 
00391               next->a_desc = ad_olmBDBIDLCache;
00392               attr_valadd( next, &bv, NULL, 1 );
00393               next = next->a_next;
00394        }
00395 
00396        {
00397               struct berval bv, nbv;
00398               ber_len_t     pathlen = 0, len = 0;
00399               char          path[ MAXPATHLEN ] = { '\0' };
00400               char          *fname = bdb->bi_dbenv_home,
00401                             *ptr;
00402 
00403               len = strlen( fname );
00404               if ( fname[ 0 ] != '/' ) {
00405                      /* get full path name */
00406                      getcwd( path, sizeof( path ) );
00407                      pathlen = strlen( path );
00408 
00409                      if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
00410                             fname += 2;
00411                             len -= 2;
00412                      }
00413               }
00414 
00415               bv.bv_len = pathlen + STRLENOF( "/" ) + len;
00416               ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
00417               if ( pathlen ) {
00418                      ptr = lutil_strncopy( ptr, path, pathlen );
00419                      ptr[ 0 ] = '/';
00420                      ptr++;
00421               }
00422               ptr = lutil_strncopy( ptr, fname, len );
00423               if ( ptr[ -1 ] != '/' ) {
00424                      ptr[ 0 ] = '/';
00425                      ptr++;
00426               }
00427               ptr[ 0 ] = '\0';
00428               
00429               attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );
00430 
00431               next->a_desc = ad_olmDbDirectory;
00432               next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
00433               next->a_vals[ 0 ] = bv;
00434               next->a_numvals = 1;
00435 
00436               if ( BER_BVISNULL( &nbv ) ) {
00437                      next->a_nvals = next->a_vals;
00438 
00439               } else {
00440                      next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
00441                      next->a_nvals[ 0 ] = nbv;
00442               }
00443 
00444               next = next->a_next;
00445        }
00446 
00447        cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
00448        cb->mc_update = bdb_monitor_update;
00449 #if 0  /* uncomment if required */
00450        cb->mc_modify = bdb_monitor_modify;
00451 #endif
00452        cb->mc_free = bdb_monitor_free;
00453        cb->mc_private = (void *)bdb;
00454 
00455        /* make sure the database is registered; then add monitor attributes */
00456        rc = mbe->register_database( be, &bdb->bi_monitor.bdm_ndn );
00457        if ( rc == 0 ) {
00458               rc = mbe->register_entry_attrs( &bdb->bi_monitor.bdm_ndn, a, cb,
00459                      &dummy, 0, &dummy );
00460        }
00461 
00462 cleanup:;
00463        if ( rc != 0 ) {
00464               if ( cb != NULL ) {
00465                      ch_free( cb );
00466                      cb = NULL;
00467               }
00468 
00469               if ( a != NULL ) {
00470                      attrs_free( a );
00471                      a = NULL;
00472               }
00473        }
00474 
00475        /* store for cleanup */
00476        bdb->bi_monitor.bdm_cb = (void *)cb;
00477 
00478        /* we don't need to keep track of the attributes, because
00479         * bdb_monitor_free() takes care of everything */
00480        if ( a != NULL ) {
00481               attrs_free( a );
00482        }
00483 
00484        return rc;
00485 }
00486 
00487 /*
00488  * call from within bdb_db_close()
00489  */
00490 int
00491 bdb_monitor_db_close( BackendDB *be )
00492 {
00493        struct bdb_info             *bdb = (struct bdb_info *) be->be_private;
00494 
00495        if ( !BER_BVISNULL( &bdb->bi_monitor.bdm_ndn ) ) {
00496               BackendInfo          *mi = backend_info( "monitor" );
00497               monitor_extra_t             *mbe;
00498 
00499               if ( mi && &mi->bi_extra ) {
00500                      mbe = mi->bi_extra;
00501                      mbe->unregister_entry_callback( &bdb->bi_monitor.bdm_ndn,
00502                             (monitor_callback_t *)bdb->bi_monitor.bdm_cb,
00503                             NULL, 0, NULL );
00504               }
00505 
00506               memset( &bdb->bi_monitor, 0, sizeof( bdb->bi_monitor ) );
00507        }
00508 
00509        return 0;
00510 }
00511 
00512 /*
00513  * call from within bdb_db_destroy()
00514  */
00515 int
00516 bdb_monitor_db_destroy( BackendDB *be )
00517 {
00518 #ifdef BDB_MONITOR_IDX
00519        struct bdb_info             *bdb = (struct bdb_info *) be->be_private;
00520 
00521        /* TODO: free tree */
00522        ldap_pvt_thread_mutex_destroy( &bdb->bi_idx_mutex );
00523        avl_free( bdb->bi_idx, ch_free );
00524 #endif /* BDB_MONITOR_IDX */
00525 
00526        return 0;
00527 }
00528 
00529 #ifdef BDB_MONITOR_IDX
00530 
00531 #define BDB_MONITOR_IDX_TYPES      (4)
00532 
00533 typedef struct monitor_idx_t monitor_idx_t;
00534 
00535 struct monitor_idx_t {
00536        AttributeDescription *idx_ad;
00537        unsigned long        idx_count[BDB_MONITOR_IDX_TYPES];
00538 };
00539 
00540 static int
00541 bdb_monitor_bitmask2key( slap_mask_t bitmask )
00542 {
00543        int    key;
00544 
00545        for ( key = 0; key < 8 * (int)sizeof(slap_mask_t) && !( bitmask & 0x1U );
00546                      key++ )
00547               bitmask >>= 1;
00548 
00549        return key;
00550 }
00551 
00552 static struct berval idxbv[] = {
00553        BER_BVC( "present=" ),
00554        BER_BVC( "equality=" ),
00555        BER_BVC( "approx=" ),
00556        BER_BVC( "substr=" ),
00557        BER_BVNULL
00558 };
00559 
00560 static ber_len_t
00561 bdb_monitor_idx2len( monitor_idx_t *idx )
00562 {
00563        int           i;
00564        ber_len_t     len = 0;
00565 
00566        for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
00567               if ( idx->idx_count[ i ] != 0 ) {
00568                      len += idxbv[i].bv_len;
00569               }
00570        }
00571 
00572        return len;
00573 }
00574 
00575 static int
00576 monitor_idx_cmp( const void *p1, const void *p2 )
00577 {
00578        const monitor_idx_t  *idx1 = (const monitor_idx_t *)p1;
00579        const monitor_idx_t  *idx2 = (const monitor_idx_t *)p2;
00580 
00581        return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad );
00582 }
00583 
00584 static int
00585 monitor_idx_dup( void *p1, void *p2 )
00586 {
00587        monitor_idx_t *idx1 = (monitor_idx_t *)p1;
00588        monitor_idx_t *idx2 = (monitor_idx_t *)p2;
00589 
00590        return SLAP_PTRCMP( idx1->idx_ad, idx2->idx_ad ) == 0 ? -1 : 0;
00591 }
00592 
00593 int
00594 bdb_monitor_idx_add(
00595        struct bdb_info             *bdb,
00596        AttributeDescription *desc,
00597        slap_mask_t          type )
00598 {
00599        monitor_idx_t        idx_dummy = { 0 },
00600                             *idx;
00601        int                  rc = 0, key;
00602 
00603        idx_dummy.idx_ad = desc;
00604        key = bdb_monitor_bitmask2key( type ) - 1;
00605        if ( key >= BDB_MONITOR_IDX_TYPES ) {
00606               /* invalid index type */
00607               return -1;
00608        }
00609 
00610        ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
00611 
00612        idx = (monitor_idx_t *)avl_find( bdb->bi_idx,
00613               (caddr_t)&idx_dummy, monitor_idx_cmp );
00614        if ( idx == NULL ) {
00615               idx = (monitor_idx_t *)ch_calloc( sizeof( monitor_idx_t ), 1 );
00616               idx->idx_ad = desc;
00617               idx->idx_count[ key ] = 1;
00618 
00619               switch ( avl_insert( &bdb->bi_idx, (caddr_t)idx, 
00620                      monitor_idx_cmp, monitor_idx_dup ) )
00621               {
00622               case 0:
00623                      break;
00624 
00625               default:
00626                      ch_free( idx );
00627                      rc = -1;
00628               }
00629 
00630        } else {
00631               idx->idx_count[ key ]++;
00632        }
00633 
00634        ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
00635 
00636        return rc;
00637 }
00638 
00639 static int
00640 bdb_monitor_idx_apply( void *v_idx, void *v_valp )
00641 {
00642        monitor_idx_t *idx = (monitor_idx_t *)v_idx;
00643        BerVarray     *valp = (BerVarray *)v_valp;
00644 
00645        struct berval bv;
00646        char          *ptr;
00647        char          count_buf[ BDB_MONITOR_IDX_TYPES ][ SLAP_TEXT_BUFLEN ];
00648        ber_len_t     count_len[ BDB_MONITOR_IDX_TYPES ],
00649                      idx_len;
00650        int           i, num = 0;
00651 
00652        idx_len = bdb_monitor_idx2len( idx );
00653 
00654        bv.bv_len = 0;
00655        for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
00656               if ( idx->idx_count[ i ] == 0 ) {
00657                      continue;
00658               }
00659 
00660               count_len[ i ] = snprintf( count_buf[ i ],
00661                      sizeof( count_buf[ i ] ), "%lu", idx->idx_count[ i ] );
00662               bv.bv_len += count_len[ i ];
00663               num++;
00664        }
00665 
00666        bv.bv_len += idx->idx_ad->ad_cname.bv_len
00667               + num
00668               + idx_len;
00669        ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 );
00670        ptr = lutil_strcopy( ptr, idx->idx_ad->ad_cname.bv_val );
00671        for ( i = 0; i < BDB_MONITOR_IDX_TYPES; i++ ) {
00672               if ( idx->idx_count[ i ] == 0 ) {
00673                      continue;
00674               }
00675 
00676               ptr[ 0 ] = '#';
00677               ++ptr;
00678               ptr = lutil_strcopy( ptr, idxbv[ i ].bv_val );
00679               ptr = lutil_strcopy( ptr, count_buf[ i ] );
00680        }
00681 
00682        ber_bvarray_add( valp, &bv );
00683 
00684        return 0;
00685 }
00686 
00687 static int
00688 bdb_monitor_idx_entry_add(
00689        struct bdb_info      *bdb,
00690        Entry         *e )
00691 {
00692        BerVarray     vals = NULL;
00693        Attribute     *a;
00694 
00695        a = attr_find( e->e_attrs, ad_olmDbNotIndexed );
00696 
00697        ldap_pvt_thread_mutex_lock( &bdb->bi_idx_mutex );
00698 
00699        avl_apply( bdb->bi_idx, bdb_monitor_idx_apply,
00700               &vals, -1, AVL_INORDER );
00701 
00702        ldap_pvt_thread_mutex_unlock( &bdb->bi_idx_mutex );
00703 
00704        if ( vals != NULL ) {
00705               if ( a != NULL ) {
00706                      assert( a->a_nvals == a->a_vals );
00707 
00708                      ber_bvarray_free( a->a_vals );
00709 
00710               } else {
00711                      Attribute     **ap;
00712 
00713                      for ( ap = &e->e_attrs; *ap != NULL; ap = &(*ap)->a_next )
00714                             ;
00715                      *ap = attr_alloc( ad_olmDbNotIndexed );
00716                      a = *ap;
00717               }
00718               a->a_vals = vals;
00719               a->a_nvals = a->a_vals;
00720        }
00721 
00722        return 0;
00723 }
00724 
00725 #endif /* BDB_MONITOR_IDX */