Commit bda051ce authored by Nadezhda Ivanova's avatar Nadezhda Ivanova
Browse files

Enable addition of targets to back-asyncmeta via cn=config

parent 7307d776
Pipeline #2577 passed with stage
in 58 minutes and 12 seconds
......@@ -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;
......
......@@ -769,6 +769,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)
......
......@@ -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 */
......
......@@ -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;
......
......@@ -445,11 +445,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;
}
......@@ -475,12 +485,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 );
......@@ -493,6 +506,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;
}
......@@ -1015,6 +1040,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;
......@@ -1505,6 +1537,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:
......@@ -1529,8 +1562,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:
......@@ -1552,7 +1592,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:
......@@ -1589,7 +1636,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
......@@ -1610,9 +1664,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.
......@@ -1623,44 +1684,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;
......@@ -1714,7 +1797,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:
......@@ -1722,9 +1808,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;
default:
......@@ -1795,7 +1888,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 <protocol>://<server>[:port]/<naming context>\"",
......
......@@ -1177,3 +1177,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;
}
......@@ -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;
......
......@@ -237,23 +237,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 ));
......@@ -261,15 +258,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;
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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()
*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment