From: Nadezhda Ivanova Date: Tue, 13 Apr 2021 12:12:34 +0000 (+0300) Subject: Enable addition of targets to back-asyncmeta via cn=config X-Git-Tag: OPENLDAP_REL_ENG_2_6_0~151 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6463280d8cbfcbcd67ea25501820fbde877e3685;p=thirdparty%2Fopenldap.git Enable addition of targets to back-asyncmeta via cn=config --- diff --git a/servers/slapd/back-asyncmeta/add.c b/servers/slapd/back-asyncmeta/add.c index f672467e8b..eb606ad4ce 100644 --- a/servers/slapd/back-asyncmeta/add.c +++ b/servers/slapd/back-asyncmeta/add.c @@ -255,6 +255,13 @@ asyncmeta_back_add( Operation *op, SlapReply *rs ) op->o_log_prefix, op->o_time, current_time ); } + if ( mi->mi_ntargets == 0 ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "No targets are configured for this database"; + send_ldap_result(op, rs); + return rs->sr_err; + } + asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi ); if (bc == NULL) { rs->sr_err = LDAP_OTHER; diff --git a/servers/slapd/back-asyncmeta/back-asyncmeta.h b/servers/slapd/back-asyncmeta/back-asyncmeta.h index bae9be3edb..fcc0d69b25 100644 --- a/servers/slapd/back-asyncmeta/back-asyncmeta.h +++ b/servers/slapd/back-asyncmeta/back-asyncmeta.h @@ -771,6 +771,12 @@ asyncmeta_return_bind_errors(a_metaconn_t *mc, void *ctx, int dolock); +int +asyncmeta_db_has_pending_ops(a_metainfo_t *mi); + +int +asyncmeta_db_has_mscs(a_metainfo_t *mi); + /* The the maximum time in seconds after a result has been received on a connection, * after which it can be reset if a sender error occurs. Should this be configurable? */ #define META_BACK_RESULT_INTERVAL (2) diff --git a/servers/slapd/back-asyncmeta/bind.c b/servers/slapd/back-asyncmeta/bind.c index 739fbf7b63..261384545e 100644 --- a/servers/slapd/back-asyncmeta/bind.c +++ b/servers/slapd/back-asyncmeta/bind.c @@ -65,9 +65,8 @@ asyncmeta_back_bind( Operation *op, SlapReply *rs ) gotit = 0, isroot = 0; - SlapReply *candidates; + SlapReply *candidates = NULL; - candidates = op->o_tmpcalloc(mi->mi_ntargets, sizeof(SlapReply),op->o_tmpmemctx); rs->sr_err = LDAP_SUCCESS; Debug( LDAP_DEBUG_ARGS, "%s asyncmeta_back_bind: dn=\"%s\".\n", @@ -92,6 +91,16 @@ asyncmeta_back_bind( Operation *op, SlapReply *rs ) return rs->sr_err; } + + if ( mi->mi_ntargets == 0 ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "No targets are configured for this database"; + send_ldap_result(op, rs); + return rs->sr_err; + } + + candidates = op->o_tmpcalloc(mi->mi_ntargets, sizeof(SlapReply),op->o_tmpmemctx); + /* we need asyncmeta_getconn() not send result even on error, * because we want to intercept the error and make it * invalidCredentials */ diff --git a/servers/slapd/back-asyncmeta/compare.c b/servers/slapd/back-asyncmeta/compare.c index 6448197ff3..f59690eec3 100644 --- a/servers/slapd/back-asyncmeta/compare.c +++ b/servers/slapd/back-asyncmeta/compare.c @@ -197,6 +197,14 @@ asyncmeta_back_compare( Operation *op, SlapReply *rs ) Debug( asyncmeta_debug, "==> asyncmeta_back_compare[%s]: o_time:[%ld], current time: [%ld]\n", op->o_log_prefix, op->o_time, current_time ); } + + if ( mi->mi_ntargets == 0 ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "No targets are configured for this database"; + send_ldap_result(op, rs); + return rs->sr_err; + } + asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi ); if (bc == NULL) { rs->sr_err = LDAP_OTHER; diff --git a/servers/slapd/back-asyncmeta/config.c b/servers/slapd/back-asyncmeta/config.c index 05ec953655..aabac8abd5 100644 --- a/servers/slapd/back-asyncmeta/config.c +++ b/servers/slapd/back-asyncmeta/config.c @@ -456,11 +456,21 @@ static ConfigOCs a_metaocs[] = { static int asyncmeta_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *c ) { + a_metainfo_t *mi; + if ( p->ce_type != Cft_Database || !p->ce_be || p->ce_be->be_cf_ocs != a_metaocs ) return LDAP_CONSTRAINT_VIOLATION; c->be = p->ce_be; + mi = ( a_metainfo_t * )c->be->be_private; + + if ( asyncmeta_db_has_pending_ops ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify a working database" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + return 1; + } return LDAP_SUCCESS; } @@ -486,12 +496,15 @@ asyncmeta_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *c ) static int asyncmeta_back_new_target( - a_metatarget_t **mtp ) + a_metatarget_t **mtp, + a_metainfo_t *mi ) { a_metatarget_t *mt; *mtp = NULL; + int i; + assert ( mi != NULL ); mt = ch_calloc( sizeof( a_metatarget_t ), 1 ); ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex ); @@ -504,6 +517,18 @@ asyncmeta_back_new_target( *mtp = mt; + for ( i = 0; i < mi->mi_num_conns; i++ ) { + a_metaconn_t *mc = &mi->mi_conns[i]; + mc->mc_conns = ch_realloc( mc->mc_conns, sizeof( a_metasingleconn_t ) * mi->mi_ntargets); + memset( &(mc->mc_conns[mi->mi_ntargets-1]), 0, sizeof( a_metasingleconn_t ) ); + } + /* If this is the first target, start the timeout loop */ + if ( mi->mi_ntargets == 1 ) { + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); + mi->mi_task = ldap_pvt_runqueue_insert( &slapd_rq, 1, + asyncmeta_timeout_loop, mi, "asyncmeta_timeout_loop", mi->mi_suffix.bv_val ); + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + } return 0; } @@ -1026,6 +1051,13 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) } } + if ( c->op != SLAP_CONFIG_EMIT && asyncmeta_db_has_pending_ops ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify a working database" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + return 1; + } + if ( c->op == SLAP_CONFIG_EMIT ) { struct berval bv = BER_BVNULL; @@ -1520,6 +1552,7 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { + switch( c->type ) { /* Base attrs */ case LDAP_BACK_CFG_DNCACHE_TTL: @@ -1544,8 +1577,15 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) /* common attrs */ case LDAP_BACK_CFG_BIND_TIMEOUT: - mc->mc_bind_timeout.tv_sec = 0; - mc->mc_bind_timeout.tv_usec = 0; + if ( asyncmeta_db_has_mscs ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify this attribute if there are established target connections" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; + } else { + mc->mc_bind_timeout.tv_sec = 0; + mc->mc_bind_timeout.tv_usec = 0; + } break; case LDAP_BACK_CFG_CANCEL: @@ -1567,7 +1607,14 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) break; case LDAP_BACK_CFG_NETWORK_TIMEOUT: - mc->mc_network_timeout = 0; + if ( asyncmeta_db_has_mscs ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify this attribute if there are established target connections" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; + } else { + mc->mc_network_timeout = 0; + } break; case LDAP_BACK_CFG_NOREFS: @@ -1604,7 +1651,14 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) break; case LDAP_BACK_CFG_VERSION: - mc->mc_version = 0; + if ( asyncmeta_db_has_mscs ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify this attribute if there are established target connections" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; + } else { + mc->mc_version = 0; + } break; #ifdef SLAP_CONTROL_X_SESSION_TRACKING @@ -1625,9 +1679,16 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) /* target attrs */ case LDAP_BACK_CFG_URI: - if ( mt->mt_uri ) { - ch_free( mt->mt_uri ); - mt->mt_uri = NULL; + if ( asyncmeta_db_has_mscs ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify this attribute if there are established target connections" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; + } else { + if ( mt->mt_uri ) { + ch_free( mt->mt_uri ); + mt->mt_uri = NULL; + } } /* FIXME: should have a way to close all cached * connections associated with this target. @@ -1638,44 +1699,66 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) BerVarray *bvp; bvp = &mt->mt_idassert_authz; - if ( c->valx < 0 ) { - if ( *bvp != NULL ) { - ber_bvarray_free( *bvp ); - *bvp = NULL; - } - + if ( asyncmeta_db_has_mscs ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify this attribute if there are established target connections" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; } else { - if ( *bvp == NULL ) { - rc = 1; - break; - } + if ( c->valx < 0 ) { + if ( *bvp != NULL ) { + ber_bvarray_free( *bvp ); + *bvp = NULL; + } - for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) - ; + } else { + if ( *bvp == NULL ) { + rc = 1; + break; + } - if ( i >= c->valx ) { - rc = 1; - break; - } - ber_memfree( ((*bvp)[ c->valx ]).bv_val ); - for ( i = c->valx; !BER_BVISNULL( &((*bvp)[ i + 1 ]) ); i++ ) { - (*bvp)[ i ] = (*bvp)[ i + 1 ]; + for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) + ; + + if ( i >= c->valx ) { + rc = 1; + break; + } + ber_memfree( ((*bvp)[ c->valx ]).bv_val ); + for ( i = c->valx; !BER_BVISNULL( &((*bvp)[ i + 1 ]) ); i++ ) { + (*bvp)[ i ] = (*bvp)[ i + 1 ]; + } + BER_BVZERO( &((*bvp)[ i ]) ); } - BER_BVZERO( &((*bvp)[ i ]) ); } - } break; + } + break; case LDAP_BACK_CFG_IDASSERT_BIND: - bindconf_free( &mt->mt_idassert.si_bc ); - memset( &mt->mt_idassert, 0, sizeof( slap_idassert_t ) ); + if ( asyncmeta_db_has_mscs ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify this attribute if there are established target connections" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; + } else { + bindconf_free( &mt->mt_idassert.si_bc ); + memset( &mt->mt_idassert, 0, sizeof( slap_idassert_t ) ); + } break; case LDAP_BACK_CFG_SUFFIXM: - if ( mt->mt_lsuffixm.bv_val ) { - ch_free( mt->mt_lsuffixm.bv_val ); - ch_free( mt->mt_rsuffixm.bv_val ); - BER_BVZERO( &mt->mt_lsuffixm ); - BER_BVZERO( &mt->mt_rsuffixm ); + if ( asyncmeta_db_has_mscs ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify this attribute if there are established target connections" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; + } else { + if ( mt->mt_lsuffixm.bv_val ) { + ch_free( mt->mt_lsuffixm.bv_val ); + ch_free( mt->mt_rsuffixm.bv_val ); + BER_BVZERO( &mt->mt_lsuffixm ); + BER_BVZERO( &mt->mt_rsuffixm ); + } } break; @@ -1729,7 +1812,10 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) break; case LDAP_BACK_CFG_MAX_TARGET_CONNS: - mi->mi_max_target_conns = 0; + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "max-target-conns cannot be modified at runtime" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; break; case LDAP_BACK_CFG_MAX_TIMEOUT_OPS: @@ -1737,9 +1823,16 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) break; case LDAP_BACK_CFG_KEEPALIVE: - mt->mt_tls.sb_keepalive.sk_idle = 0; - mt->mt_tls.sb_keepalive.sk_probes = 0; - mt->mt_tls.sb_keepalive.sk_interval = 0; + if ( asyncmeta_db_has_mscs ( mi ) > 0 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "cannot modify this attribute if there are established target connections" ); + Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); + rc = 1; + } else { + mt->mt_tls.sb_keepalive.sk_idle = 0; + mt->mt_tls.sb_keepalive.sk_probes = 0; + mt->mt_tls.sb_keepalive.sk_interval = 0; + } break; case LDAP_BACK_CFG_TCP_USER_TIMEOUT: @@ -1814,7 +1907,7 @@ asyncmeta_back_cf_gen( ConfigArgs *c ) return 1; } - if ( asyncmeta_back_new_target( &mi->mi_targets[ i ] ) != 0 ) { + if ( asyncmeta_back_new_target( &mi->mi_targets[ i ], mi ) != 0 ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to init server" " in \"%s ://[:port]/\"", diff --git a/servers/slapd/back-asyncmeta/conn.c b/servers/slapd/back-asyncmeta/conn.c index 8a43cab649..2d52e2fb40 100644 --- a/servers/slapd/back-asyncmeta/conn.c +++ b/servers/slapd/back-asyncmeta/conn.c @@ -1182,3 +1182,41 @@ void asyncmeta_log_conns(a_metainfo_t *mi) } } + +int +asyncmeta_db_has_pending_ops(a_metainfo_t *mi) +{ + int i; + if (mi->mi_ntargets == 0) { + return 0; + } + + for (i = 0; i < mi->mi_num_conns; i++) { + if (mi->mi_conns[i].pending_ops > 0) { + return mi->mi_conns[i].pending_ops; + } + } + + return 0; +} + + +int +asyncmeta_db_has_mscs(a_metainfo_t *mi) +{ + int i, j; + if (mi->mi_ntargets == 0) { + return 0; + } + + for (i = 0; i < mi->mi_num_conns; i++) { + for (j = 0; j < mi->mi_ntargets; j++) { + if (mi->mi_conns[i].mc_conns[j].msc_ld != NULL || + mi->mi_conns[i].mc_conns[j].msc_ldr != NULL ) { + return 1; + } + } + } + + return 0; +} diff --git a/servers/slapd/back-asyncmeta/delete.c b/servers/slapd/back-asyncmeta/delete.c index 6f7ee9d291..fb6b06ea8c 100644 --- a/servers/slapd/back-asyncmeta/delete.c +++ b/servers/slapd/back-asyncmeta/delete.c @@ -190,6 +190,13 @@ asyncmeta_back_delete( Operation *op, SlapReply *rs ) op->o_log_prefix, op->o_time, current_time ); } + if ( mi->mi_ntargets == 0 ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "No targets are configured for this database"; + send_ldap_result(op, rs); + return rs->sr_err; + } + asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi ); if (bc == NULL) { rs->sr_err = LDAP_OTHER; diff --git a/servers/slapd/back-asyncmeta/init.c b/servers/slapd/back-asyncmeta/init.c index a45fc3b66e..87b9bec0f4 100644 --- a/servers/slapd/back-asyncmeta/init.c +++ b/servers/slapd/back-asyncmeta/init.c @@ -241,23 +241,20 @@ asyncmeta_back_db_open( int i; if ( mi->mi_ntargets == 0 ) { - /* Dynamically added, nothing to check here until - * some targets get added - */ - if ( slapMode & SLAP_SERVER_RUNNING ) - return 0; Debug( LDAP_DEBUG_ANY, "asyncmeta_back_db_open: no targets defined\n" ); - return 1; } + mi->mi_num_conns = 0; for ( i = 0; i < mi->mi_ntargets; i++ ) { a_metatarget_t *mt = mi->mi_targets[ i ]; if ( asyncmeta_target_finish( mi, mt, - "asyncmeta_back_db_open", msg, sizeof( msg ))) + "asyncmeta_back_db_open", msg, sizeof( msg ))) { return 1; + } } + mi->mi_num_conns = (mi->mi_max_target_conns == 0) ? META_BACK_CFG_MAX_TARGET_CONNS : mi->mi_max_target_conns; assert(mi->mi_num_conns > 0); mi->mi_conns = ch_calloc( mi->mi_num_conns, sizeof( a_metaconn_t )); @@ -265,15 +262,25 @@ asyncmeta_back_db_open( a_metaconn_t *mc = &mi->mi_conns[i]; ldap_pvt_thread_mutex_init( &mc->mc_om_mutex); mc->mc_authz_target = META_BOUND_NONE; - mc->mc_conns = ch_calloc( mi->mi_ntargets, sizeof( a_metasingleconn_t )); + + if ( mi->mi_ntargets > 0 ) { + mc->mc_conns = ch_calloc( mi->mi_ntargets, sizeof( a_metasingleconn_t )); + } else { + mc->mc_conns = NULL; + } + mc->mc_info = mi; LDAP_STAILQ_INIT( &mc->mc_om_list ); } - mi->mi_suffix = be->be_suffix[0]; - ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); - mi->mi_task = ldap_pvt_runqueue_insert( &slapd_rq, 1, - asyncmeta_timeout_loop, mi, "asyncmeta_timeout_loop", mi->mi_suffix.bv_val ); - ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + + ber_dupbv ( &mi->mi_suffix, &be->be_suffix[0] ); + + if ( mi->mi_ntargets > 0 ) { + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); + mi->mi_task = ldap_pvt_runqueue_insert( &slapd_rq, 1, + asyncmeta_timeout_loop, mi, "asyncmeta_timeout_loop", mi->mi_suffix.bv_val ); + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + } return 0; } diff --git a/servers/slapd/back-asyncmeta/modify.c b/servers/slapd/back-asyncmeta/modify.c index a6a1f5666a..25faf194fa 100644 --- a/servers/slapd/back-asyncmeta/modify.c +++ b/servers/slapd/back-asyncmeta/modify.c @@ -250,6 +250,13 @@ asyncmeta_back_modify( Operation *op, SlapReply *rs ) op->o_log_prefix, op->o_time, current_time ); } + if ( mi->mi_ntargets == 0 ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "No targets are configured for this database"; + send_ldap_result(op, rs); + return rs->sr_err; + } + asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi ); if (bc == NULL) { rs->sr_err = LDAP_OTHER; diff --git a/servers/slapd/back-asyncmeta/modrdn.c b/servers/slapd/back-asyncmeta/modrdn.c index 970566e4de..a4f42d4408 100644 --- a/servers/slapd/back-asyncmeta/modrdn.c +++ b/servers/slapd/back-asyncmeta/modrdn.c @@ -259,6 +259,14 @@ asyncmeta_back_modrdn( Operation *op, SlapReply *rs ) Debug(asyncmeta_debug, "==> asyncmeta_back_modrdn[%s]: o_time:[%ld], current time: [%ld]\n", op->o_log_prefix, op->o_time, current_time ); } + + if ( mi->mi_ntargets == 0 ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "No targets are configured for this database"; + send_ldap_result(op, rs); + return rs->sr_err; + } + asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets, mi ); if (bc == NULL) { rs->sr_err = LDAP_OTHER; diff --git a/servers/slapd/back-asyncmeta/search.c b/servers/slapd/back-asyncmeta/search.c index 37b9457ff2..92e76b31b0 100644 --- a/servers/slapd/back-asyncmeta/search.c +++ b/servers/slapd/back-asyncmeta/search.c @@ -687,6 +687,13 @@ asyncmeta_back_search( Operation *op, SlapReply *rs ) rs_assert_ready( rs ); rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */ + if ( mi->mi_ntargets == 0 ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "No targets are configured for this database"; + send_ldap_result(op, rs); + return rs->sr_err; + } + /* * controls are set in ldap_back_dobind() *