]> git.sur5r.net Git - openldap/commitdiff
import selected fixes/enhancements from HEAD (ITS#4387, partial ITS#4390)
authorPierangelo Masarati <ando@openldap.org>
Thu, 16 Feb 2006 23:21:27 +0000 (23:21 +0000)
committerPierangelo Masarati <ando@openldap.org>
Thu, 16 Feb 2006 23:21:27 +0000 (23:21 +0000)
14 files changed:
doc/man/man5/slapd-ldap.5
doc/man/man5/slapd-meta.5
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldap/search.c
servers/slapd/back-ldap/unbind.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/candidates.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/unbind.c

index 5e1070ad85807fb5f40deb499f97f0f8b7c378b1..192ab4fccccbcd4595102776e44380d346427857 100644 (file)
@@ -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
index 226b64be36ac3ca0f2ba8b4312fad79c5fe76afb..2bf1e8a0e83b1eda34e543577d498449ef400acc 100644 (file)
@@ -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
@@ -179,6 +184,15 @@ causes \fIl2.foo.com\fP to be contacted whenever \fIl1.foo.com\fP
 does not respond.
 .RE
 
+.TP
+.B subtree-exclude "<DN>"
+This directive instructs back-meta to ignore the current target
+for operations whose requestDN is subordinate to
+.BR DN .
+There may be multiple occurrences of the
+.B subtree-exclude
+directive for each of the targets.
+
 .TP
 .B acl-authcDN "<administrative DN for access control purposes>"
 DN which is used to query the target server for acl checking,
index dd16d53d05f5b769fdbcc4788b2e5441df75c8d3..2c14022d2fdeba7ec97ef9ba3175f7f5e8f37451 100644 (file)
@@ -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;
index 33d4545f8a5d0b608baecd858a0dfb22a164d766..ed478507eff9bff3c01a0dd49beacc998b8be78d 100644 (file)
 
 #include <lutil_ldap.h>
 
+#ifndef PRINT_CONNTREE
 #define PRINT_CONNTREE 0
+#endif /* !PRINT_CONNTREE */
+
+#define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ      "2.16.840.1.113730.3.4.12"
 
 static LDAP_REBIND_PROC        ldap_back_default_rebind;
 
@@ -118,12 +122,12 @@ retry_lock:;
 
                assert( lc->lc_refcnt == 1 );
                lc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
-                               ldap_back_conn_cmp );
+                               ldap_back_conndn_cmp );
                assert( lc != NULL );
 
                ber_bvreplace( &lc->lc_local_ndn, &op->o_req_ndn );
                lerr = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc,
-                       ldap_back_conn_cmp, ldap_back_conn_dup );
+                       ldap_back_conndn_cmp, ldap_back_conndn_dup );
                ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
                if ( lerr == -1 ) {
                        /* we can do this because lc_refcnt == 1 */
@@ -140,24 +144,43 @@ retry_lock:;
 }
 
 /*
- * ldap_back_conn_cmp
+ * ldap_back_conndn_cmp
  *
- * compares two ldapconn_t based on the value of the conn pointer;
- * used by avl stuff
+ * compares two ldapconn_t based on the value of the conn pointer
+ * and of the local DN; used by avl stuff for insert, lookup
+ * and direct delete
  */
 int
