1 /* monitor.c - monitor bdb backend */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-bdb/monitor.c,v 1.19.2.9 2008/05/26 18:57:01 ando Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2000-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/string.h>
21 #include <ac/unistd.h>
22 #include <ac/stdlib.h>
28 #include "../back-monitor/back-monitor.h"
32 static ObjectClass
*oc_olmBDBDatabase
;
34 static AttributeDescription
*ad_olmBDBEntryCache
,
35 *ad_olmBDBDNCache
, *ad_olmBDBIDLCache
,
38 #ifdef BDB_MONITOR_IDX
40 bdb_monitor_idx_entry_add(
44 static AttributeDescription
*ad_olmBDBNotIndexed
;
45 #endif /* BDB_MONITOR_IDX */
48 * NOTE: there's some confusion in monitor OID arc;
49 * by now, let's consider:
51 * Subsystems monitor attributes 1.3.6.1.4.1.4203.666.1.55.0
52 * Databases monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1
53 * BDB database monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1.1
55 * Subsystems monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0
56 * Databases monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1
57 * BDB database monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1.1
64 { "olmBDBAttributes", "olmDatabaseAttributes:1" },
65 { "olmBDBObjectClasses", "olmDatabaseObjectClasses:1" },
72 AttributeDescription
**ad
;
74 { "( olmBDBAttributes:1 "
75 "NAME ( 'olmBDBEntryCache' ) "
76 "DESC 'Number of items in Entry Cache' "
78 "NO-USER-MODIFICATION "
79 "USAGE dSAOperation )",
80 &ad_olmBDBEntryCache
},
82 { "( olmBDBAttributes:2 "
83 "NAME ( 'olmBDBDNCache' ) "
84 "DESC 'Number of items in DN Cache' "
86 "NO-USER-MODIFICATION "
87 "USAGE dSAOperation )",
90 { "( olmBDBAttributes:3 "
91 "NAME ( 'olmBDBIDLCache' ) "
92 "DESC 'Number of items in IDL Cache' "
94 "NO-USER-MODIFICATION "
95 "USAGE dSAOperation )",
98 { "( olmBDBAttributes:4 "
99 "NAME ( 'olmDbDirectory' ) "
100 "DESC 'Path name of the directory "
101 "where the database environment resides' "
103 "NO-USER-MODIFICATION "
104 "USAGE dSAOperation )",
105 &ad_olmDbDirectory
},
107 #ifdef BDB_MONITOR_IDX
108 { "( olmBDBAttributes:5 "
109 "NAME ( 'olmBDBNotIndexed' ) "
110 "DESC 'Missing indexes resulting from candidate selection' "
112 "NO-USER-MODIFICATION "
113 "USAGE dSAOperation )",
114 &ad_olmBDBNotIndexed
},
115 #endif /* BDB_MONITOR_IDX */
124 /* augments an existing object, so it must be AUXILIARY
125 * FIXME: derive from some ABSTRACT "monitoredEntity"? */
126 { "( olmBDBObjectClasses:1 "
127 "NAME ( 'olmBDBDatabase' ) "
134 #ifdef BDB_MONITOR_IDX
135 "$ olmBDBNotIndexed "
136 #endif /* BDB_MONITOR_IDX */
138 &oc_olmBDBDatabase
},
150 struct bdb_info
*bdb
= (struct bdb_info
*) priv
;
156 assert( ad_olmBDBEntryCache
!= NULL
);
158 a
= attr_find( e
->e_attrs
, ad_olmBDBEntryCache
);
161 bv
.bv_len
= snprintf( buf
, sizeof( buf
), "%d", bdb
->bi_cache
.c_cursize
);
162 ber_bvreplace( &a
->a_vals
[ 0 ], &bv
);
164 a
= attr_find( e
->e_attrs
, ad_olmBDBDNCache
);
166 bv
.bv_len
= snprintf( buf
, sizeof( buf
), "%d", bdb
->bi_cache
.c_eiused
);
167 ber_bvreplace( &a
->a_vals
[ 0 ], &bv
);
169 a
= attr_find( e
->e_attrs
, ad_olmBDBIDLCache
);
171 bv
.bv_len
= snprintf( buf
, sizeof( buf
), "%d", bdb
->bi_idl_cache_size
);
172 ber_bvreplace( &a
->a_vals
[ 0 ], &bv
);
174 #ifdef BDB_MONITOR_IDX
175 bdb_monitor_idx_entry_add( bdb
, e
);
176 #endif /* BDB_MONITOR_IDX */
178 return SLAP_CB_CONTINUE
;
181 #if 0 /* uncomment if required */
189 return SLAP_CB_CONTINUE
;
198 struct berval values
[ 2 ];
199 Modification mod
= { 0 };
202 char textbuf
[ SLAP_TEXT_BUFLEN
];
206 /* NOTE: if slap_shutdown != 0, priv might have already been freed */
209 /* Remove objectClass */
210 mod
.sm_op
= LDAP_MOD_DELETE
;
211 mod
.sm_desc
= slap_schema
.si_ad_objectClass
;
212 mod
.sm_values
= values
;
214 values
[ 0 ] = oc_olmBDBDatabase
->soc_cname
;
215 BER_BVZERO( &values
[ 1 ] );
217 rc
= modify_delete_values( e
, &mod
, 1, &text
,
218 textbuf
, sizeof( textbuf
) );
219 /* don't care too much about return code... */
222 mod
.sm_values
= NULL
;
224 for ( i
= 0; s_at
[ i
].desc
!= NULL
; i
++ ) {
225 mod
.sm_desc
= *s_at
[ i
].ad
;
226 rc
= modify_delete_values( e
, &mod
, 1, &text
,
227 textbuf
, sizeof( textbuf
) );
228 /* don't care too much about return code... */
231 return SLAP_CB_CONTINUE
;
234 #define bdb_monitor_initialize BDB_SYMBOL(monitor_initialize)
237 * call from within bdb_initialize()
240 bdb_monitor_initialize( void )
246 static int bdb_monitor_initialized
= 0;
248 if ( backend_info( "monitor" ) == NULL
) {
252 if ( bdb_monitor_initialized
++ ) {
256 /* register schema here */
258 argv
[ 0 ] = "back-bdb/back-hdb monitor";
263 for ( i
= 0; s_oid
[ i
].name
; i
++ ) {
265 argv
[ 1 ] = s_oid
[ i
].name
;
266 argv
[ 2 ] = s_oid
[ i
].oid
;
268 if ( parse_oidm( &c
, 0, NULL
) != 0 ) {
269 Debug( LDAP_DEBUG_ANY
, LDAP_XSTRING(bdb_monitor_initialize
)
271 "objectIdentifier \"%s=%s\"\n",
272 s_oid
[ i
].name
, s_oid
[ i
].oid
, 0 );
277 for ( i
= 0; s_at
[ i
].desc
!= NULL
; i
++ ) {
278 code
= register_at( s_at
[ i
].desc
, s_at
[ i
].ad
, 1 );
279 if ( code
!= LDAP_SUCCESS
) {
280 Debug( LDAP_DEBUG_ANY
, LDAP_XSTRING(bdb_monitor_initialize
)
281 ": register_at failed\n",
284 (*s_at
[ i
].ad
)->ad_type
->sat_flags
|= SLAP_AT_HIDE
;
287 for ( i
= 0; s_oc
[ i
].desc
!= NULL
; i
++ ) {
288 code
= register_oc( s_oc
[ i
].desc
, s_oc
[ i
].oc
, 1 );
289 if ( code
!= LDAP_SUCCESS
) {
290 Debug( LDAP_DEBUG_ANY
, LDAP_XSTRING(bdb_monitor_initialize
)
291 ": register_oc failed\n",
294 (*s_oc
[ i
].oc
)->soc_flags
|= SLAP_OC_HIDE
;
301 * call from within bdb_db_init()
304 bdb_monitor_db_init( BackendDB
*be
)
306 struct bdb_info
*bdb
= (struct bdb_info
*) be
->be_private
;
308 if ( SLAP_GLUE_SUBORDINATE( be
) ) {
312 if ( bdb_monitor_initialize() == LDAP_SUCCESS
) {
313 /* monitoring in back-bdb is on by default */
314 SLAP_DBFLAGS( be
) |= SLAP_DBFLAG_MONITORING
;
317 #ifdef BDB_MONITOR_IDX
319 ldap_pvt_thread_mutex_init( &bdb
->bi_idx_mutex
);
320 #endif /* BDB_MONITOR_IDX */
326 * call from within bdb_db_open()
329 bdb_monitor_db_open( BackendDB
*be
)
331 struct bdb_info
*bdb
= (struct bdb_info
*) be
->be_private
;
333 monitor_callback_t
*cb
= NULL
;
336 monitor_extra_t
*mbe
;
337 struct berval dummy
= BER_BVC("");
339 if ( !SLAP_DBMONITORING( be
) ) {
343 if ( SLAP_GLUE_SUBORDINATE( be
) ) {
347 mi
= backend_info( "monitor" );
348 if ( !mi
|| !mi
->bi_extra
) {
349 SLAP_DBFLAGS( be
) ^= SLAP_DBFLAG_MONITORING
;
354 /* don't bother if monitor is not configured */
355 if ( !mbe
->is_configured() ) {
356 static int warning
= 0;
358 if ( warning
++ == 0 ) {
359 Debug( LDAP_DEBUG_ANY
, LDAP_XSTRING(bdb_monitor_db_open
)
360 ": monitoring disabled; "
361 "configure monitor database to enable\n",
368 /* alloc as many as required (plus 1 for objectClass) */
369 a
= attrs_alloc( 1 + 4 );
375 a
->a_desc
= slap_schema
.si_ad_objectClass
;
376 attr_valadd( a
, &oc_olmBDBDatabase
->soc_cname
, NULL
, 1 );
380 struct berval bv
= BER_BVC( "0" );
382 next
->a_desc
= ad_olmBDBEntryCache
;
383 attr_valadd( next
, &bv
, NULL
, 1 );
386 next
->a_desc
= ad_olmBDBDNCache
;
387 attr_valadd( next
, &bv
, NULL
, 1 );
390 next
->a_desc
= ad_olmBDBIDLCache
;
391 attr_valadd( next
, &bv
, NULL
, 1 );
396 struct berval bv
, nbv
;
397 ber_len_t pathlen
= 0, len
= 0;
398 char path
[ MAXPATHLEN
] = { '\0' };
399 char *fname
= bdb
->bi_dbenv_home
,
402 len
= strlen( fname
);
403 if ( fname
[ 0 ] != '/' ) {
404 /* get full path name */
405 getcwd( path
, sizeof( path
) );
406 pathlen
= strlen( path
);
408 if ( fname
[ 0 ] == '.' && fname
[ 1 ] == '/' ) {
414 bv
.bv_len
= pathlen
+ STRLENOF( "/" ) + len
;
415 ptr
= bv
.bv_val
= ch_malloc( bv
.bv_len
+ STRLENOF( "/" ) + 1 );
417 ptr
= lutil_strncopy( ptr
, path
, pathlen
);
421 ptr
= lutil_strncopy( ptr
, fname
, len
);
422 if ( ptr
[ -1 ] != '/' ) {
428 attr_normalize_one( ad_olmDbDirectory
, &bv
, &nbv
, NULL
);
430 next
->a_desc
= ad_olmDbDirectory
;
431 next
->a_vals
= ch_calloc( sizeof( struct berval
), 2 );
432 next
->a_vals
[ 0 ] = bv
;
435 if ( BER_BVISNULL( &nbv
) ) {
436 next
->a_nvals
= next
->a_vals
;
439 next
->a_nvals
= ch_calloc( sizeof( struct berval
), 2 );
440 next
->a_nvals
[ 0 ] = nbv
;
446 cb
= ch_calloc( sizeof( monitor_callback_t
), 1 );
447 cb
->mc_update
= bdb_monitor_update
;
448 #if 0 /* uncomment if required */
449 cb
->mc_modify
= bdb_monitor_modify
;
451 cb
->mc_free
= bdb_monitor_free
;
452 cb
->mc_private
= (void *)bdb
;
454 /* make sure the database is registered; then add monitor attributes */
455 rc
= mbe
->register_database( be
, &bdb
->bi_monitor
.bdm_ndn
);
457 rc
= mbe
->register_entry_attrs( &bdb
->bi_monitor
.bdm_ndn
, a
, cb
,
474 /* store for cleanup */
475 bdb
->bi_monitor
.bdm_cb
= (void *)cb
;
477 /* we don't need to keep track of the attributes, because
478 * bdb_monitor_free() takes care of everything */
487 * call from within bdb_db_close()
490 bdb_monitor_db_close( BackendDB
*be
)
492 struct bdb_info
*bdb
= (struct bdb_info
*) be
->be_private
;
494 if ( SLAP_GLUE_SUBORDINATE( be
) ) {
498 if ( !BER_BVISNULL( &bdb
->bi_monitor
.bdm_ndn
) ) {
499 BackendInfo
*mi
= backend_info( "monitor" );
500 monitor_extra_t
*mbe
;
502 if ( mi
&& &mi
->bi_extra
) {
504 mbe
->unregister_entry_callback( &bdb
->bi_monitor
.bdm_ndn
,
505 (monitor_callback_t
*)bdb
->bi_monitor
.bdm_cb
,
509 memset( &bdb
->bi_monitor
, 0, sizeof( bdb
->bi_monitor
) );
516 * call from within bdb_db_destroy()
519 bdb_monitor_db_destroy( BackendDB
*be
)
521 if ( SLAP_GLUE_SUBORDINATE( be
) ) {
525 #ifdef BDB_MONITOR_IDX
527 struct bdb_info
*bdb
= (struct bdb_info
*) be
->be_private
;
529 /* TODO: free tree */
530 ldap_pvt_thread_mutex_destroy( &bdb
->bi_idx_mutex
);
531 avl_free( bdb
->bi_idx
, ch_free
);
533 #endif /* BDB_MONITOR_IDX */
538 #ifdef BDB_MONITOR_IDX
540 #define BDB_MONITOR_IDX_TYPES (4)
542 typedef struct monitor_idx_t monitor_idx_t
;
544 struct monitor_idx_t
{
545 AttributeDescription
*idx_ad
;
546 unsigned long idx_count
[BDB_MONITOR_IDX_TYPES
];
550 bdb_monitor_bitmask2key( slap_mask_t bitmask
)
554 for ( key
= 0; key
< 8*sizeof(slap_mask_t
) && !( bitmask
& 0x1U
); key
++ ) {
561 static struct berval idxbv
[] = {
562 BER_BVC( "present=" ),
563 BER_BVC( "equality=" ),
564 BER_BVC( "approx=" ),
565 BER_BVC( "substr=" ),
570 bdb_monitor_idx2len( monitor_idx_t
*idx
)
575 for ( i
= 0; i
< BDB_MONITOR_IDX_TYPES
; i
++ ) {
576 if ( idx
->idx_count
[ i
] != 0 ) {
577 len
+= idxbv
[i
].bv_len
;
585 monitor_idx_cmp( const void *p1
, const void *p2
)
587 const monitor_idx_t
*idx1
= (const monitor_idx_t
*)p1
;
588 const monitor_idx_t
*idx2
= (const monitor_idx_t
*)p2
;
590 return SLAP_PTRCMP( idx1
->idx_ad
, idx2
->idx_ad
);
594 monitor_idx_dup( void *p1
, void *p2
)
596 monitor_idx_t
*idx1
= (monitor_idx_t
*)p1
;
597 monitor_idx_t
*idx2
= (monitor_idx_t
*)p2
;
599 return SLAP_PTRCMP( idx1
->idx_ad
, idx2
->idx_ad
) == 0 ? -1 : 0;
604 struct bdb_info
*bdb
,
605 AttributeDescription
*desc
,
608 monitor_idx_t idx_dummy
= { 0 },
612 idx_dummy
.idx_ad
= desc
;
613 key
= bdb_monitor_bitmask2key( type
) - 1;
614 if ( key
>= BDB_MONITOR_IDX_TYPES
) {
615 /* invalid index type */
619 ldap_pvt_thread_mutex_lock( &bdb
->bi_idx_mutex
);
621 idx
= (monitor_idx_t
*)avl_find( bdb
->bi_idx
,
622 (caddr_t
)&idx_dummy
, monitor_idx_cmp
);
624 idx
= (monitor_idx_t
*)ch_calloc( sizeof( monitor_idx_t
), 1 );
626 idx
->idx_count
[ key
] = 1;
628 switch ( avl_insert( &bdb
->bi_idx
, (caddr_t
)idx
,
629 monitor_idx_cmp
, monitor_idx_dup
) )
640 idx
->idx_count
[ key
]++;
643 ldap_pvt_thread_mutex_unlock( &bdb
->bi_idx_mutex
);
649 bdb_monitor_idx_apply( void *v_idx
, void *v_valp
)
651 monitor_idx_t
*idx
= (monitor_idx_t
*)v_idx
;
652 BerVarray
*valp
= (BerVarray
*)v_valp
;
656 char count_buf
[ BDB_MONITOR_IDX_TYPES
][ SLAP_TEXT_BUFLEN
];
657 ber_len_t count_len
[ BDB_MONITOR_IDX_TYPES
],
661 idx_len
= bdb_monitor_idx2len( idx
);
664 for ( i
= 0; i
< BDB_MONITOR_IDX_TYPES
; i
++ ) {
665 if ( idx
->idx_count
[ i
] == 0 ) {
669 count_len
[ i
] = snprintf( count_buf
[ i
],
670 sizeof( count_buf
[ i
] ), "%lu", idx
->idx_count
[ i
] );
671 bv
.bv_len
+= count_len
[ i
];
675 bv
.bv_len
+= idx
->idx_ad
->ad_cname
.bv_len
678 ptr
= bv
.bv_val
= ch_malloc( bv
.bv_len
+ 1 );
679 ptr
= lutil_strcopy( ptr
, idx
->idx_ad
->ad_cname
.bv_val
);
680 for ( i
= 0; i
< BDB_MONITOR_IDX_TYPES
; i
++ ) {
681 if ( idx
->idx_count
[ i
] == 0 ) {
687 ptr
= lutil_strcopy( ptr
, idxbv
[ i
].bv_val
);
688 ptr
= lutil_strcopy( ptr
, count_buf
[ i
] );
691 ber_bvarray_add( valp
, &bv
);
697 bdb_monitor_idx_entry_add(
698 struct bdb_info
*bdb
,
701 BerVarray vals
= NULL
;
704 a
= attr_find( e
->e_attrs
, ad_olmBDBNotIndexed
);
706 ldap_pvt_thread_mutex_lock( &bdb
->bi_idx_mutex
);
708 avl_apply( bdb
->bi_idx
, bdb_monitor_idx_apply
,
709 &vals
, -1, AVL_INORDER
);
711 ldap_pvt_thread_mutex_unlock( &bdb
->bi_idx_mutex
);
713 if ( vals
!= NULL
) {
715 assert( a
->a_nvals
== a
->a_vals
);
717 ber_bvarray_free( a
->a_vals
);
722 for ( ap
= &e
->e_attrs
; *ap
!= NULL
; ap
= &(*ap
)->a_next
)
724 *ap
= attr_alloc( ad_olmBDBNotIndexed
);
728 a
->a_nvals
= a
->a_vals
;
734 #endif /* BDB_MONITOR_IDX */