implement per-target, per-operation timeouts

This commit is contained in:
Pierangelo Masarati 2005-07-19 00:43:38 +00:00
parent c172a20c49
commit 54a0c02c3d
6 changed files with 221 additions and 22 deletions

View file

@ -43,6 +43,7 @@ meta_back_add( Operation *op, SlapReply *rs )
LDAPMod **attrs;
struct berval mdn = BER_BVNULL, mapped;
dncookie dc;
int msgid;
int do_retry = 1;
Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
@ -163,20 +164,49 @@ meta_back_add( Operation *op, SlapReply *rs )
attrs[ i ] = NULL;
retry:;
#if 0
rs->sr_err = ldap_add_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
attrs, op->o_ctrls, NULL, &msgid );
rs->sr_err = meta_back_op_result( op, rs, &mc->mc_conns[ candidate ], msgid, LDAP_BACK_SENDERR );
#endif
rs->sr_err = ldap_add_ext_s( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
attrs, op->o_ctrls, NULL );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
goto retry;
}
} else if ( rs->sr_err == LDAP_SUCCESS ) {
struct timeval tv, *tvp = NULL;
LDAPMessage *res = NULL;
if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_ADD ] != 0 ) {
tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_ADD ];
tv.tv_usec = 0;
tvp = &tv;
}
rs->sr_err = ldap_result( mc->mc_conns[ candidate ].msc_ld,
msgid, LDAP_MSG_ONE, tvp, &res );
switch ( rs->sr_err ) {
case -1:
rs->sr_err = LDAP_OTHER;
send_ldap_result( op, rs );
goto cleanup;
case 0:
ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
msgid, NULL, NULL );
rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
send_ldap_result( op, rs );
goto cleanup;
default:
ldap_msgfree( res );
break;
}
}
(void)meta_back_op_result( mc, op, rs, candidate );
cleanup:;
for ( --i; i >= 0; --i ) {
free( attrs[ i ]->mod_bvalues );
free( attrs[ i ] );
@ -187,8 +217,6 @@ retry:;
BER_BVZERO( &mdn );
}
(void)meta_back_op_result( mc, op, rs, candidate );
done:;
meta_back_release_conn( op, mc );

View file

@ -193,6 +193,14 @@ typedef struct metaconn_t {
* in one block with the metaconn_t structure */
} metaconn_t;
enum {
META_OP_ADD = 0,
META_OP_DELETE,
META_OP_MODIFY,
META_OP_MODRDN,
META_OP_LAST
};
typedef struct metatarget_t {
char *mt_uri;
@ -215,6 +223,7 @@ typedef struct metatarget_t {
unsigned mt_flags;
int mt_version;
time_t mt_timeout[ META_OP_LAST ];
} metatarget_t;
typedef struct metadncache_t {
@ -253,6 +262,7 @@ typedef struct metainfo_t {
#define META_BACK_ONERR_CONTINUE(mi) ( !META_BACK_ONERR_CONTINUE( (mi) ) )
int mi_version;
time_t mi_timeout[ META_OP_LAST ];
} metainfo_t;
typedef enum meta_op_type {

View file

@ -96,6 +96,7 @@ meta_back_db_config(
LDAPURLDesc *ludp, *tmpludp;
struct berval dn;
int rc;
int c;
if ( argc != 2 ) {
fprintf( stderr,
@ -129,6 +130,10 @@ meta_back_db_config(
mi->mi_targets[ i ].mt_flags = mi->flags;
mi->mi_targets[ i ].mt_version = mi->mi_version;
for ( c = 0; c < META_OP_LAST; c++ ) {
mi->mi_targets[ i ].mt_timeout[ c ] = mi->mi_timeout[ c ];
}
/*
* uri MUST be legal!
*/
@ -492,6 +497,67 @@ meta_back_db_config(
return 1;
}
} else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) {
char *sep, *next;
time_t *tv = mi->mi_ntargets ?
&mi->mi_targets[ mi->mi_ntargets - 1 ].mt_timeout
: &mi->mi_timeout;
int c;
if ( argc < 2 ) {
fprintf( stderr,
"%s: line %d: \"timeout [{add|delete|modify|modrdn}=]<val> [...]\" takes at least 1 argument\n",
fname, lineno );
return( 1 );
}
for ( c = 1; c < argc; c++ ) {
time_t *t = NULL, val;
sep = strchr( argv[ c ], '=' );
if ( sep != NULL ) {
size_t len = sep - argv[ c ];
if ( strncasecmp( argv[ c ], "add", len ) == 0 ) {
t = &tv[ META_OP_ADD ];
} else if ( strncasecmp( argv[ c ], "delete", len ) == 0 ) {
t = &tv[ META_OP_DELETE ];
} else if ( strncasecmp( argv[ c ], "modify", len ) == 0 ) {
t = &tv[ META_OP_MODIFY ];
} else if ( strncasecmp( argv[ c ], "modrdn", len ) == 0 ) {
t = &tv[ META_OP_MODRDN ];
} else {
fprintf( stderr,
"%s: line %d: unknown operation \"%s\" for timeout #%d.\n",
fname, lineno, argv[ c ], c );
return 1;
}
sep++;
} else {
sep = argv[ c ];
}
val = strtoul( sep, &next, 10 );
if ( next == sep || next[ 0 ] != '\0' ) {
fprintf( stderr,
"%s: line %d: unable to parse value \"%s\" for timeout.\n",
fname, lineno, sep );
return 1;
}
if ( t ) {
*t = val;
} else {
int i;
for ( i = 0; i < META_OP_LAST; i++ ) {
tv[ i ] = val;
}
}
}
/* name to use as pseudo-root dn */
} else if ( strcasecmp( argv[ 0 ], "pseudorootdn" ) == 0 ) {
int i = mi->mi_ntargets - 1;

View file

@ -39,6 +39,7 @@ meta_back_delete( Operation *op, SlapReply *rs )
int candidate = -1;
struct berval mdn = BER_BVNULL;
dncookie dc;
int msgid;
int do_retry = 1;
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
@ -62,22 +63,54 @@ meta_back_delete( Operation *op, SlapReply *rs )
}
retry:;
rs->sr_err = ldap_delete_ext_s( mc->mc_conns[ candidate ].msc_ld,
mdn.bv_val, op->o_ctrls, NULL );
rs->sr_err = ldap_delete_ext( mc->mc_conns[ candidate ].msc_ld,
mdn.bv_val, op->o_ctrls, NULL, &msgid );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
goto retry;
}
} else if ( rs->sr_err == LDAP_SUCCESS ) {
struct timeval tv, *tvp = NULL;
LDAPMessage *res = NULL;
if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_DELETE ] != 0 ) {
tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_DELETE ];
tv.tv_usec = 0;
tvp = &tv;
}
rs->sr_err = ldap_result( mc->mc_conns[ candidate ].msc_ld,
msgid, LDAP_MSG_ONE, tvp, &res );
switch ( rs->sr_err ) {
case -1:
rs->sr_err = LDAP_OTHER;
send_ldap_result( op, rs );
goto cleanup;
case 0:
ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
msgid, NULL, NULL );
rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
send_ldap_result( op, rs );
goto cleanup;
default:
ldap_msgfree( res );
break;
}
}
rs->sr_err = meta_back_op_result( mc, op, rs, candidate );
cleanup:;
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
BER_BVZERO( &mdn );
}
rs->sr_err = meta_back_op_result( mc, op, rs, candidate );
done:;
meta_back_release_conn( op, mc );

