diff --git a/configure b/configure
index 43694150d6..83f1233fd8 100755
--- a/configure
+++ b/configure
@@ -40109,6 +40109,23 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
+if test "$ol_enable_monitor" != no ; then
+ BUILD_SLAPD=yes
+ BUILD_MONITOR=$ol_enable_monitor
+ if test "$ol_enable_monitor" = mod ; then
+ SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-monitor"
+ MFLAG=SLAPD_MOD_DYNAMIC
+ else
+ SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-monitor"
+ MFLAG=SLAPD_MOD_STATIC
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define SLAPD_MONITOR $MFLAG
+_ACEOF
+
+fi
+
if test "$ol_enable_bdb" != no ; then
BUILD_SLAPD=yes
BUILD_BDB=$ol_enable_bdb
@@ -40195,23 +40212,6 @@ _ACEOF
fi
-if test "$ol_enable_monitor" != no ; then
- BUILD_SLAPD=yes
- BUILD_MONITOR=$ol_enable_monitor
- if test "$ol_enable_monitor" = mod ; then
- SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-monitor"
- MFLAG=SLAPD_MOD_DYNAMIC
- else
- SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-monitor"
- MFLAG=SLAPD_MOD_STATIC
- fi
-
-cat >>confdefs.h <<_ACEOF
-#define SLAPD_MONITOR $MFLAG
-_ACEOF
-
-fi
-
if test "$ol_enable_null" != no ; then
BUILD_SLAPD=yes
BUILD_NULL=$ol_enable_null
diff --git a/configure.in b/configure.in
index 692d8d3384..aa2b1fe72e 100644
--- a/configure.in
+++ b/configure.in
@@ -2562,6 +2562,20 @@ fi
AC_DEFINE(SLAPD_MOD_STATIC,1,[statically linked module])
AC_DEFINE(SLAPD_MOD_DYNAMIC,2,[dynamically linked module])
+dnl back-monitor goes first (well, after back-config)
+if test "$ol_enable_monitor" != no ; then
+ BUILD_SLAPD=yes
+ BUILD_MONITOR=$ol_enable_monitor
+ if test "$ol_enable_monitor" = mod ; then
+ SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-monitor"
+ MFLAG=SLAPD_MOD_DYNAMIC
+ else
+ SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-monitor"
+ MFLAG=SLAPD_MOD_STATIC
+ fi
+ AC_DEFINE_UNQUOTED(SLAPD_MONITOR,$MFLAG,[define to support cn=Monitor backend])
+fi
+
if test "$ol_enable_bdb" != no ; then
BUILD_SLAPD=yes
BUILD_BDB=$ol_enable_bdb
@@ -2628,19 +2642,6 @@ if test "$ol_enable_meta" != no ; then
AC_DEFINE_UNQUOTED(SLAPD_META,$MFLAG,[define to support LDAP Metadirectory backend])
fi
-if test "$ol_enable_monitor" != no ; then
- BUILD_SLAPD=yes
- BUILD_MONITOR=$ol_enable_monitor
- if test "$ol_enable_monitor" = mod ; then
- SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-monitor"
- MFLAG=SLAPD_MOD_DYNAMIC
- else
- SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-monitor"
- MFLAG=SLAPD_MOD_STATIC
- fi
- AC_DEFINE_UNQUOTED(SLAPD_MONITOR,$MFLAG,[define to support cn=Monitor backend])
-fi
-
if test "$ol_enable_null" != no ; then
BUILD_SLAPD=yes
BUILD_NULL=$ol_enable_null
diff --git a/servers/slapd/back-bdb/Makefile.in b/servers/slapd/back-bdb/Makefile.in
index 06a987f489..4f1d8d0cc9 100644
--- a/servers/slapd/back-bdb/Makefile.in
+++ b/servers/slapd/back-bdb/Makefile.in
@@ -18,14 +18,14 @@ SRCS = init.c tools.c config.c \
extended.c referral.c operational.c \
attr.c index.c key.c dbcache.c filterindex.c \
dn2entry.c dn2id.c error.c id2entry.c idl.c \
- nextid.c cache.c trans.c
+ nextid.c cache.c trans.c monitor.c
OBJS = init.lo tools.lo config.lo \
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
extended.lo referral.lo operational.lo \
attr.lo index.lo key.lo dbcache.lo filterindex.lo \
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo \
- nextid.lo cache.lo trans.lo
+ nextid.lo cache.lo trans.lo monitor.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c
index dccc329070..fcdab9ad2c 100644
--- a/servers/slapd/back-bdb/init.c
+++ b/servers/slapd/back-bdb/init.c
@@ -422,6 +422,12 @@ bdb_db_open( BackendDB *be )
XLOCK_ID(bdb->bi_dbenv, &bdb->bi_cache.c_locker);
}
+ /* monitor setup */
+ rc = bdb_monitor_open( be );
+ if ( rc != 0 ) {
+ goto fail;
+ }
+
bdb->bi_flags |= BDB_IS_OPEN;
entry_prealloc( bdb->bi_cache.c_maxsize );
@@ -663,6 +669,14 @@ bdb_back_initialize(
bi->bi_connection_init = 0;
bi->bi_connection_destroy = 0;
+ /*
+ * initialize monitor stuff
+ */
+ rc = bdb_monitor_initialize();
+ if ( rc ) {
+ return rc;
+ }
+
rc = bdb_back_init_cf( bi );
return rc;
diff --git a/servers/slapd/back-bdb/monitor.c b/servers/slapd/back-bdb/monitor.c
new file mode 100644
index 0000000000..aaabe0a0d4
--- /dev/null
+++ b/servers/slapd/back-bdb/monitor.c
@@ -0,0 +1,351 @@
+/* monitor.c - monitor bdb backend */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software .
+ *
+ * Copyright 2000-2006 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * .
+ */
+
+#include "portable.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "lutil.h"
+#include "back-bdb.h"
+#include "../back-monitor/back-monitor.h"
+
+static ObjectClass *oc_olmBDBDatabase;
+
+static AttributeDescription *ad_olmBDBCounter;
+
+static int
+bdb_monitor_update(
+ Operation *op,
+ SlapReply *rs,
+ Entry *e,
+ void *priv )
+{
+ struct bdb_info *bdb = (struct bdb_info *) priv;
+ Attribute *a;
+
+ /* NOTE: dummy code that increments a olmBDBCounter
+ * any time it's called; replace with something useful */
+ unsigned long u;
+ char buf[ BUFSIZ ];
+ struct berval bv;
+
+ assert( ad_olmBDBCounter != NULL );
+
+ a = attr_find( e->e_attrs, ad_olmBDBCounter );
+ assert( a != NULL );
+ lutil_atoul( &u, a->a_vals[ 0 ].bv_val );
+ u++;
+ bv.bv_val = buf;
+ bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", u );
+ ber_bvreplace( &a->a_vals[ 0 ], &bv );
+
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+bdb_monitor_modify(
+ Operation *op,
+ SlapReply *rs,
+ Entry *e,
+ void *priv )
+{
+ struct bdb_info *bdb = (struct bdb_info *) priv;
+
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+bdb_monitor_free(
+ Entry *e,
+ void *priv )
+{
+ struct bdb_info *bdb = (struct bdb_info *) priv;
+
+ return SLAP_CB_CONTINUE;
+}
+
+/*
+ * NOTE: there's some confusion in monitor OID arc;
+ * by now, let's consider:
+ *
+ * Subsystems monitor attributes 1.3.6.1.4.1.4203.666.1.55.0
+ * Databases monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1
+ * BDB database monitor attributes 1.3.6.1.4.1.4203.666.1.55.0.1.1
+ *
+ * Subsystems monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0
+ * Databases monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1
+ * BDB database monitor objectclasses 1.3.6.1.4.1.4203.666.3.16.0.1.1
+ */
+#define BDB_MONITOR_SCHEMA_AD "1.3.6.1.4.1.4203.666.1.55.0.1.1"
+#define BDB_MONITOR_SCHEMA_OC "1.3.6.1.4.1.4203.666.3.16.0.1.1"
+
+static struct {
+ char *name;
+ char *desc;
+ AttributeDescription **ad;
+} s_at[] = {
+ { "olmBDBCounter", "( " BDB_MONITOR_SCHEMA_AD ".0 "
+ "NAME ( 'olmBDBCounter' ) "
+ "DESC 'A dummy counter' "
+ "SUP monitorCounter "
+ "NO-USER-MODIFICATION "
+ "USAGE directoryOperation )",
+ &ad_olmBDBCounter },
+
+ { NULL }
+};
+
+static struct {
+ char *name;
+ char *desc;
+ ObjectClass **oc;
+} s_oc[] = {
+ { "olmBDBDatabase", "( " BDB_MONITOR_SCHEMA_OC ".1 "
+ "NAME ( 'olmBDBDatabase' ) "
+ "SUP monitoredObject STRUCTURAL "
+ "MAY ( "
+ "olmBDBCounter "
+ ") )",
+ &oc_olmBDBDatabase },
+
+ { NULL }
+};
+
+/*
+ * call from within bdb_initialize()
+ */
+int
+bdb_monitor_initialize( void )
+{
+ int i, code;
+ const char *err;
+
+ static int bdb_monitor_initialized = 0;
+
+ /* register schema here; if compiled as dynamic object,
+ * must be loaded __after__ back_monitor.la */
+
+ if ( bdb_monitor_initialized++ ) {
+ return 0;
+ }
+
+ for ( i = 0; s_at[ i ].name != NULL; i++ ) {
+ LDAPAttributeType *at;
+
+ at = ldap_str2attributetype( s_at[ i ].desc,
+ &code, &err, LDAP_SCHEMA_ALLOW_ALL );
+ if ( !at ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb_monitor_initialize: "
+ "AttributeType load failed: %s %s\n",
+ ldap_scherr2str( code ), err, 0 );
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ code = at_add( at, 0, NULL, &err );
+ if ( code != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb_monitor_initialize: "
+ "AttributeType load failed: %s %s\n",
+ scherr2str( code ), err, 0 );
+ code = LDAP_INVALID_SYNTAX;
+ goto done_at;
+ }
+
+ code = slap_str2ad( s_at[ i ].name,
+ s_at[ i ].ad, &err );
+ if ( code != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb_monitor_initialize: "
+ "unable to find AttributeDescription "
+ "\"%s\": %d (%s)\n",
+ s_at[ i ].name, code, err );
+ code = LDAP_UNDEFINED_TYPE;
+ goto done_at;
+ }
+
+done_at:;
+ if ( code ) {
+ ldap_attributetype_free( at );
+ return code;
+ }
+
+ ldap_memfree( at );
+ }
+
+ for ( i = 0; s_oc[ i ].name != NULL; i++ ) {
+ LDAPObjectClass *oc;
+
+ oc = ldap_str2objectclass( s_oc[ i ].desc,
+ &code, &err, LDAP_SCHEMA_ALLOW_ALL );
+ if ( !oc ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb_monitor_initialize: "
+ "ObjectClass load failed: %s %s\n",
+ ldap_scherr2str( code ), err, 0 );
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ code = oc_add( oc, 0, NULL, &err );
+ if ( code != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "bdb_monitor_initialize: "
+ "ObjectClass load failed: %s %s\n",
+ scherr2str( code ), err, 0 );
+ code = LDAP_INVALID_SYNTAX;
+ goto done_oc;
+ }
+
+ *s_oc[ i ].oc = oc_find( s_oc[ i ].name );
+ if ( *s_oc[ i ].oc == NULL ) {
+ code = LDAP_UNDEFINED_TYPE;
+ Debug( LDAP_DEBUG_ANY,
+ "bdb_monitor_initialize: "
+ "unable to find objectClass \"%s\"\n",
+ s_oc[ i ].name, 0, 0 );
+ goto done_oc;
+ }
+
+done_oc:;
+ if ( code != LDAP_SUCCESS ) {
+ ldap_objectclass_free( oc );
+ return code;
+ }
+
+ ldap_memfree( oc );
+ }
+
+ return 0;
+}
+
+/*
+ * call from within bdb_db_init()
+ */
+int
+bdb_monitor_init( BackendDB *be )
+{
+ return 0;
+}
+
+/*
+ * call from within bdb_db_open()
+ */
+int
+bdb_monitor_open( BackendDB *be )
+{
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ Attribute *a, *next;
+ monitor_callback_t *cb;
+ struct berval base = BER_BVC( "cn=databases,cn=monitor" );
+ struct berval suffix, filter;
+ char *ptr;
+ int rc = 0;
+
+ /* monitor_back_register_entry_attrs() with a NULL ndn,
+ * base="cn=Databases,cn=Monitor", scope=LDAP_SCOPE_ONE
+ * and filter="(namingContexts:distinguishedNameMatch:=)" */
+
+ suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
+ if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
+ suffix = be->be_nsuffix[ 0 ];
+
+ } else {
+ ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
+ }
+
+ filter.bv_len = STRLENOF( "(namingContexts:distinguishedNameMatch:=)" ) + suffix.bv_len;
+ ptr = filter.bv_val = ch_malloc( filter.bv_len + 1 );
+ ptr = lutil_strcopy( ptr, "(namingContexts:distinguishedNameMatch:=" );
+ ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
+ ptr[ 0 ] = ')';
+ ptr++;
+ ptr[ 0 ] = '\0';
+ assert( filter.bv_len == ptr - filter.bv_val );
+
+ if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
+ ch_free( suffix.bv_val );
+ }
+
+ /* alloc as many as required (plus 1 for objectClass) */
+ a = attrs_alloc( 1 + 1 );
+ if ( a == NULL ) {
+ rc = 1;
+ goto cleanup;
+ }
+
+ a->a_desc = slap_schema.si_ad_objectClass;
+ a->a_vals = NULL;
+ value_add_one( &a->a_vals, &oc_olmBDBDatabase->soc_cname );
+ a->a_nvals = a->a_vals;
+ next = a->a_next;
+
+ /* NOTE: dummy code that increments a olmBDBCounter
+ * any time it's called; replace with something useful */
+ {
+ struct berval bv = BER_BVC( "0" );
+
+ next->a_desc = ad_olmBDBCounter;
+ next->a_vals = NULL;
+ value_add_one( &next->a_vals, &bv );
+ next->a_nvals = next->a_vals;
+ next = a->a_next;
+ }
+
+ cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
+ cb->mc_update = bdb_monitor_update;
+ cb->mc_modify = bdb_monitor_modify;
+ cb->mc_free = bdb_monitor_free;
+ cb->mc_private = (void *)bdb;
+
+ rc = monitor_back_register_entry_attrs( NULL,
+ a, cb, &base, LDAP_SCOPE_ONELEVEL, &filter );
+
+cleanup:;
+ if ( rc != 0 ) {
+ if ( cb != NULL ) {
+ ch_free( cb );
+ }
+
+ if ( a != NULL ) {
+ attrs_free( a );
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * call from within bdb_db_close()
+ */
+int
+bdb_monitor_close( BackendDB *be )
+{
+ return 0;
+}
+
+/*
+ * call from within bdb_db_destroy()
+ */
+int
+bdb_monitor_destroy( BackendDB *be )
+{
+ return 0;
+}
+
diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h
index 19cdb7ddf4..f3b69fc7aa 100644
--- a/servers/slapd/back-bdb/proto-bdb.h
+++ b/servers/slapd/back-bdb/proto-bdb.h
@@ -426,6 +426,14 @@ int bdb_modify_internal(
char *textbuf,
size_t textlen );
+/*
+ * monitor.c
+ */
+int bdb_monitor_initialize( void );
+int bdb_monitor_init( BackendDB *be );
+int bdb_monitor_open( BackendDB *be );
+int bdb_monitor_close( BackendDB *be );
+int bdb_monitor_destroy( BackendDB *be );
/*
* cache.c
diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c
index 264b70c5c7..3a3d4b543a 100644
--- a/servers/slapd/back-monitor/init.c
+++ b/servers/slapd/back-monitor/init.c
@@ -471,7 +471,7 @@ monitor_back_register_entry_parent(
/* entry does not exist */
Debug( LDAP_DEBUG_ANY,
"monitor_back_register_entry_parent(\"\"): "
- "base=%s scope=%d filter=%s : "
+ "base=\"%s\" scope=%d filter=\"%s\": "
"unable to find entry\n",
base->bv_val ? base->bv_val : "\"\"",
scope, filter->bv_val );
@@ -797,7 +797,7 @@ monitor_back_register_entry_attrs(
snprintf( buf, sizeof( buf ),
"monitor_back_register_entry_%s(\"\"): "
- "base=%s scope=%d filter=%s : "
+ "base=\"%s\" scope=%d filter=\"%s\": "
"unable to find entry\n",
fname,
base->bv_val ? base->bv_val : "\"\"",
@@ -838,14 +838,26 @@ monitor_back_register_entry_attrs(
for ( atp = &e->e_attrs; *atp; atp = &(*atp)->a_next )
/* just get to last */ ;
- *atp = attrs_dup( a );
- if ( *atp == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "monitor_back_register_entry_%s(\"%s\"): "
- "attrs_dup() failed\n",
- fname, e->e_name.bv_val, 0 );
- rc = -1;
- goto done;
+ for ( ; a != NULL; a = a->a_next ) {
+ assert( a->a_desc != NULL );
+ assert( a->a_vals != NULL );
+
+ if ( attr_find( e->e_attrs, a->a_desc ) ) {
+ attr_merge( e, a->a_desc, a->a_vals,
+ a->a_nvals == a->a_vals ? NULL : a->a_nvals );
+
+ } else {
+ *atp = attr_dup( a );
+ if ( *atp == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "monitor_back_register_entry_%s(\"%s\"): "
+ "attr_dup() failed\n",
+ fname, e->e_name.bv_val, 0 );
+ rc = -1;
+ goto done;
+ }
+ atp = &(*atp)->a_next;
+ }
}
}
@@ -923,6 +935,57 @@ monitor_back_register_entry_callback(
base, scope, filter );
}
+/*
+ * TODO: add corresponding calls to remove installed callbacks, entries
+ * and so, in case the entity that installed them is removed (e.g. a
+ * database, via back-config)
+ */
+int
+monitor_back_unregister_entry(
+ Entry **ep,
+ monitor_callback_t **cbp )
+{
+ /* TODO */
+ return 1;
+}
+
+int
+monitor_back_unregister_entry_parent(
+ Entry **ep,
+ monitor_callback_t **cbp,
+ struct berval *base,
+ int scope,
+ struct berval *filter )
+{
+ /* TODO */
+ return 1;
+}
+
+int
+monitor_back_unregister_entry_attrs(
+ struct berval *ndn,
+ Attribute **ap,
+ monitor_callback_t **cbp,
+ struct berval *base,
+ int scope,
+ struct berval *filter )
+{
+ /* TODO */
+ return 1;
+}
+
+int
+monitor_back_unregister_entry_callback(
+ struct berval *ndn,
+ monitor_callback_t **cbp,
+ struct berval *base,
+ int scope,
+ struct berval *filter )
+{
+ return monitor_back_unregister_entry_attrs( ndn, NULL, cbp,
+ base, scope, filter );
+}
+
monitor_subsys_t *
monitor_back_get_subsys( const char *name )
{
diff --git a/servers/slapd/back-monitor/proto-back-monitor.h b/servers/slapd/back-monitor/proto-back-monitor.h
index ebe6a46c68..3b97e119a2 100644
--- a/servers/slapd/back-monitor/proto-back-monitor.h
+++ b/servers/slapd/back-monitor/proto-back-monitor.h
@@ -173,6 +173,32 @@ monitor_back_register_entry_callback LDAP_P((
struct berval *base,
int scope,
struct berval *filter ));
+extern int
+monitor_back_unregister_entry LDAP_P((
+ Entry **ep,
+ monitor_callback_t **cbp ));
+extern int
+monitor_back_unregister_entry_parent LDAP_P((
+ Entry **ep,
+ monitor_callback_t **cbp,
+ struct berval *base,
+ int scope,
+ struct berval *filter ));
+extern int
+monitor_back_unregister_entry_attrs LDAP_P((
+ struct berval *ndn,
+ Attribute **ap,
+ monitor_callback_t **cbp,
+ struct berval *base,
+ int scope,
+ struct berval *filter ));
+extern int
+monitor_back_unregister_entry_callback LDAP_P((
+ struct berval *ndn,
+ monitor_callback_t **cbp,
+ struct berval *base,
+ int scope,
+ struct berval *filter ));
/*
* listener