.fi
.RE
.LP
-for every
+for
.B ldap
and
.B meta
-database.
-This is because operational attributes related to entry creation and
-modification should not be proxied, as they could be mistakenly written
+databases.
+This was required because operational attributes related to entry creation
+and modification should not be proxied, as they could be mistakenly written
to the target server(s), generating an error.
-The current implementation automatically sets lastmod to off, so its use
-is redundant and should be omitted, because the lastmod directive will
-be deprecated in the future.
+The current implementation automatically sets lastmod to \fBoff\fP,
+so its use is redundant and should be omitted.
.SH SPECIAL CONFIGURATION DIRECTIVES
Target configuration starts with the "uri" directive.
rs->sr_err = ldap_add_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
attrs, ctrls, NULL, &msgid );
rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
- mt->mt_timeout[ LDAP_BACK_OP_ADD ], LDAP_BACK_SENDRESULT );
+ mt->mt_timeout[ SLAP_OP_ADD ], LDAP_BACK_SENDRESULT );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
time_t mt_network_timeout;
struct timeval mt_bind_timeout;
#define META_BIND_TIMEOUT LDAP_BACK_RESULT_UTIMEOUT
- time_t mt_timeout[ LDAP_BACK_OP_LAST ];
+ time_t mt_timeout[ SLAP_OP_LAST ];
} metatarget_t;
typedef struct metadncache_t {
time_t mi_conn_ttl;
time_t mi_idle_timeout;
struct timeval mi_bind_timeout;
- time_t mi_timeout[ LDAP_BACK_OP_LAST ];
+ time_t mi_timeout[ SLAP_OP_LAST ];
} metainfo_t;
typedef enum meta_op_type {
op->o_log_prefix, candidate, 0 );
if ( rs->sr_err == LDAP_SUCCESS ) {
+ time_t stoptime = (time_t)(-1),
+ timeout;
+ int timeout_err = op->o_protocol >= LDAP_VERSION3 ?
+ LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
+ const char *timeout_text = "Operation timed out";
+ slap_op_t opidx = slap_req2op( op->o_tag );
+
+ /* since timeout is not specified, compute and use
+ * the one specific to the ongoing operation */
+ if ( opidx == LDAP_REQ_SEARCH ) {
+ if ( op->ors_tlimit <= 0 ) {
+ timeout = 0;
+
+ } else {
+ timeout = op->ors_tlimit;
+ timeout_err = LDAP_TIMELIMIT_EXCEEDED;
+ timeout_text = NULL;
+ }
+
+ } else {
+ timeout = mt->mt_timeout[ opidx ];
+ }
+
+ /* better than nothing :) */
+ if ( timeout == 0 ) {
+ if ( mi->mi_idle_timeout ) {
+ timeout = mi->mi_idle_timeout;
+
+ } else if ( mi->mi_conn_ttl ) {
+ timeout = mi->mi_conn_ttl;
+ }
+ }
+
+ if ( timeout ) {
+ stoptime = op->o_time + timeout;
+ }
+
LDAP_BACK_TV_SET( &tv );
/*
rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res );
switch ( rc ) {
case 0:
+#if 0
Debug( LDAP_DEBUG_ANY,
"%s meta_back_bind_op_result[%d]: ldap_result=0 nretries=%d.\n",
op->o_log_prefix, candidate, nretries );
+#endif
- if ( nretries != META_RETRY_NEVER ) {
+ if ( nretries != META_RETRY_NEVER
+ || ( timeout && slap_get_time() <= stoptime ) )
+ {
ldap_pvt_thread_yield();
if ( nretries > 0 ) {
nretries--;
goto retry;
}
- /* FIXME: binds cannot be abandoned */
/* don't let anyone else use this handler,
* because there's a pending bind that will not
* be acknowledged */
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
- rs->sr_err = LDAP_BUSY;
LDAP_BACK_CONN_BINDING_CLEAR( msc );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+
+ rs->sr_err = timeout_err;
+ rs->sr_text = timeout_text;
break;
case -1:
int rc;
struct timeval tv;
LDAPMessage *res = NULL;
+ time_t stoptime = (time_t)(-1);
+ int timeout_err = op->o_protocol >= LDAP_VERSION3 ?
+ LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
+ const char *timeout_text = "Operation timed out";
- if ( timeout ) {
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
+ /* if timeout is not specified, compute and use
+ * the one specific to the ongoing operation */
+ if ( timeout == (time_t)(-1) ) {
+ slap_op_t opidx = slap_req2op( op->o_tag );
- } else {
- LDAP_BACK_TV_SET( &tv );
+ if ( opidx == SLAP_OP_SEARCH ) {
+ if ( op->ors_tlimit <= 0 ) {
+ timeout = 0;
+
+ } else {
+ timeout = op->ors_tlimit;
+ timeout_err = LDAP_TIMELIMIT_EXCEEDED;
+ timeout_text = NULL;
+ }
+
+ } else {
+ timeout = mt->mt_timeout[ opidx ];
+ }
}
+ /* better than nothing :) */
+ if ( timeout == 0 ) {
+ if ( mi->mi_idle_timeout ) {
+ timeout = mi->mi_idle_timeout;
+
+ } else if ( mi->mi_conn_ttl ) {
+ timeout = mi->mi_conn_ttl;
+ }
+ }
+
+ if ( timeout ) {
+ stoptime = op->o_time + timeout;
+ }
+
+ LDAP_BACK_TV_SET( &tv );
+
retry:;
rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res );
switch ( rc ) {
case 0:
- if ( timeout ) {
+ if ( timeout && slap_get_time() > stoptime ) {
(void)meta_back_cancel( mc, op, rs, msgid, candidate, sendok );
- rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
- LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
- rs->sr_text = "Operation timed out";
+ rs->sr_err = timeout_err;
+ rs->sr_text = timeout_text;
break;
}
mt->mt_version = mi->mi_version;
mt->mt_network_timeout = mi->mi_network_timeout;
mt->mt_bind_timeout = mi->mi_bind_timeout;
- for ( c = 0; c < LDAP_BACK_OP_LAST; c++ ) {
+ for ( c = 0; c < SLAP_OP_LAST; c++ ) {
mt->mt_timeout[ c ] = mi->mi_timeout[ c ];
}
if ( argc < 2 ) {
Debug( LDAP_DEBUG_ANY,
- "%s: line %d: \"timeout [{add|delete|modify|modrdn}=]<val> [...]\" takes at least 1 argument\n",
+ "%s: line %d: \"timeout [{add|bind|delete|modify|modrdn}=]<val> [...]\" takes at least 1 argument\n",
fname, lineno, 0 );
return( 1 );
}
if ( sep != NULL ) {
size_t len = sep - argv[ c ];
- if ( strncasecmp( argv[ c ], "add", len ) == 0 ) {
- t = &tv[ LDAP_BACK_OP_ADD ];
+ if ( strncasecmp( argv[ c ], "bind", len ) == 0 ) {
+ t = &tv[ SLAP_OP_BIND ];
+ /* unbind makes little sense */
+ } else if ( strncasecmp( argv[ c ], "add", len ) == 0 ) {
+ t = &tv[ SLAP_OP_ADD ];
} else if ( strncasecmp( argv[ c ], "delete", len ) == 0 ) {
- t = &tv[ LDAP_BACK_OP_DELETE ];
- } else if ( strncasecmp( argv[ c ], "modify", len ) == 0 ) {
- t = &tv[ LDAP_BACK_OP_MODIFY ];
+ t = &tv[ SLAP_OP_DELETE ];
} else if ( strncasecmp( argv[ c ], "modrdn", len ) == 0 ) {
- t = &tv[ LDAP_BACK_OP_MODRDN ];
+ t = &tv[ SLAP_OP_MODRDN ];
+ } else if ( strncasecmp( argv[ c ], "modify", len ) == 0 ) {
+ t = &tv[ SLAP_OP_MODIFY ];
+ } else if ( strncasecmp( argv[ c ], "compare", len ) == 0 ) {
+ t = &tv[ SLAP_OP_COMPARE ];
+#if 0 /* uses timelimit instead */
+ } else if ( strncasecmp( argv[ c ], "search", len ) == 0 ) {
+ t = &tv[ SLAP_OP_SEARCH ];
+#endif
+ /* abandon makes little sense */
+#if 0 /* not implemented yet */
+ } else if ( strncasecmp( argv[ c ], "extended", len ) == 0 ) {
+ t = &tv[ SLAP_OP_EXTENDED ];
+#endif
} else {
char buf[ SLAP_TEXT_BUFLEN ];
snprintf( buf, sizeof( buf ),
- "unknown operation \"%s\" for timeout #%d",
- argv[ c ], c );
+ "unknown/unhandled operation \"%s\" for timeout #%d",
+ argv[ c ], c - 1 );
Debug( LDAP_DEBUG_ANY,
"%s: line %d: %s.\n",
fname, lineno, buf );
} else {
int i;
- for ( i = 0; i < LDAP_BACK_OP_LAST; i++ ) {
+ for ( i = 0; i < SLAP_OP_LAST; i++ ) {
tv[ i ] = (time_t)val;
}
}
rs->sr_err = ldap_delete_ext( mc->mc_conns[ candidate ].msc_ld,
mdn.bv_val, ctrls, NULL, &msgid );
rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
- mt->mt_timeout[ LDAP_BACK_OP_DELETE ], LDAP_BACK_SENDRESULT );
+ mt->mt_timeout[ SLAP_OP_DELETE ], LDAP_BACK_SENDRESULT );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
rs->sr_err = ldap_modify_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
modv, ctrls, NULL, &msgid );
rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
- mt->mt_timeout[ LDAP_BACK_OP_MODIFY ], LDAP_BACK_SENDRESULT );
+ mt->mt_timeout[ SLAP_OP_MODIFY ], LDAP_BACK_SENDRESULT );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
mnewSuperior.bv_val, op->orr_deleteoldrdn,
ctrls, NULL, &msgid );
rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
- mt->mt_timeout[ LDAP_BACK_OP_MODRDN ], LDAP_BACK_SENDRESULT );
+ mt->mt_timeout[ SLAP_OP_MODRDN ], LDAP_BACK_SENDRESULT );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {