From: Pierangelo Masarati Date: Mon, 10 Dec 2001 09:50:06 +0000 (+0000) Subject: improvements to monitor backend: added a log entry that lists the current log level... X-Git-Tag: LDBM_PRE_GIANT_RWLOCK~677 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=95f1740aa6bad5df15552a05c7a1d78ba62d0995;p=openldap improvements to monitor backend: added a log entry that lists the current log level and can be modified via protocol at runtime, to change the log level; minor improvements; fixed a problem in dealing with dn normalization --- diff --git a/include/ldap_defaults.h b/include/ldap_defaults.h index 9d77e75253..c8cbcf2ef2 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 5e3ce20328..cd77e57d41 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 73c360a409..97030eef49 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 b794b40233..b6fdabe738 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 f4318c5e94..acaf766bcb 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 036a6c511c..a4cdafd085 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 f644744b93..6cf06e84c2 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 b7b0c51ea6..5b46dca302 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 0000000000..f1e6835392 --- /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. + * + * 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 + +#include + +#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 d0de827fca..ca16fd5a59 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 27b9fb5efc..64f3b95e6d 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 04b3fb6b6c..b1e05f29d6 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 5bf2a78ec9..20386a9afe 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 508650b36b..c26fe7b8c0 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 7df651706b..0b4b737c2e 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;