-ldap_back_conn_cmp( const void *c1, const void *c2 )
+ldap_back_conndn_cmp( const void *c1, const void *c2 )
 {
        const ldapconn_t        *lc1 = (const ldapconn_t *)c1;
        const ldapconn_t        *lc2 = (const ldapconn_t *)c2;
        int rc;
 
        /* If local DNs don't match, it is definitely not a match */
-       rc = ber_bvcmp( &lc1->lc_local_ndn, &lc2->lc_local_ndn );
-       if ( rc ) {
-               return rc;
+       /* For shared sessions, conn is NULL. Only explicitly
+        * bound sessions will have non-NULL conn.
+        */
+       rc = SLAP_PTRCMP( lc1->lc_conn, lc2->lc_conn );
+       if ( rc == 0 ) {
+               rc = ber_bvcmp( &lc1->lc_local_ndn, &lc2->lc_local_ndn );
        }
 
+       return rc;
+}
+
+/*
+ * ldap_back_conn_cmp
+ *
+ * compares two ldapconn_t based on the value of the conn pointer;
+ * used by avl stuff for delete of all conns with the same connid
+ */
+int
+ldap_back_conn_cmp( const void *c1, const void *c2 )
+{
+       const ldapconn_t        *lc1 = (const ldapconn_t *)c1;
+       const ldapconn_t        *lc2 = (const ldapconn_t *)c2;
+
        /* For shared sessions, conn is NULL. Only explicitly
         * bound sessions will have non-NULL conn.
         */
@@ -165,20 +188,20 @@ ldap_back_conn_cmp( const void *c1, const void *c2 )
 }
 
 /*
- * ldap_back_conn_dup
+ * ldap_back_conndn_dup
  *
  * returns -1 in case a duplicate ldapconn_t has been inserted;
  * used by avl stuff
  */
 int
-ldap_back_conn_dup( void *c1, void *c2 )
+ldap_back_conndn_dup( void *c1, void *c2 )
 {
        ldapconn_t      *lc1 = (ldapconn_t *)c1;
        ldapconn_t      *lc2 = (ldapconn_t *)c2;
 
        /* Cannot have more than one shared session with same DN */
-       if ( dn_match( &lc1->lc_local_ndn, &lc2->lc_local_ndn ) &&
-                               lc1->lc_conn == lc2->lc_conn )
+       if ( lc1->lc_conn == lc2->lc_conn &&
+               dn_match( &lc1->lc_local_ndn, &lc2->lc_local_ndn ) )
        {
                return -1;
        }
@@ -200,12 +223,13 @@ ravl_print( Avlnode *root, int depth )
        ravl_print( root->avl_right, depth+1 );
        
        for ( i = 0; i < depth; i++ ) {
-               printf( "   " );
+               fprintf( stderr, "-" );
        }
 
        lc = root->avl_data;
-       printf( "lc(%lx) local(%s) conn(%lx) %d\n",
-                       lc, lc->lc_local_ndn.bv_val, lc->lc_conn, root->avl_bf );
+       fprintf( stderr, "lc=%p local=\"%s\" conn=%p %s\n",
+               (void *)lc, lc->lc_local_ndn.bv_val, (void *)lc->lc_conn,
+               avl_bf2str( root->avl_bf) );
        
        ravl_print( root->avl_left, depth+1 );
 }
@@ -213,16 +237,16 @@ ravl_print( Avlnode *root, int depth )
 static void
 myprint( Avlnode *root )
 {
-       printf( "********\n" );
+       fprintf( stderr, "========>\n" );
        
        if ( root == 0 ) {
-               printf( "\tNULL\n" );
+               fprintf( stderr, "\tNULL\n" );
 
        } else {
                ravl_print( root, 0 );
        }
        
-       printf( "********\n" );
+       fprintf( stderr, "<========\n" );
 }
 #endif /* PRINT_CONNTREE */
 
@@ -238,7 +262,7 @@ ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock )
        assert( lc->lc_refcnt > 0 );
        if ( --lc->lc_refcnt == 0 ) {
                lc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
-                               ldap_back_conn_cmp );
+                               ldap_back_conndn_cmp );
                assert( lc != NULL );
 
                ldap_back_conn_free( (void *)lc );
@@ -459,6 +483,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;
@@ -496,7 +525,7 @@ retry_lock:
                ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
 
                lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, 
-                               (caddr_t)&lc_curr, ldap_back_conn_cmp );
+                               (caddr_t)&lc_curr, ldap_back_conndn_cmp );
                if ( lc != NULL ) {
                        /* Don't reuse connections while they're still binding */
                        if ( LDAP_BACK_CONN_BINDING( lc ) ) {
@@ -552,7 +581,7 @@ retry_lock:
                        lc_curr.lc_conn = LDAP_BACK_PCONN;
                        ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
                        tmplc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, 
-                                       (caddr_t)&lc_curr, ldap_back_conn_cmp );
+                                       (caddr_t)&lc_curr, ldap_back_conndn_cmp );
                        if ( tmplc != NULL ) {
                                refcnt = ++tmplc->lc_refcnt;
                                ldap_back_conn_free( lc );
@@ -573,7 +602,7 @@ retry_lock:
 
                assert( lc->lc_refcnt == 1 );
                rs->sr_err = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc,
-                       ldap_back_conn_cmp, ldap_back_conn_dup );
+                       ldap_back_conndn_cmp, ldap_back_conndn_dup );
 
 #if PRINT_CONNTREE > 0
                myprint( li->li_conninfo.lai_tree );
