diff --git a/include/ldap_defaults.h b/include/ldap_defaults.h
index 9d77e752538daed167f4002390df8ee4cfe2ffbd..c8cbcf2ef29412ef1fd6b75a4f3942e47d540fea 100644
--- a/include/ldap_defaults.h
+++ b/include/ldap_defaults.h
@@ -220,7 +220,6 @@ Please try again later.\r\n"
 #define SLAPD_SCHEMA_DN			"cn=Subschema"
 	/* dn of the default "monitor" subentry */
 #define SLAPD_MONITOR_DN		"cn=Monitor"
-#define SLAPD_MONITOR_NDN		"CN=MONITOR"
 #if 0
 	/* dn of the default "config" subentry */
 #define SLAPD_CONFIG_DN			"cn=Config"
diff --git a/servers/slapd/back-monitor/Makefile.in b/servers/slapd/back-monitor/Makefile.in
index 5e3ce20328cb7e36c8136502a2591bf169abb724..cd77e57d4186644809ea0f1a98d0c4e015a37578 100644
--- a/servers/slapd/back-monitor/Makefile.in
+++ b/servers/slapd/back-monitor/Makefile.in
@@ -1,12 +1,12 @@
 # $OpenLDAP$
 
-SRCS = init.c search.c compare.c abandon.c \
+SRCS = init.c search.c compare.c abandon.c modify.c bind.c \
 	cache.c entry.c \
-	backend.c database.c thread.c conn.c rww.c \
+	backend.c database.c thread.c conn.c rww.c log.c \
 	dummy.c
-OBJS = init.o search.o compare.o abandon.o \
+OBJS = init.o search.o compare.o abandon.o modify.o bind.o \
 	cache.o entry.o \
-	backend.o database.o thread.o conn.o rww.o \
+	backend.o database.o thread.o conn.o rww.o log.o \
 	dummy.o
 
 LDAP_INCDIR= ../../../include       
