Commit 7e8242d5 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

pool privileged connections (ITS#4791)

parent 1939ed3f
......@@ -44,22 +44,57 @@ typedef struct ldap_monitor_info_t {
struct berval lmi_more_filter;
} ldap_monitor_info_t;
enum {
/* even numbers are connection types */
LDAP_BACK_PCONN_FIRST = 0,
LDAP_BACK_PCONN_ROOTDN = LDAP_BACK_PCONN_FIRST,
LDAP_BACK_PCONN_ANON = 2,
LDAP_BACK_PCONN_BIND = 4,
/* add the TLS bit */
LDAP_BACK_PCONN_TLS = 0x1U,
LDAP_BACK_PCONN_ROOTDN_TLS = (LDAP_BACK_PCONN_ROOTDN|LDAP_BACK_PCONN_TLS),
LDAP_BACK_PCONN_ANON_TLS = (LDAP_BACK_PCONN_ANON|LDAP_BACK_PCONN_TLS),
LDAP_BACK_PCONN_BIND_TLS = (LDAP_BACK_PCONN_BIND|LDAP_BACK_PCONN_TLS),
LDAP_BACK_PCONN_LAST
};
typedef struct ldapconn_t {
Connection *lc_conn;
#define LDAP_BACK_PCONN ((void *)0x0)
#define LDAP_BACK_PCONN_TLS ((void *)0x1)
#define LDAP_BACK_PCONN_BIND ((void *)0x2)
#define LDAP_BACK_PCONN_BIND_TLS ((void *)0x3)
#define LDAP_BACK_PCONN_LAST ((void *)0x4)
#define LDAP_BACK_PCONN_ISPRIV(lc) ((void *)(lc)->lc_conn < LDAP_BACK_PCONN_LAST)
#define LDAP_BACK_PCONN_ID(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) ? ( -1 - (long)(lc)->lc_conn ): (lc)->lc_conn->c_connid )
#define LDAP_BACK_CONN2PRIV(lc) ((unsigned long)(lc)->lc_conn)
#define LDAP_BACK_PCONN_ISPRIV(lc) ((void *)(lc)->lc_conn >= (void *)LDAP_BACK_PCONN_FIRST \
&& (void *)(lc)->lc_conn < (void *)LDAP_BACK_PCONN_LAST)
#define LDAP_BACK_PCONN_ISROOTDN(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) \
&& (LDAP_BACK_CONN2PRIV((lc)) < LDAP_BACK_PCONN_ANON))
#define LDAP_BACK_PCONN_ISANON(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) \
&& (LDAP_BACK_CONN2PRIV((lc)) < LDAP_BACK_PCONN_BIND) \
&& (LDAP_BACK_CONN2PRIV((lc)) >= LDAP_BACK_PCONN_ANON))
#define LDAP_BACK_PCONN_ISBIND(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) \
&& (LDAP_BACK_CONN2PRIV((lc)) >= LDAP_BACK_PCONN_BIND))
#define LDAP_BACK_PCONN_ISTLS(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) \
&& (LDAP_BACK_CONN2PRIV((lc)) & LDAP_BACK_PCONN_TLS))
#define LDAP_BACK_PCONN_ID(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) ? \
( -1 - (long)(lc)->lc_conn ) : (lc)->lc_conn->c_connid )
#ifdef HAVE_TLS
#define LDAP_BACK_PCONN_SET(op) ((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_TLS : LDAP_BACK_PCONN)
#define LDAP_BACK_PCONN_BIND_SET(op) ((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_BIND_TLS : LDAP_BACK_PCONN_BIND)
#define LDAP_BACK_PCONN_ROOTDN_SET(lc, op) \
((lc)->lc_conn = (void *)((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_ROOTDN_TLS : LDAP_BACK_PCONN_ROOTDN))
#define LDAP_BACK_PCONN_ANON_SET(lc, op) \
((lc)->lc_conn = (void *)((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_ANON_TLS : LDAP_BACK_PCONN_ANON))
#define LDAP_BACK_PCONN_BIND_SET(lc, op) \
((lc)->lc_conn = (void *)((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_BIND_TLS : LDAP_BACK_PCONN_BIND))
#else /* ! HAVE_TLS */
#define LDAP_BACK_PCONN_SET(op) (LDAP_BACK_PCONN)
#define LDAP_BACK_PCONN_BIND_SET(op) (LDAP_BACK_PCONN_BIND)
#define LDAP_BACK_PCONN_ROOTDN_SET(lc, op) \
((lc)->lc_conn = (void *)LDAP_BACK_PCONN_ROOTDN)
#define LDAP_BACK_PCONN_ANON_SET(lc, op) \
((lc)->lc_conn = (void *)LDAP_BACK_PCONN_ANON)
#define LDAP_BACK_PCONN_BIND_SET(lc, op) \
((lc)->lc_conn = (void *)LDAP_BACK_PCONN_BIND)
#endif /* ! HAVE_TLS */
#define LDAP_BACK_PCONN_SET(lc, op) \
(BER_BVISEMPTY(&(op)->o_ndn) ? \
LDAP_BACK_PCONN_ANON_SET((lc), (op)) : LDAP_BACK_PCONN_ROOTDN_SET((lc), (op)))
LDAP *lc_ld;
struct berval lc_cred;
......@@ -93,6 +128,7 @@ typedef struct ldapconn_t {
#define LDAP_BACK_FCONN_BINDING (0x00000010U)
#define LDAP_BACK_FCONN_TAINTED (0x00000020U)
#define LDAP_BACK_FCONN_ISIDASR (0x00000040U)
#define LDAP_BACK_FCONN_CACHED (0x00000080U)
#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)
......@@ -120,12 +156,17 @@ typedef struct ldapconn_t {
#define LDAP_BACK_CONN_ISIDASSERT_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISIDASR)
#define LDAP_BACK_CONN_ISIDASSERT_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISIDASR)
#define LDAP_BACK_CONN_ISIDASSERT_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISIDASR, (mlc))
#define LDAP_BACK_CONN_CACHED(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_CACHED)
#define LDAP_BACK_CONN_CACHED_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_CACHED)
#define LDAP_BACK_CONN_CACHED_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_CACHED)
unsigned lc_refcnt;
unsigned lc_binding;
unsigned lc_flags;
time_t lc_create_time;
time_t lc_time;
LDAP_TAILQ_ENTRY(ldapconn_t) lc_q;
} ldapconn_t;
typedef struct ldap_avl_info_t {
......@@ -259,8 +300,11 @@ typedef struct ldapinfo_t {
#define LDAP_BACK_F_CANCEL_MASK (LDAP_BACK_F_CANCEL_IGNORE|LDAP_BACK_F_CANCEL_EXOP)
#define LDAP_BACK_F_CANCEL_MASK2 (LDAP_BACK_F_CANCEL_MASK|LDAP_BACK_F_CANCEL_EXOP_DISCOVER)
#define LDAP_BACK_ISSET(li,f) ( ( (li)->li_flags & (f) ) == (f) )
#define LDAP_BACK_ISMASK(li,m,f) ( ( (li)->li_flags & (m) ) == (f) )
#define LDAP_BACK_ISSET_F(ff,f) ( ( (ff) & (f) ) == (f) )
#define LDAP_BACK_ISMASK_F(ff,m,f) ( ( (ff) & (m) ) == (f) )
#define LDAP_BACK_ISSET(li,f) LDAP_BACK_ISSET_F( (li)->li_flags, (f) )
#define LDAP_BACK_ISMASK(li,m,f) LDAP_BACK_ISMASK_F( (li)->li_flags, (m), (f) )
#define LDAP_BACK_SAVECRED(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_SAVECRED )
#define LDAP_BACK_USE_TLS(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_USE_TLS )
......@@ -269,6 +313,10 @@ typedef struct ldapinfo_t {
#define LDAP_BACK_CHASE_REFERRALS(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_CHASE_REFERRALS )
#define LDAP_BACK_PROXY_WHOAMI(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_PROXY_WHOAMI )
#define LDAP_BACK_USE_TLS_F(ff) LDAP_BACK_ISSET_F( (ff), LDAP_BACK_F_USE_TLS )
#define LDAP_BACK_PROPAGATE_TLS_F(ff) LDAP_BACK_ISSET_F( (ff), LDAP_BACK_F_PROPAGATE_TLS )
#define LDAP_BACK_TLS_CRITICAL_F(ff) LDAP_BACK_ISSET_F( (ff), LDAP_BACK_F_TLS_CRITICAL )
#define LDAP_BACK_T_F(li) LDAP_BACK_ISMASK( (li), LDAP_BACK_F_T_F_MASK, LDAP_BACK_F_T_F )
#define LDAP_BACK_T_F_DISCOVER(li) LDAP_BACK_ISMASK( (li), LDAP_BACK_F_T_F_MASK2, LDAP_BACK_F_T_F_DISCOVER )
......@@ -285,10 +333,23 @@ typedef struct ldapinfo_t {
int li_version;
/* cached connections;
* special conns are in tailq rather than in tree */
ldap_avl_info_t li_conninfo;
ldap_monitor_info_t li_monitor_info;
struct {
int lic_num;
LDAP_TAILQ_HEAD(lc_conn_priv_q, ldapconn_t) lic_priv;
} li_conn_priv[ LDAP_BACK_PCONN_LAST ];
int li_conn_priv_max;
#define LDAP_BACK_CONN_PRIV_MIN (1)
#define LDAP_BACK_CONN_PRIV_MAX (256)
/* must be between LDAP_BACK_CONN_PRIV_MIN
* and LDAP_BACK_CONN_PRIV_MAX ! */
#define LDAP_BACK_CONN_PRIV_DEFAULT (16)
sig_atomic_t li_isquarantined;
#define LDAP_BACK_FQ_NO (0)
#define LDAP_BACK_FQ_YES (1)
......
This diff is collapsed.
......@@ -66,6 +66,7 @@ enum {
LDAP_BACK_CFG_VERSION,
LDAP_BACK_CFG_SINGLECONN,
LDAP_BACK_CFG_USETEMP,
LDAP_BACK_CFG_CONNPOOLMAX,
LDAP_BACK_CFG_CANCEL,
LDAP_BACK_CFG_QUARANTINE,
LDAP_BACK_CFG_REWRITE,
......@@ -286,6 +287,14 @@ static ConfigTable ldapcfg[] = {
"SYNTAX OMsBoolean "
"SINGLE-VALUE )",
NULL, NULL },
{ "conn-pool-max", "<n>", 2, 0, 0,
ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX,
ldap_back_cf_gen, "( OLcfgDbAt:3.23 "
"NAME 'olcDbConnectionPoolMax' "
"DESC 'Max size of privileged connections pool' "
"SYNTAX OMsInteger "
"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 },
......@@ -324,6 +333,7 @@ static ConfigOCs ldapocs[] = {
"$ olcDbCancel "
"$ olcDbQuarantine "
"$ olcDbUseTemporaryConn "
"$ olcDbConnectionPoolMax "
") )",
Cft_Database, ldapcfg},
{ NULL, 0, NULL }
......@@ -1060,6 +1070,10 @@ ldap_back_cf_gen( ConfigArgs *c )
c->value_int = LDAP_BACK_USE_TEMPORARIES( li );
break;
case LDAP_BACK_CFG_CONNPOOLMAX:
c->value_int = li->li_conn_priv_max;
break;
case LDAP_BACK_CFG_CANCEL: {
slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2;
......@@ -1190,6 +1204,10 @@ ldap_back_cf_gen( ConfigArgs *c )
li->li_flags &= ~LDAP_BACK_F_USE_TEMPORARIES;
break;
case LDAP_BACK_CFG_CONNPOOLMAX:
li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN;
break;
case LDAP_BACK_CFG_QUARANTINE:
if ( !LDAP_BACK_QUARANTINE( li ) ) {
break;
......@@ -1744,6 +1762,24 @@ done_url:;
}
break;
case LDAP_BACK_CFG_CONNPOOLMAX:
if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN
|| c->value_int > LDAP_BACK_CONN_PRIV_MAX )
{
snprintf( c->msg, sizeof( c->msg ),
"invalid max size " "of privileged "
"connections pool \"%s\" "
"in \"conn-pool-max <n> "
"(must be between %d and %d)\"",
c->argv[ 1 ],
LDAP_BACK_CONN_PRIV_MIN,
LDAP_BACK_CONN_PRIV_MAX );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
return 1;
}
li->li_conn_priv_max = c->value_int;
break;
case LDAP_BACK_CFG_CANCEL: {
slap_mask_t mask;
......
......@@ -102,6 +102,7 @@ ldap_back_db_init( Backend *be )
{
ldapinfo_t *li;
int rc;
unsigned i;
li = (ldapinfo_t *)ch_calloc( 1, sizeof( ldapinfo_t ) );
if ( li == NULL ) {
......@@ -146,6 +147,12 @@ ldap_back_db_init( Backend *be )
ldap_pvt_thread_mutex_init( &li->li_conninfo.lai_mutex );
for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
li->li_conn_priv[ i ].lic_num = 0;
LDAP_TAILQ_INIT( &li->li_conn_priv[ i ].lic_priv );
}
li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_DEFAULT;
be->be_private = li;
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_NOLASTMOD;
......@@ -244,6 +251,8 @@ ldap_back_conn_free( void *v_lc )
if ( !BER_BVISNULL( &lc->lc_local_ndn ) ) {
ch_free( lc->lc_local_ndn.bv_val );
}
lc->lc_q.tqe_prev = NULL;
lc->lc_q.tqe_next = NULL;
ch_free( lc );
}
......@@ -264,6 +273,7 @@ ldap_back_db_destroy( Backend *be )
{
if ( be->be_private ) {
ldapinfo_t *li = ( ldapinfo_t * )be->be_private;
unsigned i;
(void)ldap_back_monitor_db_destroy( be );
......@@ -328,6 +338,14 @@ ldap_back_db_destroy( Backend *be )
if ( li->li_conninfo.lai_tree ) {
avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free );
}
for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
while ( !LDAP_TAILQ_EMPTY( &li->li_conn_priv[ i ].lic_priv ) ) {
ldapconn_t *lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ i ].lic_priv );
LDAP_TAILQ_REMOVE( &li->li_conn_priv[ i ].lic_priv, lc, lc_q );
ldap_back_conn_free( lc );
}
}
if ( LDAP_BACK_QUARANTINE( li ) ) {
slap_retry_info_destroy( &li->li_quarantine );
ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex );
......
......@@ -45,7 +45,6 @@ extern BI_connection_destroy ldap_back_conn_destroy;
extern BI_entry_get_rw ldap_back_entry_get;
int ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock );
void ldap_back_release_conn_lock( Operation *op, SlapReply *rs, ldapconn_t **lcp, int dolock );
#define ldap_back_release_conn(op, rs, lc) ldap_back_release_conn_lock((op), (rs), &(lc), 1)
int ldap_back_dobind( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
......@@ -83,7 +82,7 @@ ldap_back_quarantine(
#ifdef LDAP_BACK_PRINT_CONNTREE
extern void
ldap_back_print_conntree( Avlnode *root, char *msg );
ldap_back_print_conntree( ldapinfo_t *li, char *msg );
#endif /* LDAP_BACK_PRINT_CONNTREE */
extern void slap_retry_info_destroy( slap_retry_info_t *ri );
......
......@@ -49,7 +49,7 @@ ldap_back_conn_destroy(
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
#if LDAP_BACK_PRINT_CONNTREE > 0
ldap_back_print_conntree( li->li_conninfo.lai_tree, ">>> ldap_back_conn_destroy" );
ldap_back_print_conntree( li, ">>> ldap_back_conn_destroy" );
#endif /* LDAP_BACK_PRINT_CONNTREE */
while ( ( lc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)&lc_curr, ldap_back_conn_cmp ) ) != NULL )
{
......@@ -67,7 +67,7 @@ ldap_back_conn_destroy(
ldap_back_conn_free( lc );
}
#if LDAP_BACK_PRINT_CONNTREE > 0
ldap_back_print_conntree( li->li_conninfo.lai_tree, "<<< ldap_back_conn_destroy" );
ldap_back_print_conntree( li, "<<< ldap_back_conn_destroy" );
#endif /* LDAP_BACK_PRINT_CONNTREE */
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
......
......@@ -241,6 +241,8 @@ typedef struct metaconn_t {
struct metainfo_t *mc_info;
LDAP_TAILQ_ENTRY(metaconn_t) mc_q;
/* supersedes the connection stuff */
metasingleconn_t mc_conns[ 1 ];
/* NOTE: mc_conns must be last, because
......@@ -346,7 +348,14 @@ typedef struct metainfo_t {
metadncache_t mi_cache;
/* cached connections;
* special conns are in tailq rather than in tree */
ldap_avl_info_t mi_conninfo;
struct {
int mic_num;
LDAP_TAILQ_HEAD(mc_conn_priv_q, metaconn_t) mic_priv;
} mi_conn_priv[ LDAP_BACK_PCONN_LAST ];
int mi_conn_priv_max;
/* NOTE: quarantine uses the connection mutex */
slap_retry_info_t mi_quarantine;
......@@ -417,7 +426,7 @@ meta_back_conn_free(
#if META_BACK_PRINT_CONNTREE > 0
extern void
meta_back_print_conntree(
Avlnode *root,
metainfo_t *mi,
char *msg );
#endif
......
......@@ -220,7 +220,7 @@ retry_lock:;
assert( mc->mc_refcnt == 1 );
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_bind" );
meta_back_print_conntree( mi, ">>> meta_back_bind" );
#endif /* META_BACK_PRINT_CONNTREE */
tmpmc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
meta_back_conndn_cmp );
......@@ -252,12 +252,12 @@ retry_lock:;
ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
if ( isroot ) {
LDAP_BACK_CONN_ISPRIV_SET( mc );
mc->mc_conn = LDAP_BACK_PCONN_SET( op );
LDAP_BACK_PCONN_SET( mc, op );
}
lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
meta_back_conndn_cmp, meta_back_conndn_dup );
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_bind" );
meta_back_print_conntree( mi, "<<< meta_back_bind" );
#endif /* META_BACK_PRINT_CONNTREE */
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
if ( lerr == -1 ) {
......
......@@ -877,6 +877,32 @@ meta_back_db_config(
return 1;
}
/* privileged connections pool max size ? */
} else if ( strcasecmp( argv[ 0 ], "conn-pool-max" ) == 0 ) {
if ( argc != 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"conn-pool-max <n>\" takes 1 argument\n",
fname, lineno, 0 );
return( 1 );
}
if ( mi->mi_ntargets > 0 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"conn-pool-max\" must appear before target definitions\n",
fname, lineno, 0 );
return( 1 );
}
if ( lutil_atoi( &mi->mi_conn_priv_max, argv[1] )
|| mi->mi_conn_priv_max < LDAP_BACK_CONN_PRIV_MIN
|| mi->mi_conn_priv_max > LDAP_BACK_CONN_PRIV_MAX )
{
Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"conn-pool-max <n>\": invalid arg \"%s\".\n",
fname, lineno, argv[ 1 ] );
return 1;
}
} else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) {
unsigned flag = 0;
unsigned *flagsp = mi->mi_ntargets ?
......
<
......@@ -140,7 +140,7 @@ meta_back_conndn_dup(
*/
#if META_BACK_PRINT_CONNTREE > 0
static void
ravl_print( Avlnode *root, int depth )
meta_back_ravl_print( Avlnode *root, int depth )
{
int i;
metaconn_t *mc;
......@@ -149,7 +149,7 @@ ravl_print( Avlnode *root, int depth )
return;
}
ravl_print( root->avl_right, depth + 1 );
meta_back_ravl_print( root->avl_right, depth + 1 );
for ( i = 0; i < depth; i++ ) {
fprintf( stderr, "-" );
......@@ -163,19 +163,49 @@ ravl_print( Avlnode *root, int depth )
avl_bf2str( root->avl_bf ), mc->mc_refcnt,
LDAP_BACK_CONN_TAINTED( mc ) ? " tainted" : "" );
ravl_print( root->avl_left, depth + 1 );
meta_back_ravl_print( root->avl_left, depth + 1 );
}
/* NOTE: duplicate from back-ldap/bind.c */
static char* priv2str[] = {
"privileged",
"privileged/TLS",
"anonymous",
"anonymous/TLS",
"bind",
"bind/TLS",
NULL
};
void
meta_back_print_conntree( Avlnode *root, char *msg )
meta_back_print_conntree( metainfo_t *mi, char *msg )
{
int c;
fprintf( stderr, "========> %s\n", msg );
if ( root == 0 ) {
for ( c = LDAP_BACK_PCONN_FIRST; c < LDAP_BACK_PCONN_LAST; c++ ) {
int i = 0;
metaconn_t *mc;
fprintf( stderr, " %s[%d]\n", priv2str[ c ], mi->mi_conn_priv[ c ].mic_num );
LDAP_TAILQ_FOREACH( mc, &mi->mi_conn_priv[ c ].mic_priv, mc_q )
{
fprintf( stderr, " [%d] mc=%p local=\"%s\" conn=%p refcnt=%d flags=0x%08x\n",
i,
(void *)mc,
mc->mc_local_ndn.bv_val ? mc->mc_local_ndn.bv_val : "",
(void *)mc->mc_conn, mc->mc_refcnt, mc->msc_mscflags );
i++;
}
}
if ( mi->mi_conninfo.lai_tree == NULL ) {
fprintf( stderr, "\t(empty)\n" );
} else {
ravl_print( root, 0 );
meta_back_ravl_print( mi->mi_conninfo.lai_tree, 0 );
}
fprintf( stderr, "<======== %s\n", msg );
......@@ -708,13 +738,33 @@ meta_back_retry(
} else {
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_retry" );
meta_back_print_conntree( mi, ">>> meta_back_retry" );
#endif /* META_BACK_PRINT_CONNTREE */
/* FIXME: could be done better, reworking meta_back_release_conn_lock() */
(void)avl_delete( &mi->mi_conninfo.lai_tree,
( caddr_t )mc, meta_back_conndnmc_cmp );
if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
if ( mc->mc_q.tqe_prev != NULL ) {
assert( LDAP_BACK_CONN_CACHED( mc ) );
assert( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num > 0 );
LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
mc, mc_q );
mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num--;
mc->mc_q.tqe_prev = NULL;
mc->mc_q.tqe_next = NULL;
} else {
assert( !LDAP_BACK_CONN_CACHED( mc ) );
}
} else {
/* FIXME: check if in tree, for consistency? */
(void)avl_delete( &mi->mi_conninfo.lai_tree,
( caddr_t )mc, meta_back_conndnmc_cmp );
}
LDAP_BACK_CONN_CACHED_CLEAR( mc );
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_retry" );
meta_back_print_conntree( mi, "<<< meta_back_retry" );
#endif /* META_BACK_PRINT_CONNTREE */
}
}
......@@ -970,7 +1020,7 @@ meta_back_getconn(
if ( META_BACK_PROXYAUTHZ_ALWAYS( mi ) || op->o_do_not_cache || be_isroot( op ) ) {
mc_curr.mc_local_ndn = op->o_bd->be_rootndn;
LDAP_BACK_CONN_ISPRIV_SET( &mc_curr );
mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
LDAP_BACK_PCONN_ROOTDN_SET( &mc_curr, op );
} else {
mc_curr.mc_local_ndn = op->o_ndn;
......@@ -980,7 +1030,8 @@ meta_back_getconn(
mc_curr.mc_conn = op->o_conn;
} else {
mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
LDAP_BACK_CONN_ISANON_SET( &mc_curr );
LDAP_BACK_PCONN_ANON_SET( &mc_curr, op );
}
}
......@@ -989,8 +1040,41 @@ meta_back_getconn(
/* Searches for a metaconn in the avl tree */
retry_lock:;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree,
(caddr_t)&mc_curr, meta_back_conndn_cmp );
if ( LDAP_BACK_PCONN_ISPRIV( &mc_curr ) ) {
/* lookup a conn that's not binding */
LDAP_TAILQ_FOREACH( mc,
&mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_priv,
mc_q )
{
if ( !LDAP_BACK_CONN_BINDING( mc ) && mc->mc_refcnt == 0 ) {
break;
}
}
if ( mc != NULL ) {
if ( mc != LDAP_TAILQ_LAST( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
metaconn_t, mc_q ) )
{
LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
mc, mc_q );
mc->mc_q.tqe_prev = NULL;
mc->mc_q.tqe_next = NULL;
LDAP_TAILQ_INSERT_TAIL( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
mc, mc_q );
}
} else if ( !LDAP_BACK_USE_TEMPORARIES( mi )
&& mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_num == mi->mi_conn_priv_max )
{
mc = LDAP_TAILQ_FIRST( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_priv );
}
} else {
mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree,
(caddr_t)&mc_curr, meta_back_conndn_cmp );
}
if ( mc ) {
/* catch taint errors */
assert( !LDAP_BACK_CONN_TAINTED( mc ) );
......@@ -1013,17 +1097,36 @@ retry_lock:;
|| ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) )
{
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree,
meta_back_print_conntree( mi,
">>> meta_back_getconn(expired)" );
#endif /* META_BACK_PRINT_CONNTREE */
/* don't let anyone else use this expired connection */
(void)avl_delete( &mi->mi_conninfo.lai_tree,
(caddr_t)mc, meta_back_conndnmc_cmp );
if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
if ( mc->mc_q.tqe_prev != NULL ) {
assert( LDAP_BACK_CONN_CACHED( mc ) );
assert( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num > 0 );
LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
mc, mc_q );
mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num--;
mc->mc_q.tqe_prev = NULL;
mc->mc_q.tqe_next = NULL;
} else {
assert( !LDAP_BACK_CONN_CACHED( mc ) );
}
} else {
(void)avl_delete( &mi->mi_conninfo.lai_tree,
(caddr_t)mc, meta_back_conndnmc_cmp );
}
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree,
meta_back_print_conntree( mi,
"<<< meta_back_getconn(expired)" );
#endif /* META_BACK_PRINT_CONNTREE */
LDAP_BACK_CONN_TAINTED_SET( mc );
LDAP_BACK_CONN_CACHED_CLEAR( mc );
Debug( LDAP_DEBUG_TRACE, "%s meta_back_getconn: mc=%p conn=%ld expired (tainted).\n",
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc ) );
......@@ -1092,6 +1195,9 @@ retry_lock:;
}
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
LDAP_BACK_CONN_ISPRIV_SET( mc );
} else if ( LDAP_BACK_CONN_ISANON( &mc_curr ) ) {