@@ -597,9 +626,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;
                        }
                }
index d115544201a2d654d68fe1a4fa69835f7038c450..6dd8363a19b3a0cb771adb986b98d2ca739a84eb 100644 (file)
@@ -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 );
@@ -1074,7 +1099,7 @@ done_url:;
                                                snprintf( c->msg, sizeof( c->msg ),
                                                        "\"idassert-bind <args>\": "
                                                        "unknown flag \"%s\"",
-                                                       c->fname, c->lineno, flags[ j ] );
+                                                       flags[ j ] );
                                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                                                return 1;
                                        }
@@ -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 "
index 7ac221b6b475f442d41c1aff2a001f29ba25493b..9d562a417a899ae90484cb890f47bcb5608cba07 100644 (file)
@@ -59,8 +59,9 @@ int ldap_back_op_result( ldapconn_t *lc, Operation *op, SlapReply *rs,
 
 int ldap_back_init_cf( BackendInfo *bi );
 
+extern int ldap_back_conndn_cmp( const void *c1, const void *c2);
 extern int ldap_back_conn_cmp( const void *c1, const void *c2);
-extern int ldap_back_conn_dup( void *c1, void *c2 );
+extern int ldap_back_conndn_dup( void *c1, void *c2 );
 extern void ldap_back_conn_free( void *c );
 
 extern int
index d0840b0be069ebc8ff4bcb9ce6ec3a8cda2114a1..2be811f1faad92907173adf33d03a4849e0690d2 100644 (file)
@@ -720,12 +720,14 @@ ldap_back_entry_get(
        struct berval   bdn;
        LDAPMessage     *result = NULL,
                        *e = NULL;
-       char            *gattr[3];
+       char            *attr[3], **attrp = NULL;
        char            *filter = NULL;
        SlapReply       rs;
        int             do_retry = 1;
        LDAPControl     **ctrls = NULL;
 
+       *ent = NULL;
+
        /* Tell getconn this is a privileged op */
        do_not_cache = op->o_do_not_cache;
        op->o_do_not_cache = 1;
@@ -737,14 +739,15 @@ ldap_back_entry_get(
        op->o_do_not_cache = do_not_cache;
 
        if ( at ) {
+               attrp = attr;
                if ( oc && at != slap_schema.si_ad_objectClass ) {
-                       gattr[0] = slap_schema.si_ad_objectClass->ad_cname.bv_val;
-                       gattr[1] = at->ad_cname.bv_val;
-                       gattr[2] = NULL;
+                       attr[0] = slap_schema.si_ad_objectClass->ad_cname.bv_val;
+                       attr[1] = at->ad_cname.bv_val;
+                       attr[2] = NULL;
 
                } else {
-                       gattr[0] = at->ad_cname.bv_val;
-                       gattr[1] = NULL;
+                       attr[0] = at->ad_cname.bv_val;
+                       attr[1] = NULL;
                }
        }
 
@@ -767,8 +770,8 @@ ldap_back_entry_get(
        
 retry:
        rc = ldap_search_ext_s( lc->lc_ld, ndn->bv_val, LDAP_SCOPE_BASE, filter,
-                               at ? gattr : NULL, 0, ctrls, NULL,
-                               LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result );
+                               attrp, 0, ctrls, NULL,
+                               NULL, LDAP_NO_LIMIT, &result );
        if ( rc != LDAP_SUCCESS ) {
                if ( rc == LDAP_SERVER_DOWN && do_retry ) {
                        do_retry = 0;
@@ -781,10 +784,15 @@ retry:
 
        e = ldap_first_entry( lc->lc_ld, result );
        if ( e == NULL ) {
+               /* the entry exists, but it doesn't match the filter? */
                goto cleanup;
        }
 
        *ent = ch_calloc( 1, sizeof( Entry ) );
+       if ( *ent == NULL ) {
+               rc = LDAP_NO_MEMORY;
+               goto cleanup;
+       }
 
        rc = ldap_build_entry( op, e, *ent, &bdn );
 
index 141ac4a4cb64a133a475401030e32c83f67f1a0c..faa4b527dc8bd461c6f3e6fa343a6dea3200cc79 100644 (file)
@@ -46,13 +46,10 @@ ldap_back_conn_destroy(
                conn->c_connid, 0, 0 );
 
        lc_curr.lc_conn = conn;
-       lc_curr.lc_local_ndn = conn->c_ndn;
        
        ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
-       lc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)&lc_curr, ldap_back_conn_cmp );
-       ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
-
-       if ( lc ) {
+       while ( ( lc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)&lc_curr, ldap_back_conn_cmp ) ) != NULL )
+       {
                Debug( LDAP_DEBUG_TRACE,
                        "=>ldap_back_conn_destroy: destroying conn %ld (refcnt=%u)\n",
                        LDAP_BACK_PCONN_ID( lc->lc_conn ), lc->lc_refcnt, 0 );
@@ -66,8 +63,7 @@ ldap_back_conn_destroy(
                 */
                ldap_back_conn_free( lc );
        }
-
-       /* no response to unbind */
+       ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
 
        return 0;
 }
index 5e2dbaf78ec45f63282645fbc3e885071f591040..2cf8369c7ca5fc908fc17fd03958950849ec1563 100644 (file)
@@ -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;
@@ -206,6 +207,7 @@ typedef struct metaconn_t {
 
 typedef struct metatarget_t {
        char                    *mt_uri;
+       BerVarray               mt_subtree_exclude;
        int                     mt_scope;
 
        struct berval           mt_psuffix;             /* pretty suffix */
@@ -228,6 +230,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 +277,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 ];
@@ -368,7 +372,12 @@ meta_back_conn_cmp(
        const void              *c2 );
 
 extern int
-meta_back_conn_dup(
+meta_back_dnconn_cmp(
+       const void              *c1,
+       const void              *c2 );
+
+extern int
+meta_back_dnconn_dup(
        void                    *c1,
        void                    *c2 );
 
@@ -379,6 +388,7 @@ extern int
 meta_back_is_candidate(
        struct berval           *nsuffix,
        int                     suffixscope,
+       BerVarray               subtree_exclude,
        struct berval           *ndn,
        int                     scope );
 
index 0540c23ec3796d88de70fb1c581c7d1153a3defd..9f5c0962dae51e0b22c5d3090b58d26a9cbfd318 100644 (file)
@@ -205,12 +205,12 @@ retry_lock:;
 
                        assert( mc->mc_refcnt == 1 );
                        mc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
-                               meta_back_conn_cmp );
+                               meta_back_dnconn_cmp );
                        assert( mc != NULL );
 
                        ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
                        lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
-                               meta_back_conn_cmp, meta_back_conn_dup );
+                               meta_back_dnconn_cmp, meta_back_dnconn_dup );
                        ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                        if ( lerr == -1 ) {
                                for ( i = 0; i < mi->mi_ntargets; ++i ) {
index e78b20602dc8ab5d4054a5467c32e4dcf1cda408..1986ab3bd6f45158343099039b1893463867fa8a 100644 (file)
@@ -61,10 +61,21 @@ int
 meta_back_is_candidate(
        struct berval   *nsuffix,
        int             suffixscope,
+       BerVarray       subtree_exclude,
        struct berval   *ndn,
        int             scope )
 {
        if ( dnIsSuffix( ndn, nsuffix ) ) {
+               if ( subtree_exclude ) {
+                       int     i;
+
+                       for ( i = 0; !BER_BVISNULL( &subtree_exclude[ i ] ); i++ ) {
+                               if ( dnIsSuffix( ndn, &subtree_exclude[ i ] ) ) {
+                                       return META_NOT_CANDIDATE;
+                               }
+                       }
+               }
+
                switch ( suffixscope ) {
                case LDAP_SCOPE_SUBTREE:
                default:
@@ -128,6 +139,7 @@ meta_back_select_unique_candidate(
        for ( i = 0; i < mi->mi_ntargets; ++i ) {
                if ( meta_back_is_candidate( &mi->mi_targets[ i ].mt_nsuffix,
                                mi->mi_targets[ i ].mt_scope,
+                               mi->mi_targets[ i ].mt_subtree_exclude,
                                ndn, LDAP_SCOPE_BASE ) )
                {
                        if ( candidate == META_TARGET_NONE ) {
index 229e70a9b0e57f687fcdc3b1ab0af30217483517..cf26945dfe3a2c5da9b0f908508495541f0fbde2 100644 (file)
@@ -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++ ) {
@@ -279,6 +280,82 @@ meta_back_db_config(
                }
 #endif
 
+       /* subtree-exclude */
+       } else if ( strcasecmp( argv[ 0 ], "subtree-exclude" ) == 0 ) {
+               int             i = mi->mi_ntargets - 1;
+               struct berval   dn, ndn;
+
+               if ( i < 0 ) {
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: need \"uri\" directive first\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+               
+               switch ( argc ) {
+               case 1:
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: missing DN in \"subtree-exclude <DN>\" line\n",
+                           fname, lineno, 0 );
+                       return 1;
+
+               case 2:
+                       break;
+
+               default:
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: too many args in \"subtree-exclude <DN>\" line\n",
+                           fname, lineno, 0 );
+                       return 1;
+               }
+
+               ber_str2bv( argv[ 1 ], 0, 0, &dn );
+               if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL )
+                       != LDAP_SUCCESS )
+               {
+                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                                       "subtree-exclude DN=\"%s\" is invalid\n",
+                                       fname, lineno, argv[ 1 ] );
+                       return( 1 );
+               }
+
+               if ( !dnIsSuffix( &ndn, &mi->mi_targets[ i ].mt_nsuffix ) ) {
+                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                                       "subtree-exclude DN=\"%s\" "
+                                       "must be subtree of target\n",
+                                       fname, lineno, argv[ 1 ] );
+                       ber_memfree( ndn.bv_val );
+                       return( 1 );
+               }
+
+               if ( mi->mi_targets[ i ].mt_subtree_exclude != NULL ) {
+                       int             j;
+
+                       for ( j = 0; !BER_BVISNULL( &mi->mi_targets[ i ].mt_subtree_exclude[ j ] ); j++ )
+                       {
+                               if ( dnIsSuffix( &mi->mi_targets[ i ].mt_subtree_exclude[ j ], &ndn ) ) {
+                                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                                                       "subtree-exclude DN=\"%s\" "
+                                                       "is suffix of another subtree-exclude\n",
+                                                       fname, lineno, argv[ 1 ] );
+                                       /* reject, because it might be superior
+                                        * to more than one subtree-exclude */
+                                       ber_memfree( ndn.bv_val );
+                                       return( 1 );
+
+                               } else if ( dnIsSuffix( &ndn, &mi->mi_targets[ i ].mt_subtree_exclude[ j ] ) ) {
+                                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                                                       "another subtree-exclude is suffix of "
+                                                       "subtree-exclude DN=\"%s\"\n",
+                                                       fname, lineno, argv[ 1 ] );
+                                       ber_memfree( ndn.bv_val );
+                                       return( 0 );
+                               }
+                       }
+               }
+
+               ber_bvarray_add( &mi->mi_targets[ i ].mt_subtree_exclude, &ndn );
+
        /* default target directive */
        } else if ( strcasecmp( argv[ 0 ], "default-target" ) == 0 ) {
                int             i = mi->mi_ntargets - 1;
@@ -346,7 +423,6 @@ meta_back_db_config(
 
        /* network timeout when connecting to ldap servers */
        } else if ( strcasecmp( argv[ 0 ], "network-timeout" ) == 0 ) {
-               int             i = mi->mi_ntargets - 1;
                unsigned long   t;
                time_t          *tp = mi->mi_ntargets ?
                                &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_network_timeout
@@ -371,7 +447,6 @@ meta_back_db_config(
 
        /* idle timeout when connecting to ldap servers */
        } else if ( strcasecmp( argv[ 0 ], "idle-timeout" ) == 0 ) {
-               int             i = mi->mi_ntargets - 1;
                unsigned long   t;
                time_t          *tp = mi->mi_ntargets ?
                                &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_idle_timeout
@@ -402,9 +477,40 @@ 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 ) {
-               int             i = mi->mi_ntargets - 1;
                unsigned long   t;
                struct timeval  *tp = mi->mi_ntargets ?
                                &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_bind_timeout
@@ -465,8 +571,7 @@ meta_back_db_config(
                        /* FIXME: some day we'll need to throw an error */
                }
 
-               dn.bv_val = argv[ 1 ];
-               dn.bv_len = strlen( argv[ 1 ] );
+               ber_str2bv( argv[ 1 ], 0, 0, &dn );
                if ( dnNormalize( 0, NULL, NULL, &dn, &mi->mi_targets[ i ].mt_binddn,
                        NULL ) != LDAP_SUCCESS )
                {
@@ -1129,7 +1234,7 @@ ldap_back_map_config(
                        || avl_find( map->remap, (caddr_t)&mapping[ 1 ], mapping_cmp ) != NULL)
        {
                Debug( LDAP_DEBUG_ANY,
-                       "%s: line %d: duplicate mapping found" SLAPD_CONF_UNKNOWN_IGNORED ".\n",
+                       "%s: line %d: duplicate mapping found.\n",
                        fname, lineno, 0 );
                goto error_return;
        }
index cd5bad958ac8095aba21d9477a9dac9f5f4306c5..7af76de1993274b5549764b5384f95956bdd6874 100644 (file)
 #define PRINT_CONNTREE 0
 
 /*
- * meta_back_conn_cmp
+ * meta_back_dnconn_cmp
  *
- * compares two struct metaconn based on the value of the conn pointer;
- * used by avl stuff
+ * compares two struct metaconn based on the value of the conn pointer
+ * and of the local DN; used by avl stuff
  */
 int
-meta_back_conn_cmp(
+meta_back_dnconn_cmp(
        const void *c1,
        const void *c2 )
 {
@@ -55,11 +55,31 @@ meta_back_conn_cmp(
        int             rc;
        
        /* If local DNs don't match, it is definitely not a match */
-       rc = ber_bvcmp( &mc1->mc_local_ndn, &mc2->mc_local_ndn );
-       if ( rc ) {
-               return rc;
+       /* For shared sessions, conn is NULL. Only explicitly
+        * bound sessions will have non-NULL conn.
+        */
+       rc = SLAP_PTRCMP( mc1->mc_conn, mc2->mc_conn );
+       if ( rc == 0 ) {
+               rc = ber_bvcmp( &mc1->mc_local_ndn, &mc2->mc_local_ndn );
        }
 
+       return rc;
+}
+
+/*
+ * meta_back_conn_cmp
+ *
+ * compares two struct metaconn based on the value of the conn pointer;
+ * used by avl stuff
+ */
+int
+meta_back_conn_cmp(
+       const void *c1,
+       const void *c2 )
+{
+       metaconn_t      *mc1 = ( metaconn_t * )c1;
+        metaconn_t     *mc2 = ( metaconn_t * )c2;
+       
        /* For shared sessions, conn is NULL. Only explicitly
         * bound sessions will have non-NULL conn.
         */
@@ -67,13 +87,13 @@ meta_back_conn_cmp(
 }
 
 /*
- * meta_back_conn_dup
+ * meta_back_dnconn_dup
  *
  * returns -1 in case a duplicate struct metaconn has been inserted;
  * used by avl stuff
  */
 int
-meta_back_conn_dup(
+meta_back_dnconn_dup(
        void *c1,
        void *c2 )
 {
@@ -81,8 +101,8 @@ meta_back_conn_dup(
        metaconn_t      *mc2 = ( metaconn_t * )c2;
 
        /* Cannot have more than one shared session with same DN */
-       if ( dn_match( &mc1->mc_local_ndn, &mc2->mc_local_ndn ) &&
-                               mc1->mc_conn == mc2->mc_conn )
+       if ( mc1->mc_conn == mc2->mc_conn &&
+               dn_match( &mc1->mc_local_ndn, &mc2->mc_local_ndn ) )
        {
                return -1;
        }
@@ -220,20 +240,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;
+               }
+
+               if ( mt->mt_idle_timeout != 0 ) {
+                       msc->msc_time = op->o_time;
                }
 
-               msc->msc_time = op->o_time;
+               if ( doreturn ) {
+                       return rs->sr_err = LDAP_SUCCESS;
+               }
        }
        
        /*
@@ -432,6 +460,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 ) {
@@ -618,6 +650,7 @@ meta_back_get_candidate(
                        if ( mi->mi_defaulttarget != META_DEFAULT_TARGET_NONE
                                && meta_back_is_candidate( &mi->mi_targets[ mi->mi_defaulttarget ].mt_nsuffix,
                                                mi->mi_targets[ mi->mi_defaulttarget ].mt_scope,
+                                               mi->mi_targets[ mi->mi_defaulttarget ].mt_subtree_exclude,
                                                ndn, op->o_tag == LDAP_REQ_SEARCH ? op->ors_scope : LDAP_SCOPE_BASE ) )
                        {
                                candidate = mi->mi_defaulttarget;
@@ -778,7 +811,7 @@ meta_back_getconn(
 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_conn_cmp );
+                       (caddr_t)&mc_curr, meta_back_dnconn_cmp );
                if ( mc ) {
                        if ( mc->mc_tainted ) {
                                rs->sr_err = LDAP_UNAVAILABLE;
@@ -935,7 +968,7 @@ retry_lock:
                                i = meta_back_get_candidate( op, rs, &pndn );
                        }
        
-                       if ( rs->sr_err != LDAP_SUCCESS ) {
+                       if ( i < 0 || rs->sr_err != LDAP_SUCCESS ) {
                                if ( mc != NULL ) {
                                        meta_back_release_conn( op, mc );
                                }
@@ -980,7 +1013,7 @@ retry_lock:
                        if ( !( sendok & LDAP_BACK_BINDING ) ) {
                                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_conn_cmp );
+                                       (caddr_t)&mc_curr, meta_back_dnconn_cmp );
                                if ( mc != NULL ) {
                                        mc->mc_refcnt++;
                                }
@@ -1062,6 +1095,7 @@ retry_lock:
                        if ( i == cached 
                                || meta_back_is_candidate( &mt->mt_nsuffix,
                                                mt->mt_scope,
+                                               mt->mt_subtree_exclude,
                                                &op->o_req_ndn,
                                                LDAP_SCOPE_SUBTREE ) )
                        {
@@ -1146,7 +1180,7 @@ done:;
                 */
                ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
                err = avl_insert( &mi->mi_conninfo.lai_tree, ( caddr_t )mc,
-                               meta_back_conn_cmp, meta_back_conn_dup );
+                               meta_back_dnconn_cmp, meta_back_dnconn_dup );
 
 #if PRINT_CONNTREE > 0
                myprint( mi->mi_conninfo.lai_tree );
@@ -1206,7 +1240,7 @@ meta_back_release_conn(
        LDAP_BACK_CONN_BINDING_CLEAR( mc );
        if ( mc->mc_refcnt == 0 && mc->mc_tainted ) {
                (void)avl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )mc,
-                               meta_back_conn_cmp );
+                               meta_back_dnconn_cmp );
                meta_back_conn_free( mc );
        }
        ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
index 6b08b50a7c24dc19d3fa38bdcd78ef9043e9bc94..0b301a242c5b6994a35869193793fdfaffa2d43c 100644 (file)
@@ -49,14 +49,10 @@ meta_back_conn_destroy(
                BER_BVISNULL( &conn->c_ndn ) ? "" : conn->c_ndn.bv_val, 0 );
        
        mc_curr.mc_conn = conn;
-       mc_curr.mc_local_ndn = conn->c_ndn;
        
        ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
-       mc = avl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )&mc_curr,
-                       meta_back_conn_cmp );
-       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
-
-       if ( mc ) {
+       while ( ( mc = avl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )&mc_curr, meta_back_conn_cmp ) ) != NULL )
+       {
                Debug( LDAP_DEBUG_TRACE,
                        "=>meta_back_conn_destroy: destroying conn %ld\n",
                        LDAP_BACK_PCONN_ID( mc->mc_conn ), 0, 0 );
@@ -65,6 +61,7 @@ meta_back_conn_destroy(
 
                meta_back_conn_free( mc );
        }
+       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
 
        /*
         * Cleanup rewrite session