diff --git a/servers/slapd/back-monitor/back-monitor.h b/servers/slapd/back-monitor/back-monitor.h
index 73c360a4092ebea45f3e5ca5105b63cb986502d9..97030eef499691b8ba24689a3de6273cc0e39b80 100644
--- a/servers/slapd/back-monitor/back-monitor.h
+++ b/servers/slapd/back-monitor/back-monitor.h
@@ -144,6 +144,13 @@ struct monitorinfo {
 #define SLAPD_MONITOR_WRITEW_DN	\
 	SLAPD_MONITOR_WRITEW_RDN "," SLAPD_MONITOR_DN
 
+#define SLAPD_MONITOR_LOG		9
+#define SLAPD_MONITOR_LOG_NAME		"Log"
+#define SLAPD_MONITOR_LOG_RDN	\
+	"cn=" SLAPD_MONITOR_LOG_NAME
+#define SLAPD_MONITOR_LOG_DN	\
+	SLAPD_MONITOR_LOG_RDN "," SLAPD_MONITOR_DN
+
 struct monitorsubsys {
 	int		mss_type;
 	char		*mss_name;
@@ -155,9 +162,16 @@ struct monitorsubsys {
 #define MONITOR_HAS_VOLATILE_CH( mp ) \
 	( ( mp )->mp_flags & MONITOR_F_VOLATILE_CH )
 
+	/* initialize entry and subentries */
 	int		( *mss_init )( BackendDB * );
+	/* update existing dynamic entry and subentries */
 	int		( *mss_update )( struct monitorinfo *, Entry * );
-	int		( *mss_create )( struct monitorinfo *, const char *ndn, Entry *, Entry ** );
+	/* create new dynamic subentries */
+	int		( *mss_create )( struct monitorinfo *, const char *ndn, 
+				Entry *, Entry ** );
+	/* modify entry and subentries */
+	int		( *mss_modify )( struct monitorinfo *, Entry *, 
+				Modifications *modlist );
 };
 
 extern struct monitorsubsys monitor_subsys[];
@@ -172,7 +186,7 @@ extern int monitor_cache_cmp LDAP_P(( const void *c1, const void *c2 ));
 extern int monitor_cache_dup LDAP_P(( void *c1, void *c2 ));
 extern int monitor_cache_add LDAP_P(( struct monitorinfo *mi, Entry *e ));
 extern int monitor_cache_get LDAP_P(( struct monitorinfo *mi, const char *ndn, Entry **ep ));
-extern int monitor_cache_dn2entry LDAP_P(( struct monitorinfo *mi, const char *ndn, Entry **ep ));
+extern int monitor_cache_dn2entry LDAP_P(( struct monitorinfo *mi, const char *ndn, Entry **ep, Entry **matched ));
 extern int monitor_cache_lock LDAP_P(( Entry *e ));
 extern int monitor_cache_release LDAP_P(( struct monitorinfo *mi, Entry *e ));
 
@@ -182,6 +196,7 @@ extern int monitor_cache_release LDAP_P(( struct monitorinfo *mi, Entry *e ));
 
 extern int monitor_entry_update LDAP_P(( struct monitorinfo *mi, Entry *e ));
 extern int monitor_entry_create LDAP_P(( struct monitorinfo *mi, const char *ndn, Entry *e_parent, Entry **ep ));
+extern int monitor_entry_modify LDAP_P(( struct monitorinfo *mi, Entry *e, Modifications *modlist ));
 
 LDAP_END_DECL
 
diff --git a/servers/slapd/back-monitor/cache.c b/servers/slapd/back-monitor/cache.c
index b794b402334b2ec775c0338812acc444671ffacc..b6fdabe7383fe76b6085ff6a6c11e7e34dcd8078 100644
--- a/servers/slapd/back-monitor/cache.c
+++ b/servers/slapd/back-monitor/cache.c
@@ -174,7 +174,8 @@ int
 monitor_cache_dn2entry(
 		struct monitorinfo      *mi,
 		const char		*ndn,
-		Entry			**ep
+		Entry			**ep,
+		Entry			**matched
 )
 {
 	int rc;
@@ -186,6 +187,9 @@ monitor_cache_dn2entry(
 	assert( mi != NULL );
 	assert( ndn != NULL );
 	assert( ep != NULL );
+	assert( matched != NULL );
+
+	*matched = NULL;
 
 	rc = monitor_cache_get( mi, ndn, ep );
        	if ( !rc && *ep != NULL ) {
@@ -194,7 +198,7 @@ monitor_cache_dn2entry(
 
 	/* try with parent/ancestors */
 	p_ndn = dn_parent( NULL, ndn );
-	rc = monitor_cache_dn2entry( mi, p_ndn, &e_parent );
+	rc = monitor_cache_dn2entry( mi, p_ndn, &e_parent, matched );
 	if ( rc || e_parent == NULL) {
 		return( -1 );
 	}
@@ -205,7 +209,12 @@ monitor_cache_dn2entry(
 		/* parent entry generates volatile children */
 		rc = monitor_entry_create( mi, ndn, e_parent, ep );
 	}
-	monitor_cache_release( mi, e_parent );
+
+	if ( !rc ) {
+		monitor_cache_release( mi, e_parent );
+	} else {
+		*matched = e_parent;
+	}
 	
 	return( rc );
 }
diff --git a/servers/slapd/back-monitor/compare.c b/servers/slapd/back-monitor/compare.c
index f4318c5e946f796a3726980550f1132d87cbfd71..acaf766bcbb6b2d22bcbd9ad5d4927c19a1beb4e 100644
--- a/servers/slapd/back-monitor/compare.c
+++ b/servers/slapd/back-monitor/compare.c
@@ -51,6 +51,55 @@ monitor_back_compare(
 	AttributeAssertion 	*ava
 )
 {
-	return( 0 );
+	struct monitorinfo      *mi = (struct monitorinfo *) be->be_private;	        int             rc;
+	Entry           *e, *matched = NULL;
+	Attribute	*a;
+
+	/* get entry with reader lock */
+	monitor_cache_dn2entry( mi, ndn, &e, &matched );
+	if ( e == NULL ) {
+		send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+				matched ? matched->e_dn : NULL,
+				NULL, NULL, NULL );
+		if ( matched ) {
+			monitor_cache_release( mi, matched );
+		}
+		
+		return( 0 );
+	}
+
+	rc = access_allowed( be, conn, op, e, ava->aa_desc, 
+			ava->aa_value, ACL_COMPARE );
+	if ( !rc ) {
+		send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+				NULL, NULL, NULL, NULL );
+		rc = 1;
+		goto return_results;
+	}
+
+	rc = LDAP_NO_SUCH_ATTRIBUTE;
+	
+	for ( a = attrs_find( e->e_attrs, ava->aa_desc );
+			a != NULL;
+			a = attrs_find( a->a_next, ava->aa_desc )) {
+		rc = LDAP_COMPARE_FALSE;
+		
+		if ( value_find( ava->aa_desc, a->a_vals, ava->aa_value ) == 0 ) {
+									
+			rc = LDAP_COMPARE_TRUE;
+			break;
+		}
+	}
+	
+	send_ldap_result( conn, op, rc, NULL, NULL, NULL, NULL );
+	
+	if( rc != LDAP_NO_SUCH_ATTRIBUTE ) {
+		rc = 0;
+	}
+	
+return_results:;
+	monitor_cache_release( mi, e );
+
+	return( rc );
 }
 
diff --git a/servers/slapd/back-monitor/entry.c b/servers/slapd/back-monitor/entry.c
index 036a6c511cb9d1a6ca5fed261efb907fd7c7d661..a4cdafd0853c1bad8002dd28856a61c94f2a86c6 100644
--- a/servers/slapd/back-monitor/entry.c
+++ b/servers/slapd/back-monitor/entry.c
@@ -85,6 +85,28 @@ monitor_entry_create(
 	return( 0 );
 }
 
+int
+monitor_entry_modify(
+	struct monitorinfo 	*mi, 
+	Entry 			*e,
+	Modifications		*modlist
+)
+{
+	struct monitorentrypriv *mp;
+
+	assert( mi != NULL );
+	assert( e != NULL );
+	assert( e->e_private != NULL );
+
+	mp = ( struct monitorentrypriv * )e->e_private;
+
+	if ( mp->mp_info && mp->mp_info->mss_modify ) {
+		return ( *mp->mp_info->mss_modify )( mi, e, modlist );
+	}
+
+	return( 0 );
+}
+
 int
 monitor_entry_test_flags(
 	struct monitorentrypriv	*mp,
diff --git a/servers/slapd/back-monitor/external.h b/servers/slapd/back-monitor/external.h
index f644744b939f643e1c1e356b2ba1269b1dfeaa40..6cf06e84c23616dc858503e2726b08b3e829bb51 100644
--- a/servers/slapd/back-monitor/external.h
+++ b/servers/slapd/back-monitor/external.h
@@ -63,6 +63,15 @@ extern int	monitor_back_compare LDAP_P(( BackendDB *bd,
 extern int	monitor_back_abandon LDAP_P(( BackendDB *bd,
 	Connection *conn, Operation *op, ber_int_t msgid ));
 
+extern int	monitor_back_modify LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	const char *dn, const char *ndn, Modifications *ml ));
+
+extern int	monitor_back_bind LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	const char *dn, const char *ndn, int method,
+	struct berval *cred, char** edn ));
+
 LDAP_END_DECL
 
 #endif /* _MONITOR_EXTERNAL_H */
diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c
index b7b0c51ea6292c556bc76f92834713faabf5ba8f..5b46dca3026eaba9081698b3e2c7b28f2fe80890 100644
--- a/servers/slapd/back-monitor/init.c
+++ b/servers/slapd/back-monitor/init.c
@@ -61,63 +61,80 @@ struct monitorsubsys monitor_subsys[] = {
 		MONITOR_F_NONE,
 		NULL,	/* init */
 		NULL,	/* update */
-		NULL	/* create */
+		NULL,	/* create */
+		NULL	/* modify */
        	}, { 
 		SLAPD_MONITOR_DATABASE, SLAPD_MONITOR_DATABASE_NAME, 	
 		NULL, NULL, NULL,
 		MONITOR_F_PERSISTENT_CH,
 		monitor_subsys_database_init,
 		NULL,   /* update */
-		NULL    /* create */
+		NULL,   /* create */
+		NULL	/* modify */
        	}, { 
 		SLAPD_MONITOR_BACKEND, SLAPD_MONITOR_BACKEND_NAME, 
 		NULL, NULL, NULL,
 		MONITOR_F_PERSISTENT_CH,
 		monitor_subsys_backend_init,
 		NULL,   /* update */
-		NULL    /* create */
+		NULL,   /* create */
+		NULL	/* modify */
        	}, { 
 		SLAPD_MONITOR_THREAD, SLAPD_MONITOR_THREAD_NAME, 	
 		NULL, NULL, NULL,
 		MONITOR_F_NONE,
-		NULL,   /* init */
+		monitor_subsys_thread_init,
 		monitor_subsys_thread_update,
-		NULL    /* create */
+		NULL,   /* create */
+		NULL	/* modify */
        	}, { 
 		SLAPD_MONITOR_SASL, SLAPD_MONITOR_SASL_NAME, 	
 		NULL, NULL, NULL,
 		MONITOR_F_NONE,
 		NULL,   /* init */
 		NULL,   /* update */
-		NULL    /* create */
+		NULL,   /* create */
+		NULL	/* modify */
        	}, { 
 		SLAPD_MONITOR_TLS, SLAPD_MONITOR_TLS_NAME,
 		NULL, NULL, NULL,
 		MONITOR_F_NONE,
 		NULL,   /* init */
 		NULL,   /* update */
-		NULL    /* create */
+		NULL,   /* create */
+		NULL	/* modify */
        	}, { 
 		SLAPD_MONITOR_CONN, SLAPD_MONITOR_CONN_NAME,
 		NULL, NULL, NULL,
 		MONITOR_F_VOLATILE_CH,
 		monitor_subsys_conn_init,
 		monitor_subsys_conn_update,
-		monitor_subsys_conn_create
+		monitor_subsys_conn_create,
+		NULL	/* modify */
        	}, { 
 		SLAPD_MONITOR_READW, SLAPD_MONITOR_READW_NAME,
 		NULL, NULL, NULL,
 		MONITOR_F_NONE,
 		NULL,	/* init */
 		monitor_subsys_readw_update,
-		NULL    /* create */
+		NULL, 	/* create */
+		NULL	/* modify */
        	}, { 
 		SLAPD_MONITOR_WRITEW, SLAPD_MONITOR_WRITEW_NAME,
 		NULL, NULL, NULL,
 		MONITOR_F_NONE,
 		NULL,   /* init */
 		monitor_subsys_writew_update,
-		NULL    /* create */
+		NULL,   /* create */
+		NULL	/* modify */
+       	}, { 
+		SLAPD_MONITOR_LOG, SLAPD_MONITOR_LOG_NAME,
+		NULL, NULL, NULL,
+		MONITOR_F_NONE,
+		monitor_subsys_log_init,
+		NULL,	/* update */
+		NULL,   /* create */
+		monitor_subsys_log_modify
 	}, { -1, NULL }
 };
 
@@ -145,11 +162,11 @@ monitor_back_initialize(
 	bi->bi_db_close = NULL;
 	bi->bi_db_destroy = monitor_back_db_destroy;
 
-	bi->bi_op_bind = NULL;
+	bi->bi_op_bind = monitor_back_bind;
 	bi->bi_op_unbind = NULL;
 	bi->bi_op_search = monitor_back_search;
 	bi->bi_op_compare = monitor_back_compare;
-	bi->bi_op_modify = NULL;
+	bi->bi_op_modify = monitor_back_modify;
 	bi->bi_op_modrdn = NULL;
 	bi->bi_op_add = NULL;
 	bi->bi_op_delete = NULL;
@@ -189,7 +206,7 @@ monitor_back_db_init(
 	Entry 			*e, *e_tmp;
 	struct monitorentrypriv	*mp;
 	int			i;
-	char 			buf[1024];
+	char 			buf[1024], *ndn;
 	const char 		*text;
 
 	if ( monitor_defined ) {
@@ -205,8 +222,11 @@ monitor_back_db_init(
 	}
 	monitor_defined++;
 
-	charray_add( &be->be_suffix, SLAPD_MONITOR_DN );
-	ber_bvecadd( &be->be_nsuffix, ber_bvstr( SLAPD_MONITOR_NDN ));
+	ndn = ch_strdup( SLAPD_MONITOR_DN );
+	charray_add( &be->be_suffix, ndn );
+	dn_normalize( ndn );
+	ber_bvecadd( &be->be_nsuffix, ber_bvstr( ndn ) );
+	ch_free( ndn );
 
 	mi = ( struct monitorinfo * )ch_calloc( sizeof( struct monitorinfo ), 1 );
 	ldap_pvt_thread_mutex_init( &mi->mi_cache_mutex );
@@ -358,11 +378,15 @@ monitor_back_open(
 {
 	BackendDB		*be;
 	struct monitorsubsys	*ms;
+	char			*ndn;
 
 	/*
 	 * adds the monitor backend
 	 */
-	be = select_backend( SLAPD_MONITOR_NDN, 0 );
+	ndn = ch_strdup( SLAPD_MONITOR_DN );
+	dn_normalize( ndn );
+	be = select_backend( ndn , 0 );
+	ch_free( ndn );
 	if ( be == NULL ) {
 #ifdef NEW_LOGGING
 		LDAP_LOG(( "operation", LDAP_LEVEL_CRIT,
diff --git a/servers/slapd/back-monitor/log.c b/servers/slapd/back-monitor/log.c
new file mode 100644
index 0000000000000000000000000000000000000000..f1e6835392e3307a1d32405c9cb106f86dd80faa
--- /dev/null
+++ b/servers/slapd/back-monitor/log.c
@@ -0,0 +1,500 @@
+/* log.c - deal with log subsystem */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ * Copyright 2001 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ * 
+ * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
+ * 
+ * This work has beed deveolped for the OpenLDAP Foundation 
+ * in the hope that it may be useful to the Open Source community, 
+ * but WITHOUT ANY WARRANTY.
+ * 
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ * 
+ * 1. The author and SysNet s.n.c. are not responsible for the consequences
+ *    of use of this software, no matter how awful, even if they arise from
+ *    flaws in it.
+ * 
+ * 2. The origin of this software must not be misrepresented, either by
+ *    explicit claim or by omission.  Since few users ever read sources,
+ *    credits should appear in the documentation.
+ * 
+ * 3. Altered versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.  Since few users
+ *    ever read sources, credits should appear in the documentation.
+ *    SysNet s.n.c. cannot be responsible for the consequences of the
+ *    alterations.
+ * 
+ * 4. This notice may not be removed or altered.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+
+#include "slap.h"
+#include "lutil.h"
+#include "ldif.h"
+#include "back-monitor.h"
+
+/*
+ * log mutex
+ */
+ldap_pvt_thread_mutex_t		monitor_log_mutex;
+
+static struct {
+	int i;
+	const char *s;
+} int_2_level[] = {
+	{ LDAP_DEBUG_TRACE,	"Trace" },
+	{ LDAP_DEBUG_PACKETS,	"Packets" },
+	{ LDAP_DEBUG_ARGS,	"Args" },
+	{ LDAP_DEBUG_CONNS,	"Conns" },
+	{ LDAP_DEBUG_BER,	"BER" },
+	{ LDAP_DEBUG_FILTER,	"Filter" },
+	{ LDAP_DEBUG_CONFIG,	"Config" },	/* useless */
+	{ LDAP_DEBUG_ACL,	"ACL" },
+	{ LDAP_DEBUG_STATS,	"Stats" },
+	{ LDAP_DEBUG_STATS2,	"Stats2" },
+	{ LDAP_DEBUG_SHELL,	"Shell" },
+	{ LDAP_DEBUG_PARSE,	"Parse" },
+	{ LDAP_DEBUG_CACHE,	"Cache" },
+	{ LDAP_DEBUG_INDEX,	"Index" },
+	{ 0,			NULL }
+};
+
+static int loglevel2int( const char *str );
+static const char * int2loglevel( int n );
+
+static int add_values( Entry *e, Modification *mod, int *newlevel );
+static int delete_values( Entry *e, Modification *mod, int *newlevel );
+static int replace_values( Entry *e, Modification *mod, int *newlevel );
+
+/*
+ * initializes log subentry
+ */
+int
+monitor_subsys_log_init(
+	BackendDB	*be
+)
+{
+	struct monitorinfo	*mi;
+	Entry			*e;
+	int			i;
+	struct monitorentrypriv	*mp;
+	struct berval 		val, *bv[2] = { &val, NULL };
+
+	ldap_pvt_thread_mutex_init( &monitor_log_mutex );
+
+	mi = ( struct monitorinfo * )be->be_private;
+
+	if ( monitor_cache_get( mi, monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn, 
+				&e ) ) {
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_CRIT,
+			"monitor_subsys_log_init: "
+			"unable to get entry '%s'\n",
+			monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn ));
+#else
+		Debug( LDAP_DEBUG_ANY,
+			"monitor_subsys_log_init: "
+			"unable to get entry '%s'\n%s%s",
+			monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn, 
+			"", "" );
+#endif
+		return( -1 );
+	}
+
+	/* initialize the debug level */
+	for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
+		if ( int_2_level[ i ].i & ldap_syslog ) {
+			val.bv_val = ( char * )int_2_level[ i ].s;
+			val.bv_len = strlen( val.bv_val );
+
+			attr_merge( e, monitor_ad_desc, bv );
+		}
+	}
+
+	monitor_cache_release( mi, e );
+
+	return( 0 );
+}
+
+int 
+monitor_subsys_log_modify( 
+	struct monitorinfo 	*mi,
+	Entry 			*e,
+	Modifications		*modlist
+)
+{
+	int		rc = LDAP_OTHER;
+	int		newlevel = ldap_syslog;
+	Attribute	*save_attrs;
+	Modifications	*ml;
+
+	ldap_pvt_thread_mutex_lock( &monitor_log_mutex );
+
+	save_attrs = e->e_attrs;
+	e->e_attrs = attrs_dup( e->e_attrs );
+
+	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
+		Modification	*mod = &ml->sml_mod;
+
+		/*
+		 * Operational attributes
+		 */
+#if 0
+		if ( mod->sm_desc == slap_schema.si_ad_modifyTimestamp 
+			|| mod->sm_desc == slap_schema.si_ad_modifiersName ) {
+			( void ) attr_delete( &e->e_attrs, mod->sm_desc );
+			rc = attr_merge( e, mod->sm_desc, mod->sm_bvalues );
+			if ( rc != 0 ) {
+				rc = LDAP_OTHER;
+				break;
+			}
+			continue;
+
+		/*
+		 * unhandled operational attributes
+		 */
+		} else if ( is_at_operational( mod->sm_desc->ad_type ) ) {
+			continue;
+
+#else
+		if ( is_at_operational( mod->sm_desc->ad_type ) ) {
+			( void ) attr_delete( &e->e_attrs, mod->sm_desc );
+			rc = attr_merge( e, mod->sm_desc, mod->sm_bvalues );
+			if ( rc != 0 ) {
+				rc = LDAP_OTHER;
+				break;
+			}
+			continue;
+
+#endif
+		/*
+		 * only the monitor description attribute can be modified
+		 */
+		} else if ( mod->sm_desc != monitor_ad_desc ) {
+			rc = LDAP_UNWILLING_TO_PERFORM;
+			break;
+		}
+
+		switch ( mod->sm_op ) {
+		case LDAP_MOD_ADD:
+			rc = add_values( e, mod, &newlevel );
+			break;
+			
+		case LDAP_MOD_DELETE:
+			rc = delete_values( e, mod, &newlevel );
+			break;
+
+		case LDAP_MOD_REPLACE:
+			rc = replace_values( e, mod, &newlevel );
+			break;
+
+		default:
+			rc = LDAP_OPERATIONS_ERROR;
+			break;
+		}
+
+		if ( rc != LDAP_SUCCESS ) {
+			break;
+		}
+	}
+
+	/* set the new debug level */
+	if ( rc == LDAP_SUCCESS ) {
+		const char *text;
+		static char textbuf[1024];
+
+#if 0 	/* need op */
+		/* check for abandon */
+		ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+		if ( op->o_abandon ) {
+			ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+			rc = SLAPD_ABANDON;
+
+			goto cleanup;
+		}
+#endif
+
+		/* check that the entry still obeys the schema */
+		rc = entry_schema_check( e, save_attrs, &text, textbuf, 
+				sizeof( textbuf ) );
+		if ( rc != LDAP_SUCCESS ) {
+			goto cleanup;
+		}
+
+		ldap_syslog = newlevel;
+
+#if 0
+		slap_debug = newlevel;
+		lutil_set_debug_level( "slapd", slap_debug );
+		ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
+		ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
+		ldif_debug = slap_debug;
+#endif
+	}
+
+cleanup:;
+	if ( rc == LDAP_SUCCESS ) {
+		attrs_free( save_attrs );
+
+	} else {
+		attrs_free( e->e_attrs );
+		e->e_attrs = save_attrs;
+	}
+	
+	ldap_pvt_thread_mutex_unlock( &monitor_log_mutex );
+
+	return( rc );
+}
+
+static int
+loglevel2int( const char *str )
+{
+	int		i;
+	
+	for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
+		if ( strcasecmp( str, int_2_level[ i ].s ) == 0 ) {
+			return int_2_level[ i ].i;
+		}
+	}
+
+	return 0;
+}
+
+static const char *
+int2loglevel( int n )
+{
+	int		i;
+	
+	for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
+		if ( int_2_level[ i ].i == n ) {
+			return int_2_level[ i ].s;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+check_constraints( Modification *mod, int *newlevel )
+{
+	int		i;
+
+	for ( i = 0; mod->sm_bvalues && mod->sm_bvalues[i] != NULL; i++ ) {
+		int len, l;
+		const char *s;
+		
+		l = loglevel2int( mod->sm_bvalues[i]->bv_val );
+		if ( !l ) {
+			return LDAP_CONSTRAINT_VIOLATION;
+		}
+
+		s = int2loglevel( l );
+		len = strlen( s );
+		assert( len == mod->sm_bvalues[i]->bv_len );
+		
+		AC_MEMCPY( mod->sm_bvalues[i]->bv_val, s, len );
+
+		*newlevel |= l;
+	}
+
+	return LDAP_SUCCESS;
+}	
+
+static int 
+add_values( Entry *e, Modification *mod, int *newlevel )
+{
+	Attribute	*a;
+	int		i, rc;
+	MatchingRule 	*mr = mod->sm_desc->ad_type->sat_equality;
+
+	rc = check_constraints( mod, newlevel );
+	if ( rc != LDAP_SUCCESS ) {
+		return rc;
+	}
+
+	a = attr_find( e->e_attrs, mod->sm_desc );
+
+	if ( a != NULL ) {
+		
+		/* "description" SHOULD have appropriate rules ... */
+		if ( mr == NULL || !mr->smr_match ) {
+			return LDAP_INAPPROPRIATE_MATCHING;
+		}
+
+		for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
+			int rc;
+			int j;
+			const char *text = NULL;
+			struct berval *asserted;
+
+			rc = value_normalize( mod->sm_desc,
+					SLAP_MR_EQUALITY,
+					mod->sm_bvalues[i],
+					&asserted,
+					&text );
+
+			if ( rc != LDAP_SUCCESS ) {
+				return rc;
+			}
+
+			for ( j = 0; a->a_vals[j] != NULL; j++ ) {
+				int match;
+				int rc = value_match( &match, mod->sm_desc, mr,
+						SLAP_MR_VALUE_SYNTAX_MATCH,
+						a->a_vals[j], asserted, &text );
+
+				if ( rc == LDAP_SUCCESS && match == 0 ) {
+					ber_bvfree( asserted );
+					return LDAP_TYPE_OR_VALUE_EXISTS;
+				}
+			}
+
+			ber_bvfree( asserted );
+		}
+	}
+
+	/* no - add them */
+	if ( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
+		/* this should return result return of attr_merge */
+		return LDAP_OTHER;
+	}
+
+	return LDAP_SUCCESS;
+}
+
+static int
+delete_values( Entry *e, Modification *mod, int *newlevel )
+{
+	int             i, j, k, found, rc, nl = 0;
+	Attribute       *a;
+	char *desc = mod->sm_desc->ad_cname.bv_val;
+	MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
+
+	rc = check_constraints( mod, &nl );
+	if ( rc != LDAP_SUCCESS ) {
+		return rc;
+	}
+
+	*newlevel &= ~nl;
+
+	/* delete the entire attribute */
+	if ( mod->sm_bvalues == NULL ) {
+		int rc = attr_delete( &e->e_attrs, mod->sm_desc );
+
+		if ( rc ) {
+			rc = LDAP_NO_SUCH_ATTRIBUTE;
+		} else {
+			*newlevel = 0;
+			rc = LDAP_SUCCESS;
+		}
+		return rc;
+	}
+
+	if ( mr == NULL || !mr->smr_match ) {
+		/* disallow specific attributes from being deleted if
+		 * no equality rule */
+		return LDAP_INAPPROPRIATE_MATCHING;
+	}
+
+	/* delete specific values - find the attribute first */
+	if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
+		return( LDAP_NO_SUCH_ATTRIBUTE );
+	}
+
+	/* find each value to delete */
+	for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
+		int rc;
+		const char *text = NULL;
+
+		struct berval *asserted;
+
+		rc = value_normalize( mod->sm_desc,
+				SLAP_MR_EQUALITY,
+				mod->sm_bvalues[i],
+				&asserted,
+				&text );
+
+		if( rc != LDAP_SUCCESS ) return rc;
+
+		found = 0;
+		for ( j = 0; a->a_vals[j] != NULL; j++ ) {
+			int match;
+			int rc = value_match( &match, mod->sm_desc, mr,
+					SLAP_MR_VALUE_SYNTAX_MATCH,
+					a->a_vals[j], asserted, &text );
+
+			if( rc == LDAP_SUCCESS && match != 0 ) {
+				continue;
+			}
+
+			/* found a matching value */
+			found = 1;
+
+			/* delete it */
+			ber_bvfree( a->a_vals[j] );
+			for ( k = j + 1; a->a_vals[k] != NULL; k++ ) {
+				a->a_vals[k - 1] = a->a_vals[k];
+			}
+			a->a_vals[k - 1] = NULL;
+
+			break;
+		}
+
+		ber_bvfree( asserted );
+
+		/* looked through them all w/o finding it */
+		if ( ! found ) {
+			return LDAP_NO_SUCH_ATTRIBUTE;
+		}
+	}
+
+	/* if no values remain, delete the entire attribute */
+	if ( a->a_vals[0] == NULL ) {
+		/* should already be zero */
+		*newlevel = 0;
+		
+		if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
+			return LDAP_NO_SUCH_ATTRIBUTE;
+		}
+	}
+
+	return LDAP_SUCCESS;
+}
+
+static int
+replace_values( Entry *e, Modification *mod, int *newlevel )
+{
+	int i, rc;
+
+	*newlevel = 0;
+	rc = check_constraints( mod, newlevel );
+	if ( rc != LDAP_SUCCESS ) {
+		return rc;
+	}
+
+	rc = attr_delete( &e->e_attrs, mod->sm_desc );
+
+	if ( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
+		return rc;
+	}
+
+	if ( mod->sm_bvalues != NULL &&
+		attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
+		return LDAP_OTHER;
+	}
+
+	return LDAP_SUCCESS;
+}
+
diff --git a/servers/slapd/back-monitor/proto-back-monitor.h b/servers/slapd/back-monitor/proto-back-monitor.h
index d0de827fca9d710a99b4e669c3d4e5cec3811f63..ca16fd5a59a3478ac3273339c90667680e22adb6 100644
--- a/servers/slapd/back-monitor/proto-back-monitor.h
+++ b/servers/slapd/back-monitor/proto-back-monitor.h
@@ -60,6 +60,7 @@ int monitor_subsys_database_init LDAP_P(( BackendDB *be ));
 /*
  * threads
  */
+int monitor_subsys_thread_init LDAP_P(( BackendDB *be ));
 int monitor_subsys_thread_update LDAP_P(( struct monitorinfo *mi, Entry *e ));
 
 /*
@@ -79,5 +80,11 @@ int monitor_subsys_readw_update LDAP_P(( struct monitorinfo *mi, Entry *e ));
  */
 int monitor_subsys_writew_update LDAP_P(( struct monitorinfo *mi, Entry *e ));
 
+/*
+ * log
+ */
+int monitor_subsys_log_init LDAP_P(( BackendDB *be ));
+int monitor_subsys_log_modify LDAP_P(( struct monitorinfo *mi, Entry *e, Modifications *modlist	));
+
 LDAP_END_DECL
 #endif
diff --git a/servers/slapd/back-monitor/search.c b/servers/slapd/back-monitor/search.c
index 27b9fb5efc6b1b2d86ff1d8a6a3aae17395b2b61..64f3b95e6d4f59beeb3fcb7a525851d85149ada9 100644
--- a/servers/slapd/back-monitor/search.c
+++ b/servers/slapd/back-monitor/search.c
@@ -127,7 +127,7 @@ monitor_back_search(
 {
 	struct monitorinfo	*mi = (struct monitorinfo *) be->be_private;
 	int		rc;
-	Entry		*e;
+	Entry		*e, *matched = NULL;
 	int		nentries = 0;
 
 #ifdef NEW_LOGGING
@@ -139,10 +139,14 @@ monitor_back_search(
 
 
 	/* get entry with reader lock */
-	monitor_cache_dn2entry( mi, nbase, &e );
+	monitor_cache_dn2entry( mi, nbase, &e, &matched );
 	if ( e == NULL ) {
 		send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
-			NULL, NULL, NULL, NULL );
+			matched ? matched->e_dn : NULL, 
+			NULL, NULL, NULL );
+		if ( matched ) {
+			monitor_cache_release( mi, matched );
+		}
 
 		return( 0 );
 	}
diff --git a/servers/slapd/back-monitor/thread.c b/servers/slapd/back-monitor/thread.c
index 04b3fb6b6cd1cd74c0ca6b63760751af801513cc..b1e05f29d6de1dce20d2c9ae0f72bb8bf37b94d0 100644
--- a/servers/slapd/back-monitor/thread.c
+++ b/servers/slapd/back-monitor/thread.c
@@ -41,6 +41,52 @@
 #include "slap.h"
 #include "back-monitor.h"
 
+/*
+*  * initializes log subentry
+*   */
+int
+monitor_subsys_thread_init(
+	BackendDB       *be
+)
+{
+	struct monitorinfo      *mi;
+	Entry                   *e;
+	struct monitorentrypriv *mp;
+	struct berval           val, *bv[2] = { &val, NULL };
+	static char		buf[1024];
+
+	mi = ( struct monitorinfo * )be->be_private;
+
+	if ( monitor_cache_get( mi, 
+				monitor_subsys[SLAPD_MONITOR_THREAD].mss_ndn,
+				&e ) ) {
+#ifdef NEW_LOGGING
+		LDAP_LOG(( "operation", LDAP_LEVEL_CRIT,
+					"monitor_subsys_thread_init: "
+					"unable to get entry '%s'\n",
+					monitor_subsys[SLAPD_MONITOR_THREAD].mss_ndn ));
+#else
+		Debug( LDAP_DEBUG_ANY,
+				"monitor_subsys_thread_init: "
+				"unable to get entry '%s'\n%s%s",
+				monitor_subsys[SLAPD_MONITOR_THREAD].mss_ndn,
+				"", "" );
+#endif
+		return( -1 );
+	}
+
+	/* initialize the thread number */
+	snprintf( buf, sizeof( buf ), "max=%d", connection_pool_max );
+
+	val.bv_val = buf;
+	val.bv_len = strlen( val.bv_val );
+
+	attr_merge( e, monitor_ad_desc, bv );
+
+	monitor_cache_release( mi, e );
+
+	return( 0 );
+}
 
 int 
 monitor_subsys_thread_update( 
@@ -55,15 +101,15 @@ monitor_subsys_thread_update(
 	bv[0] = &val;
 	bv[1] = NULL;
 
-	snprintf( buf, sizeof( buf ), "threads=%d", 
+	snprintf( buf, sizeof( buf ), "backload=%d", 
 			ldap_pvt_thread_pool_backload( &connection_pool ) );
 
 	if ( ( a = attr_find( e->e_attrs, monitor_ad_desc ) ) != NULL ) {
 
 		for ( b = a->a_vals; b[0] != NULL; b++ ) {
-			if ( strncmp( b[0]->bv_val, "threads=", 
-					sizeof( "threads=" ) - 1 ) == 0 ) {
-				free( b[0]->bv_val );
+			if ( strncmp( b[0]->bv_val, "backload=", 
+					sizeof( "backload=" ) - 1 ) == 0 ) {
+				ber_bvfree( b[0] );
 				b[0] = ber_bvstrdup( buf );
 				break;
 			}
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index 5bf2a78ec9a7d6b48f13b0c0b0ae51ad25868e9f..20386a9afe577a6a012b0969c5cbc2b1cee65fc2 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -446,6 +446,9 @@ read_config( const char *fname )
 
 			ldap_pvt_thread_pool_maxthreads( &connection_pool, c );
 
+			/* save for later use */
+			connection_pool_max = c;
+
 		/* get pid file name */
 		} else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
 			if ( cargc < 2 ) {
diff --git a/servers/slapd/init.c b/servers/slapd/init.c
index 508650b36b22251f0b4ac29de40dc962790fdd67..c26fe7b8c0bbfe4deee90b75540562f5453230df 100644
--- a/servers/slapd/init.c
+++ b/servers/slapd/init.c
@@ -39,6 +39,7 @@ char		**g_argv;
  * global variables that need mutex protection
  */
 ldap_pvt_thread_pool_t	connection_pool;
+int			connection_pool_max = SLAP_MAX_WORKER_THREADS;
 ldap_pvt_thread_mutex_t	gmtime_mutex;
 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
 ldap_pvt_thread_mutex_t	passwd_mutex;
@@ -106,7 +107,7 @@ slap_init( int mode, const char *name )
 	
 			(void) ldap_pvt_thread_initialize();
 
-			ldap_pvt_thread_pool_init(&connection_pool, SLAP_MAX_WORKER_THREADS, 0);
+			ldap_pvt_thread_pool_init(&connection_pool, connection_pool_max, 0);
 
 			ldap_pvt_thread_mutex_init( &entry2str_mutex );
 			ldap_pvt_thread_mutex_init( &replog_mutex );
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 7df651706b521cc697b5fe88dbc25bfaf9971944..0b4b737c2e1e52180067478c9a20776309ae6e21 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -921,6 +921,7 @@ LDAP_SLAPD_V (time_t)		starttime;
 #define slap_get_time()	time( NULL )
 
 LDAP_SLAPD_V (ldap_pvt_thread_pool_t)	connection_pool;
+LDAP_SLAPD_V (int)			connection_pool_max;
 
 LDAP_SLAPD_V (ldap_pvt_thread_mutex_t)	entry2str_mutex;
 LDAP_SLAPD_V (ldap_pvt_thread_mutex_t)	replog_mutex;