From 4cab386d13e4479991032859ea6cbf7181c7f2c7 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sun, 6 Nov 2005 23:29:10 +0000 Subject: [PATCH] backport write operation timeouts from back-meta to back-ldap; minor cleanup & silence warnings --- doc/man/man5/slapd-ldap.5 | 15 ++++++ servers/slapd/back-ldap/add.c | 5 +- servers/slapd/back-ldap/back-ldap.h | 13 +++++ servers/slapd/back-ldap/bind.c | 31 +++++++++-- servers/slapd/back-ldap/compare.c | 2 +- servers/slapd/back-ldap/config.c | 79 ++++++++++++++++++++++++++-- servers/slapd/back-ldap/delete.c | 5 +- servers/slapd/back-ldap/modify.c | 5 +- servers/slapd/back-ldap/modrdn.c | 5 +- servers/slapd/back-ldap/proto-ldap.h | 2 +- servers/slapd/back-ldap/search.c | 8 +-- servers/slapd/back-meta/add.c | 4 +- servers/slapd/back-meta/back-meta.h | 12 +---- servers/slapd/back-meta/config.c | 12 ++--- servers/slapd/back-meta/conn.c | 6 ++- servers/slapd/back-meta/delete.c | 4 +- servers/slapd/back-meta/modify.c | 4 +- servers/slapd/back-meta/modrdn.c | 4 +- servers/slapd/back-meta/search.c | 2 +- 19 files changed, 171 insertions(+), 47 deletions(-) diff --git a/doc/man/man5/slapd-ldap.5 b/doc/man/man5/slapd-ldap.5 index 80e408ffb6..b683085b0b 100644 --- a/doc/man/man5/slapd-ldap.5 +++ b/doc/man/man5/slapd-ldap.5 @@ -319,6 +319,21 @@ If set to .BR discover , support is detected by reading the remote server's root DSE. +.TP +.B timeout [{add|delete|modify|modrdn}=] [...] +This directive allows to set per-operation timeouts. +If no operation is specified, it affects all. +Currently, only write operations are addressed, because searches +can already be limited by means of the +.B limits +directive (see +.BR slapd.conf (5) +for details), and other operations are not supposed to incur into the +need for timeouts. +Note: if the timelimit is exceeded, the operation is abandoned; +the protocol does not provide any means to rollback the operation, +so the client will not know if the operation eventually succeeded or not. + .SH BACKWARD COMPATIBILITY The LDAP backend has been heavily reworked between releases 2.2 and 2.3; as a side-effect, some of the traditional directives have been diff --git a/servers/slapd/back-ldap/add.c b/servers/slapd/back-ldap/add.c index 96a9c3b94d..0c394c3645 100644 --- a/servers/slapd/back-ldap/add.c +++ b/servers/slapd/back-ldap/add.c @@ -36,6 +36,8 @@ ldap_back_add( Operation *op, SlapReply *rs ) { + struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private; + struct ldapconn *lc; int i = 0, j = 0; @@ -100,7 +102,8 @@ ldap_back_add( retry: rs->sr_err = ldap_add_ext( lc->lc_ld, op->o_req_dn.bv_val, attrs, ctrls, NULL, &msgid ); - rs->sr_err = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); + rs->sr_err = ldap_back_op_result( lc, op, rs, msgid, + li->timeout[ LDAP_BACK_OP_ADD ], LDAP_BACK_SENDRESULT ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index e9a74db2f8..f0a4330ac4 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -93,6 +93,17 @@ enum { LDAP_BACK_IDASSERT_OTHERID }; +/* + * operation enumeration for timeouts + */ +enum { + LDAP_BACK_OP_ADD = 0, + LDAP_BACK_OP_DELETE, + LDAP_BACK_OP_MODIFY, + LDAP_BACK_OP_MODRDN, + LDAP_BACK_OP_LAST +}; + struct ldapinfo { char *url; LDAPURLDesc *lud; @@ -166,6 +177,8 @@ struct ldapinfo { /* FIXME: automatic rwm instantiation removed */ int rwm_started; #endif + + time_t timeout[ LDAP_BACK_OP_LAST ]; }; typedef enum ldap_back_send_t { diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index a34dc44e0f..668143f682 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -71,7 +71,7 @@ ldap_back_bind( Operation *op, SlapReply *rs ) rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val, LDAP_SASL_SIMPLE, &op->orb_cred, op->o_ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR ); + rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_SENDERR ); if ( rc == LDAP_SUCCESS ) { /* If defined, proxyAuthz will be used also when @@ -737,7 +737,7 @@ retry:; return 0; } - rc = ldap_back_op_result( lc, op, rs, msgid, sendok ); + rc = ldap_back_op_result( lc, op, rs, msgid, 0, sendok ); if ( rc == LDAP_SUCCESS ) { LDAP_BACK_CONN_ISBOUND_SET( lc ); @@ -800,6 +800,7 @@ ldap_back_op_result( Operation *op, SlapReply *rs, ber_int_t msgid, + time_t timeout, ldap_back_send_t sendok ) { char *match = NULL; @@ -818,12 +819,26 @@ ldap_back_op_result( int rc; struct timeval tv; - LDAP_BACK_TV_SET( &tv ); + if ( timeout ) { + tv.tv_sec = timeout; + tv.tv_usec = 0; + + } else { + LDAP_BACK_TV_SET( &tv ); + } retry:; /* if result parsing fails, note the failure reason */ - switch ( ldap_result( lc->lc_ld, msgid, 1, &tv, &res ) ) { + rc = ldap_result( lc->lc_ld, msgid, 1, &tv, &res ); + switch ( rc ) { case 0: + if ( timeout ) { + (void)ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL ); + rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; + rs->sr_text = "Operation timed out"; + break; + } + LDAP_BACK_TV_SET( &tv ); ldap_pvt_thread_yield(); goto retry; @@ -893,6 +908,12 @@ ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_se ldap_pvt_thread_mutex_lock( &li->conn_mutex ); if ( lc->lc_refcnt == 1 ) { + Debug( LDAP_DEBUG_ANY, + "%s ldap_back_retry: retrying URI=\"%s\" DN=\"%s\"\n", + op->o_log_prefix, li->url, + BER_BVISNULL( &lc->lc_bound_ndn ) ? + "" : lc->lc_bound_ndn.bv_val ); + ldap_unbind_ext( lc->lc_ld, NULL, NULL ); lc->lc_ld = NULL; LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); @@ -1089,7 +1110,7 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs ) goto done; } - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR ); + rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_SENDERR ); if ( rc == LDAP_SUCCESS ) { LDAP_BACK_CONN_ISBOUND_SET( lc ); } diff --git a/servers/slapd/back-ldap/compare.c b/servers/slapd/back-ldap/compare.c index 44628d98b4..64caac368a 100644 --- a/servers/slapd/back-ldap/compare.c +++ b/servers/slapd/back-ldap/compare.c @@ -60,7 +60,7 @@ retry: op->orc_ava->aa_desc->ad_cname.bv_val, &op->orc_ava->aa_value, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); + rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_SENDRESULT ); if ( rc == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index 7968dc5331..3e5573f7bb 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -59,6 +59,7 @@ enum { LDAP_BACK_CFG_CHASE, LDAP_BACK_CFG_T_F, LDAP_BACK_CFG_WHOAMI, + LDAP_BACK_CFG_TIMEOUT, LDAP_BACK_CFG_REWRITE }; @@ -203,6 +204,14 @@ static ConfigTable ldapcfg[] = { "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, + { "timeout", "timeout", 0, 2, 0, + ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT, + ldap_back_cf_gen, "( OLcfgDbAt:3.14 " + "NAME 'olcDbTimeout' " + "DESC 'Per-operation timeouts' " + "SYNTAX OMsDirectoryString " + "SINGLE-VALUE )", + NULL, NULL }, { "suffixmassage", "[virtual]> o_bd->be_private; + struct ldapconn *lc; ber_int_t msgid; LDAPControl **ctrls = NULL; @@ -59,7 +61,8 @@ ldap_back_delete( retry: rs->sr_err = ldap_delete_ext( lc->lc_ld, op->o_req_ndn.bv_val, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); + rc = ldap_back_op_result( lc, op, rs, msgid, + li->timeout[ LDAP_BACK_OP_DELETE], LDAP_BACK_SENDRESULT ); if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { diff --git a/servers/slapd/back-ldap/modify.c b/servers/slapd/back-ldap/modify.c index 7725986bf7..ae0820ff53 100644 --- a/servers/slapd/back-ldap/modify.c +++ b/servers/slapd/back-ldap/modify.c @@ -36,6 +36,8 @@ ldap_back_modify( Operation *op, SlapReply *rs ) { + struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private; + struct ldapconn *lc; LDAPMod **modv = NULL, *mods = NULL; @@ -107,7 +109,8 @@ ldap_back_modify( retry: rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_ndn.bv_val, modv, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); + rc = ldap_back_op_result( lc, op, rs, msgid, + li->timeout[ LDAP_BACK_OP_MODIFY], LDAP_BACK_SENDRESULT ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { diff --git a/servers/slapd/back-ldap/modrdn.c b/servers/slapd/back-ldap/modrdn.c index 0890b26d19..254038570e 100644 --- a/servers/slapd/back-ldap/modrdn.c +++ b/servers/slapd/back-ldap/modrdn.c @@ -36,6 +36,8 @@ ldap_back_modrdn( Operation *op, SlapReply *rs ) { + struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private; + struct ldapconn *lc; ber_int_t msgid; LDAPControl **ctrls = NULL; @@ -67,7 +69,8 @@ retry: rs->sr_err = ldap_rename( lc->lc_ld, op->o_req_ndn.bv_val, op->orr_newrdn.bv_val, newSup, op->orr_deleteoldrdn, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); + rc = ldap_back_op_result( lc, op, rs, msgid, + li->timeout[ LDAP_BACK_OP_MODRDN ], LDAP_BACK_SENDRESULT ); if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { diff --git a/servers/slapd/back-ldap/proto-ldap.h b/servers/slapd/back-ldap/proto-ldap.h index 80600e391c..f705bf521c 100644 --- a/servers/slapd/back-ldap/proto-ldap.h +++ b/servers/slapd/back-ldap/proto-ldap.h @@ -55,7 +55,7 @@ int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_bac int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok); int ldap_back_map_result(SlapReply *rs); int ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs, - ber_int_t msgid, ldap_back_send_t sendok); + ber_int_t msgid, time_t timeout, ldap_back_send_t sendok); int back_ldap_LTX_init_module(int argc, char *argv[]); int ldap_back_init_cf( BackendInfo *bi ); diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 8f33ae38f5..9c880bc552 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -143,7 +143,7 @@ ldap_back_search( { struct ldapconn *lc; struct timeval tv; - time_t stoptime; + time_t stoptime = (time_t)-1; LDAPMessage *res, *e; int rc = 0, @@ -223,7 +223,7 @@ fail:; goto retry; } } - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); + rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_DONTSEND ); ldap_back_freeconn( op, lc ); lc = NULL; goto finish; @@ -346,7 +346,7 @@ fail:; /* cleanup */ if ( references ) { - ldap_value_free( references ); + ber_memvfree( (void **)references ); ch_free( rs->sr_ref ); rs->sr_ref = NULL; } @@ -404,7 +404,7 @@ fail:; /* cleanup */ if ( references ) { - ldap_value_free( references ); + ber_memvfree( (void **)references ); } rc = 0; diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c index fe383f230c..84dc2b7f1c 100644 --- a/servers/slapd/back-meta/add.c +++ b/servers/slapd/back-meta/add.c @@ -178,8 +178,8 @@ retry:; LDAPMessage *res = NULL; int rc; - if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_ADD ] != 0 ) { - tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_ADD ]; + if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_ADD ] != 0 ) { + tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_ADD ]; tv.tv_usec = 0; tvp = &tv; } diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index a37f60196f..87ba1badf0 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -205,14 +205,6 @@ 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; int mt_scope; @@ -236,7 +228,7 @@ typedef struct metatarget_t { unsigned mt_flags; int mt_version; - time_t mt_timeout[ META_OP_LAST ]; + time_t mt_timeout[ LDAP_BACK_OP_LAST ]; } metatarget_t; typedef struct metadncache_t { @@ -279,7 +271,7 @@ typedef struct metainfo_t { #define META_BACK_DEFER_ROOTDN_BIND(mi) ( (mi)->flags & META_BACK_F_DEFER_ROOTDN_BIND ) int mi_version; - time_t mi_timeout[ META_OP_LAST ]; + time_t mi_timeout[ LDAP_BACK_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 078d2ee0c6..58cba85096 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -163,7 +163,7 @@ 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++ ) { + for ( c = 0; c < LDAP_BACK_OP_LAST; c++ ) { mi->mi_targets[ i ].mt_timeout[ c ] = mi->mi_timeout[ c ]; } @@ -619,13 +619,13 @@ meta_back_db_config( size_t len = sep - argv[ c ]; if ( strncasecmp( argv[ c ], "add", len ) == 0 ) { - t = &tv[ META_OP_ADD ]; + t = &tv[ LDAP_BACK_OP_ADD ]; } else if ( strncasecmp( argv[ c ], "delete", len ) == 0 ) { - t = &tv[ META_OP_DELETE ]; + t = &tv[ LDAP_BACK_OP_DELETE ]; } else if ( strncasecmp( argv[ c ], "modify", len ) == 0 ) { - t = &tv[ META_OP_MODIFY ]; + t = &tv[ LDAP_BACK_OP_MODIFY ]; } else if ( strncasecmp( argv[ c ], "modrdn", len ) == 0 ) { - t = &tv[ META_OP_MODRDN ]; + t = &tv[ LDAP_BACK_OP_MODRDN ]; } else { fprintf( stderr, "%s: line %d: unknown operation \"%s\" for timeout #%d.\n", @@ -652,7 +652,7 @@ meta_back_db_config( } else { int i; - for ( i = 0; i < META_OP_LAST; i++ ) { + for ( i = 0; i < LDAP_BACK_OP_LAST; i++ ) { tv[ i ] = val; } } diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index d005df178c..e30bedb9b3 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -448,9 +448,11 @@ retry_lock:; goto retry_lock; } - Debug( LDAP_DEBUG_ANY, "%s meta_back_retry: retrying uri=\"%s\" DN=\"%s\"\n", + Debug( LDAP_DEBUG_ANY, + "%s meta_back_retry: retrying URI=\"%s\" DN=\"%s\"\n", op->o_log_prefix, mt->mt_uri, - BER_BVISNULL( &msc->msc_bound_ndn ) ? "" : msc->msc_bound_ndn.bv_val ); + BER_BVISNULL( &msc->msc_bound_ndn ) ? + "" : msc->msc_bound_ndn.bv_val ); meta_clear_one_candidate( msc ); LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); diff --git a/servers/slapd/back-meta/delete.c b/servers/slapd/back-meta/delete.c index 7c1463d60f..42f77bf966 100644 --- a/servers/slapd/back-meta/delete.c +++ b/servers/slapd/back-meta/delete.c @@ -76,8 +76,8 @@ retry:; LDAPMessage *res = NULL; int rc; - if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_DELETE ] != 0 ) { - tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_DELETE ]; + if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_DELETE ] != 0 ) { + tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_DELETE ]; tv.tv_usec = 0; tvp = &tv; } diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c index f6d2e9f428..9701257022 100644 --- a/servers/slapd/back-meta/modify.c +++ b/servers/slapd/back-meta/modify.c @@ -186,8 +186,8 @@ retry:; 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 ]; + if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODIFY ] != 0 ) { + tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODIFY ]; tv.tv_usec = 0; tvp = &tv; } diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c index 741571c32d..1c943b95d3 100644 --- a/servers/slapd/back-meta/modrdn.c +++ b/servers/slapd/back-meta/modrdn.c @@ -117,8 +117,8 @@ retry:; LDAPMessage *res = NULL; int rc; - if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODRDN ] != 0 ) { - tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODRDN ]; + if ( mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODRDN ] != 0 ) { + tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ LDAP_BACK_OP_MODRDN ]; tv.tv_usec = 0; tvp = &tv; } diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index e347169273..dbcab08c8b 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -245,7 +245,7 @@ meta_back_search( Operation *op, SlapReply *rs ) metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; metaconn_t *mc; struct timeval tv = { 0, 0 }; - time_t stoptime; + time_t stoptime = (time_t)-1; LDAPMessage *res = NULL, *e; int rc = 0, sres = LDAP_SUCCESS; char *matched = NULL; -- 2.39.5