Commit 54aefe30 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

implement proxy long-lived connection TTL

parent 72d27f22
......@@ -346,6 +346,11 @@ so the client will not know if the operation eventually succeeded or not.
This directive causes a cached connection to be dropped an recreated
after it has been idle for the specified time.
.TP
.B conn-ttl <time>
This directive causes a cached connection to be dropped an recreated
after a given ttl, regardless of being idle 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
......
......@@ -110,6 +110,11 @@ illustrated for the
.B idle-timeout
directive.
.TP
.B conn-ttl <time>
This directive causes a cached connection to be dropped an recreated
after a given ttl, regardless of being idle or not.
.TP
.B onerr {CONTINUE|stop}
This directive allows to select the behavior in case an error is returned
......
......@@ -83,6 +83,7 @@ typedef struct ldapconn_t {
unsigned lc_refcnt;
unsigned lc_flags;
time_t lc_create_time;
time_t lc_time;
} ldapconn_t;
......@@ -189,6 +190,7 @@ typedef struct ldapinfo_t {
ldap_avl_info_t li_conninfo;
time_t li_network_timeout;
time_t li_conn_ttl;
time_t li_idle_timeout;
time_t li_timeout[ LDAP_BACK_OP_LAST ];
} ldapinfo_t;
......
......@@ -459,6 +459,11 @@ error_return:;
send_ldap_result( op, rs );
rs->sr_text = NULL;
}
} else {
if ( li->li_conn_ttl > 0 ) {
(*lcp)->lc_create_time = op->o_time;
}
}
return rs->sr_err;
......@@ -597,9 +602,11 @@ retry_lock:
}
} else {
if ( li->li_idle_timeout != 0 && op->o_time > lc->lc_time + li->li_idle_timeout ) {
if ( ( li->li_idle_timeout != 0 && op->o_time > lc->lc_time + li->li_idle_timeout )
|| ( li->li_conn_ttl != 0 && op->o_time > lc->lc_create_time + li->li_conn_ttl ) )
{
/* in case of failure, it frees/taints lc and sets it to NULL */
if ( ldap_back_retry( &lc, op, rs, sendok ) ) {
if ( !ldap_back_retry( &lc, op, rs, sendok ) ) {
lc = NULL;
}
}
......
......@@ -61,6 +61,7 @@ enum {
LDAP_BACK_CFG_WHOAMI,
LDAP_BACK_CFG_TIMEOUT,
LDAP_BACK_CFG_IDLE_TIMEOUT,
LDAP_BACK_CFG_CONN_TTL,
LDAP_BACK_CFG_REWRITE,
LDAP_BACK_CFG_LAST
......@@ -223,6 +224,14 @@ static ConfigTable ldapcfg[] = {
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
{ "conn-ttl", "ttl", 2, 0, 0,
ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL,
ldap_back_cf_gen, "( OLcfgDbAt:3.16 "
"NAME 'olcDbConnTtl' "
"DESC 'connection ttl' "
"SYNTAX OMsDirectoryString "
"SINGLE-VALUE )",
NULL, NULL },
{ "suffixmassage", "[virtual]> <real", 2, 3, 0,
ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
ldap_back_cf_gen, NULL, NULL, NULL },
......@@ -558,6 +567,18 @@ ldap_back_cf_gen( ConfigArgs *c )
value_add_one( &c->rvalue_vals, &bv );
} break;
case LDAP_BACK_CFG_CONN_TTL: {
char buf[ SLAP_TEXT_BUFLEN ];
if ( li->li_conn_ttl == 0 ) {
return 1;
}
lutil_unparse_time( buf, sizeof( buf ), li->li_conn_ttl );
ber_str2bv( buf, 0, 0, &bv );
value_add_one( &c->rvalue_vals, &bv );
} break;
default:
/* FIXME: we need to handle all... */
assert( 0 );
......@@ -639,6 +660,10 @@ ldap_back_cf_gen( ConfigArgs *c )
li->li_idle_timeout = 0;
break;
case LDAP_BACK_CFG_CONN_TTL:
li->li_conn_ttl = 0;
break;
default:
/* FIXME: we need to handle all... */
assert( 0 );
......@@ -1162,6 +1187,19 @@ done_url:;
li->li_idle_timeout = (time_t)t;
} break;
case LDAP_BACK_CFG_CONN_TTL: {
unsigned long t;
if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
snprintf( c->msg, sizeof( c->msg),
"unable to parse conn ttl\"%s\"",
c->argv[ 1 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
return 1;
}
li->li_conn_ttl = (time_t)t;
} break;
case LDAP_BACK_CFG_REWRITE:
snprintf( c->msg, sizeof( c->msg ),
"rewrite/remap capabilities have been moved "
......
......@@ -174,6 +174,7 @@ typedef struct metasingleconn_t {
#define META_ANONYMOUS 2
#endif
time_t msc_create_time;
time_t msc_time;
struct metainfo_t *msc_info;
......@@ -228,6 +229,7 @@ typedef struct metatarget_t {
unsigned mt_flags;
int mt_version;
time_t mt_network_timeout;
time_t mt_conn_ttl;
time_t mt_idle_timeout;
struct timeval mt_bind_timeout;
#define META_BIND_TIMEOUT LDAP_BACK_RESULT_UTIMEOUT
......@@ -274,6 +276,7 @@ typedef struct metainfo_t {
int mi_version;
time_t mi_network_timeout;
time_t mi_conn_ttl;
time_t mi_idle_timeout;
struct timeval mi_bind_timeout;
time_t mi_timeout[ LDAP_BACK_OP_LAST ];
......
......@@ -158,6 +158,7 @@ meta_back_db_config(
mi->mi_targets[ i ].mt_flags = mi->mi_flags;
mi->mi_targets[ i ].mt_version = mi->mi_version;
mi->mi_targets[ i ].mt_network_timeout = mi->mi_network_timeout;
mi->mi_targets[ i ].mt_conn_ttl = mi->mi_conn_ttl;
mi->mi_targets[ i ].mt_idle_timeout = mi->mi_idle_timeout;
mi->mi_targets[ i ].mt_bind_timeout = mi->mi_bind_timeout;
for ( c = 0; c < LDAP_BACK_OP_LAST; c++ ) {
......@@ -400,6 +401,38 @@ meta_back_db_config(
*tp = (time_t)t;
/* conn ttl */
} else if ( strcasecmp( argv[ 0 ], "conn-ttl" ) == 0 ) {
unsigned long t;
time_t *tp = mi->mi_ntargets ?
&mi->mi_targets[ mi->mi_ntargets - 1 ].mt_conn_ttl
: &mi->mi_conn_ttl;
switch ( argc ) {
case 1:
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing ttl value in \"conn-ttl <seconds>\" line\n",
fname, lineno, 0 );
return 1;
case 2:
break;
default:
Debug( LDAP_DEBUG_ANY,
"%s: line %d: extra cruft after ttl value in \"conn-ttl <seconds>\" line\n",
fname, lineno, 0 );
return 1;
}
if ( lutil_parse_time( argv[ 1 ], &t ) ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: unable to parse ttl \"%s\" in \"conn-ttl <seconds>\" line\n",
fname, lineno, argv[ 1 ] );
return 1;
}
*tp = (time_t)t;
/* bind timeout when connecting to ldap servers */
} else if ( strcasecmp( argv[ 0 ], "bind-timeout" ) == 0 ) {
unsigned long t;
......
......@@ -220,20 +220,28 @@ meta_back_init_one_conn(
* Already init'ed
*/
if ( msc->msc_ld != NULL ) {
if ( mt->mt_idle_timeout == 0 ) {
return rs->sr_err = LDAP_SUCCESS;
}
int doreturn = 1;
if ( op->o_time > msc->msc_time + mt->mt_idle_timeout ) {
if ( ( mt->mt_idle_timeout != 0 && op->o_time > msc->msc_time + mt->mt_idle_timeout )
|| ( mt->mt_conn_ttl != 0 && op->o_time > msc->msc_create_time + mt->mt_conn_ttl ) )
{
Debug( LDAP_DEBUG_TRACE,
"%s meta_back_init_one_conn[%d]: idle timeout.\n",
"%s meta_back_init_one_conn[%d]: idle timeout/ttl.\n",
op->o_log_prefix, candidate, 0 );
if ( meta_back_retry( op, rs, mc, candidate, sendok ) ) {
return rs->sr_err;
}
doreturn = 0;
}
msc->msc_time = op->o_time;
if ( mt->mt_idle_timeout != 0 ) {
msc->msc_time = op->o_time;
}
if ( doreturn ) {
return rs->sr_err = LDAP_SUCCESS;
}
}
/*
......@@ -432,6 +440,10 @@ error_return:;
msc->msc_time = op->o_time;
}
if ( mt->mt_conn_ttl ) {
msc->msc_create_time = op->o_time;
}
} else {
rs->sr_err = slap_map_api2result( rs );
if ( sendok & LDAP_BACK_SENDERR ) {
......
Supports Markdown
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