Commit 8c1b8d3f authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

actually, if a connection is already in the AVL tree, use it if not binding;...

actually, if a connection is already in the AVL tree, use it if not binding; otherwise use a tainted one; taint connections that must be freed when refcnt goes to zero
parent 76bf5d4c
......@@ -60,6 +60,7 @@ typedef struct ldapconn_t {
#define LDAP_BACK_FCONN_ISPRIV (0x04)
#define LDAP_BACK_FCONN_ISTLS (0x08)
#define LDAP_BACK_FCONN_BINDING (0x10)
#define LDAP_BACK_FCONN_TAINTED (0x20)
#define LDAP_BACK_CONN_ISBOUND(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND)
#define LDAP_BACK_CONN_ISBOUND_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND)
......@@ -80,6 +81,9 @@ typedef struct ldapconn_t {
#define LDAP_BACK_CONN_BINDING(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_BINDING)
#define LDAP_BACK_CONN_BINDING_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_BINDING)
#define LDAP_BACK_CONN_BINDING_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_BINDING)
#define LDAP_BACK_CONN_TAINTED(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_TAINTED)
#define LDAP_BACK_CONN_TAINTED_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_TAINTED)
#define LDAP_BACK_CONN_TAINTED_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_TAINTED)
unsigned lc_refcnt;
unsigned lc_binding;
......
......@@ -654,12 +654,26 @@ retry_lock:
(void *)lc, refcnt, binding );
/* Err could be -1 in case a duplicate ldapconn is inserted */
if ( rs->sr_err != 0 ) {
switch ( rs->sr_err ) {
case 0:
break;
case -1:
if ( !( sendok & LDAP_BACK_BINDING ) ) {
/* duplicate: free and try to get the newly created one */
goto retry_lock;
}
/* taint connection, so that it'll be freed when released */
LDAP_BACK_CONN_TAINTED_SET( lc );
break;
default:
ldap_back_conn_free( lc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "proxy bind collision";
if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
send_ldap_error( op, rs, LDAP_OTHER,
"internal server error" );
send_ldap_result( op, rs );
rs->sr_text = NULL;
}
return NULL;
}
......@@ -679,6 +693,7 @@ retry_lock:
(void *)avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
ldap_back_conndnlc_cmp );
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
LDAP_BACK_CONN_TAINTED_SET( lc );
}
if ( LogTest( LDAP_DEBUG_TRACE ) ) {
......@@ -688,7 +703,6 @@ retry_lock:
Debug( LDAP_DEBUG_TRACE,
"=>ldap_back_getconn: %s.\n", buf, 0, 0 );
}
}
if ( li->li_idle_timeout && lc ) {
......@@ -712,8 +726,10 @@ ldap_back_release_conn_lock(
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
}
assert( lc->lc_refcnt > 0 );
lc->lc_refcnt--;
LDAP_BACK_CONN_BINDING_CLEAR( lc );
if ( --lc->lc_refcnt == 0 && LDAP_BACK_CONN_TAINTED( lc ) ) {
ldap_back_freeconn( op, rs, 0 );
}
if ( dolock ) {
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
}
......
......@@ -293,9 +293,8 @@ extern void
meta_back_release_conn_lock(
Operation *op,
metaconn_t *mc,
int dofree,
int dolock );
#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 0, 1 )
#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 1 )
extern int
meta_back_retry(
......
......@@ -616,7 +616,8 @@ done:;
rs->sr_err = rc;
if ( rc != LDAP_SUCCESS && META_BACK_ONERR_STOP( mi ) ) {
LDAP_BACK_CONN_BINDING_CLEAR( msc );
meta_back_release_conn_lock( op, mc, 1, dolock );
LDAP_BACK_CONN_TAINTED_SET( mc );
meta_back_release_conn_lock( op, mc, dolock );
*mcp = NULL;
if ( sendok & LDAP_BACK_SENDERR ) {
......
......@@ -531,7 +531,8 @@ meta_back_retry(
if ( binding ) {
LDAP_BACK_CONN_BINDING_CLEAR( msc );
}
meta_back_release_conn_lock( op, mc, 1, 0 );
LDAP_BACK_CONN_TAINTED_SET( mc );
meta_back_release_conn_lock( op, mc, 0 );
*mcp = NULL;
}
......@@ -810,6 +811,7 @@ retry_lock:
/* don't let anyone else use this expired connection */
(void)avl_delete( &mi->mi_conninfo.lai_tree,
(caddr_t)mc, meta_back_conndnmc_cmp );
LDAP_BACK_CONN_TAINTED_SET( mc );
Debug( LDAP_DEBUG_TRACE, "%s meta_back_getconn: mc=%p conn=%ld expired.\n",
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc->mc_conn ) );
......@@ -1183,7 +1185,6 @@ done:;
}
if ( new_conn ) {
if ( mi->mi_conn_ttl ) {
mc->mc_create_time = op->o_time;
}
......@@ -1203,19 +1204,29 @@ done:;
/*
* Err could be -1 in case a duplicate metaconn is inserted
*
* FIXME: what if the same client issues more than one
* asynchronous operations?
*/
if ( err != 0 ) {
switch ( err ) {
case 0:
break;
case -1:
if ( !( sendok & LDAP_BACK_BINDING ) ) {
/* duplicate: free and try to get the newly created one */
goto retry_lock;
}
LDAP_BACK_CONN_TAINTED_SET( mc );
break;
default:
Debug( LDAP_DEBUG_ANY,
"%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
op->o_log_prefix, ncandidates,
LDAP_BACK_PCONN_ID( mc->mc_conn ) );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "Internal server error";
meta_back_freeconn( op, mc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "proxy bind collision";
if ( sendok & LDAP_BACK_SENDERR ) {
send_ldap_result( op, rs );
rs->sr_text = NULL;
......@@ -1242,7 +1253,6 @@ void
meta_back_release_conn_lock(
Operation *op,
metaconn_t *mc,
int dofree,
int dolock )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
......@@ -1255,10 +1265,7 @@ meta_back_release_conn_lock(
assert( mc->mc_refcnt > 0 );
mc->mc_refcnt--;
LDAP_BACK_CONN_BINDING_CLEAR( mc );
if ( dofree
|| ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl )
|| ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) )
{
if ( LDAP_BACK_CONN_TAINTED( mc ) ) {
Debug( LDAP_DEBUG_TRACE, "%s meta_back_release_conn: mc=%p conn=%ld expired.\n",
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc->mc_conn ) );
(void)avl_delete( &mi->mi_conninfo.lai_tree,
......
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