From: Pierangelo Masarati Date: Tue, 19 Jul 2005 00:43:38 +0000 (+0000) Subject: implement per-target, per-operation timeouts X-Git-Tag: OPENLDAP_AC_BP~348 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=54a0c02c3d03c8b5853c581e51a5723165b42e56;p=openldap implement per-target, per-operation timeouts --- diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c index 31b0fcb59a..3cc3431d73 100644 --- a/servers/slapd/back-meta/add.c +++ b/servers/slapd/back-meta/add.c @@ -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 ); diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index c3c23adadb..daf6e85df9 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -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 { diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index 62fcd5f071..d4167bd094 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -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}=] [...]\" 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; diff --git a/servers/slapd/back-meta/delete.c b/servers/slapd/back-meta/delete.c index d247de359a..36a89cdadc 100644 --- a/servers/slapd/back-meta/delete.c +++ b/servers/slapd/back-meta/delete.c @@ -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 ); diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c index 2d51289cb1..379a1e03ec 100644 --- a/servers/slapd/back-meta/modify.c +++ b/servers/slapd/back-meta/modify.c @@ -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:; diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c index a63e99e48c..90b151761e 100644 --- a/servers/slapd/back-meta/modrdn.c +++ b/servers/slapd/back-meta/modrdn.c @@ -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:;