View file

@ -45,6 +45,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
struct berval mdn = BER_BVNULL;
struct berval mapped;
dncookie dc;
int msgid;
int do_retry = 1;
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
@ -172,13 +173,44 @@ meta_back_modify( Operation *op, SlapReply *rs )
modv[ i ] = 0;
retry:;
rs->sr_err = ldap_modify_ext_s( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
modv, op->o_ctrls, NULL );
rs->sr_err = ldap_modify_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
modv, op->o_ctrls, NULL, &msgid );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
goto retry;
}
} else if ( rs->sr_err == LDAP_SUCCESS ) {
struct timeval tv, *tvp = NULL;
LDAPMessage *res = NULL;
if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODIFY ] != 0 ) {
tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODIFY ];
tv.tv_usec = 0;
tvp = &tv;
}
rs->sr_err = ldap_result( mc->mc_conns[ candidate ].msc_ld,
msgid, LDAP_MSG_ONE, tvp, &res );
switch ( rs->sr_err ) {
case -1:
rs->sr_err = LDAP_OTHER;
rc = -1;
break;
case 0:
ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
msgid, NULL, NULL );
rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
rc = -1;
break;
default:
ldap_msgfree( res );
break;
}
}
cleanup:;

View file

@ -34,13 +34,14 @@
int
meta_back_modrdn( Operation *op, SlapReply *rs )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metaconn_t *mc;
int candidate = -1;
struct berval mdn = BER_BVNULL,
mnewSuperior = BER_BVNULL;
dncookie dc;
int do_retry = 1;
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metaconn_t *mc;
int candidate = -1;
struct berval mdn = BER_BVNULL,
mnewSuperior = BER_BVNULL;
dncookie dc;
int msgid;
int do_retry = 1;
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
@ -101,15 +102,44 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
}
retry:;
rs->sr_err = ldap_rename_s( mc->mc_conns[ candidate ].msc_ld,
rs->sr_err = ldap_rename( mc->mc_conns[ candidate ].msc_ld,
mdn.bv_val, op->orr_newrdn.bv_val,
mnewSuperior.bv_val, op->orr_deleteoldrdn,
op->o_ctrls, NULL );
op->o_ctrls, NULL, &msgid );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
goto retry;
}
} else if ( rs->sr_err == LDAP_SUCCESS ) {
struct timeval tv, *tvp = NULL;
LDAPMessage *res = NULL;
if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODRDN ] != 0 ) {
tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODRDN ];
tv.tv_usec = 0;
tvp = &tv;
}
rs->sr_err = ldap_result( mc->mc_conns[ candidate ].msc_ld,
msgid, LDAP_MSG_ONE, tvp, &res );
switch ( rs->sr_err ) {
case -1:
rs->sr_err = LDAP_OTHER;
break;
case 0:
ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
msgid, NULL, NULL );
rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
break;
default:
ldap_msgfree( res );
break;
}
}
cleanup:;