]> git.sur5r.net Git - openldap/commitdiff
/tmp/msg
authorRalf Haferkamp <ralf@openldap.org>
Thu, 27 Sep 2007 23:14:23 +0000 (23:14 +0000)
committerRalf Haferkamp <ralf@openldap.org>
Thu, 27 Sep 2007 23:14:23 +0000 (23:14 +0000)
19 files changed:
servers/slapd/acl.c
servers/slapd/back-bdb/search.c
servers/slapd/back-meta/conn.c
servers/slapd/back-sql/delete.c
servers/slapd/compare.c
servers/slapd/filter.c
servers/slapd/init.c
servers/slapd/main.c
servers/slapd/overlays/accesslog.c
servers/slapd/overlays/dynlist.c
servers/slapd/overlays/pcache.c
servers/slapd/overlays/syncprov.c
servers/slapd/proto-slap.h
servers/slapd/slap.h
servers/slapd/syncrepl.c
tests/data/proxycache.out
tests/data/slapd-proxycache.conf
tests/scripts/conf.sh
tests/scripts/test020-proxycache

index 14cc43894f160a2a3d421b4346d1fd003168dbf0..5647ce57fda2ed7ffe170206db330da0386ac6bb 100644 (file)
@@ -2078,7 +2078,6 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
        slap_callback           cb = { NULL, acl_set_cb_gather, NULL, NULL };
        acl_set_gather_t        p = { 0 };
        const char              *text = NULL;
-       static struct berval    defaultFilter_bv = BER_BVC( "(objectClass=*)" );
 
        /* this routine needs to return the bervals instead of
         * plain strings, since syntax is not known.  It should
@@ -2121,16 +2120,17 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
        if ( ludp->lud_filter ) {
                ber_str2bv_x( ludp->lud_filter, 0, 0, &op2.ors_filterstr,
                                cp->asc_op->o_tmpmemctx );
+               op2.ors_filter = str2filter_x( cp->asc_op, op2.ors_filterstr.bv_val );
+               if ( op2.ors_filter == NULL ) {
+                       rc = LDAP_PROTOCOL_ERROR;
+                       goto url_done;
+               }
                
        } else {
-               op2.ors_filterstr = defaultFilter_bv;
+               op2.ors_filterstr = *slap_filterstr_objectClass_pres;
+               op2.ors_filter = slap_filter_objectClass_pres;
        }
 
-       op2.ors_filter = str2filter_x( cp->asc_op, op2.ors_filterstr.bv_val );
-       if ( op2.ors_filter == NULL ) {
-               rc = LDAP_PROTOCOL_ERROR;
-               goto url_done;
-       }
 
        /* Grab the scope */
        op2.ors_scope = ludp->lud_scope;
@@ -2186,7 +2186,7 @@ acl_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
        }
 
 url_done:;
-       if ( op2.ors_filter ) {
+       if ( op2.ors_filter && op2.ors_filter != slap_filter_objectClass_pres ) {
                filter_free_x( cp->asc_op, op2.ors_filter );
        }
        if ( !BER_BVISNULL( &op2.o_req_ndn ) ) {
index 5f0f583c693a6268d054c150001ee4993786b84d..17c1a84a2ec0f54462834a367827087925302b56 100644 (file)
@@ -154,11 +154,7 @@ static int search_aliases(
        Entry *matched, *a;
        EntryInfo *ei;
        struct berval bv_alias = BER_BVC( "alias" );
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion aa_alias = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion aa_alias = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion aa_alias = ATTRIBUTEASSERTION_INIT;
        Filter  af;
        DB_LOCK locka, lockr;
        int first = 1;
@@ -1028,17 +1024,9 @@ static int search_candidates(
        int rc, depth = 1;
        Filter          f, rf, xf, nf;
        ID              *stack;
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion aa_ref = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion aa_ref = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion aa_ref = ATTRIBUTEASSERTION_INIT;
        Filter  sf;
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion aa_subentry = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion aa_subentry = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion aa_subentry = ATTRIBUTEASSERTION_INIT;
 
        /*
         * This routine takes as input a filter (user-filter)
index e5d84842f853eefa03de77d4ddc6e12d46ae40fc..ed7ff743cce025b8207055c7fa3954523a7edc22 100644 (file)
@@ -849,7 +849,6 @@ meta_back_get_candidate(
                rs->sr_text = "No suitable candidate target found";
 
        } else if ( candidate == META_TARGET_MULTIPLE ) {
-               Filter          f = { 0 };
                Operation       op2 = *op;
                SlapReply       rs2 = { 0 };
                slap_callback   cb2 = { 0 };
@@ -868,10 +867,8 @@ meta_back_get_candidate(
                op2.ors_slimit = 1;
                op2.ors_tlimit = SLAP_NO_LIMIT;
 
-               f.f_choice = LDAP_FILTER_PRESENT;
-               f.f_desc = slap_schema.si_ad_objectClass;
-               op2.ors_filter = &f;
-               BER_BVSTR( &op2.ors_filterstr, "(objectClass=*)" );
+               op2.ors_filter = slap_filter_objectClass_pres;
+               op2.ors_filterstr = *slap_filterstr_objectClass_pres;
 
                op2.o_callback = &cb2;
                cb2.sc_response = meta_back_conn_cb;
index c04acb0a8df522ec5ff98486bea581d66d06c37e..15dd62a28abe2afbd40a8ef03fe4bcce63f30cb9 100644 (file)
@@ -336,7 +336,6 @@ backsql_tree_delete(
        Operation               op2 = *op;
        slap_callback           sc = { 0 };
        SlapReply               rs2 = { 0 };
-       Filter                  f = { 0 };
        backsql_tree_delete_t   btd = { 0 };
 
        int                     rc;
@@ -368,10 +367,8 @@ backsql_tree_delete(
        op2.ors_deref = LDAP_DEREF_NEVER;
        op2.ors_slimit = SLAP_NO_LIMIT;
        op2.ors_tlimit = SLAP_NO_LIMIT;
-       op2.ors_filter = &f;
-       f.f_choice = LDAP_FILTER_PRESENT;
-       f.f_desc = slap_schema.si_ad_objectClass;
-       BER_BVSTR( &op2.ors_filterstr, "(objectClass=*)" );
+       op2.ors_filter = slap_filter_objectClass_pres;
+       op2.ors_filterstr = *slap_filterstr_objectClass_pres;
        op2.ors_attrs = slap_anlist_all_attributes;
        op2.ors_attrsonly = 0;
 
index 900f585fa4a8d2031f6ac4ed84060cc7b4f4fcba..eaee0c0e9bd3ceecc9f2e2cda2e8f1bd84b6a0a4 100644 (file)
@@ -44,7 +44,7 @@ do_compare(
        struct berval dn = BER_BVNULL;
        struct berval desc = BER_BVNULL;
        struct berval value = BER_BVNULL;
-       AttributeAssertion ava = { 0 };
+       AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
 
        Debug( LDAP_DEBUG_TRACE, "%s do_compare\n",
                op->o_log_prefix, 0, 0 );
index d3ceb0b8a8c78d43e9db15c133e6f509daf2d4d4..5eac384b758ee3fba02c63ce3ac4b6b2671c3e12 100644 (file)
@@ -33,6 +33,9 @@
 
 #include "slap.h"
 
+const Filter *slap_filter_objectClass_pres;
+const struct berval *slap_filterstr_objectClass_pres;
+
 static int     get_filter_list(
        Operation *op,
        BerElement *ber,
@@ -56,6 +59,26 @@ static int   get_simple_vrFilter(
        ValuesReturnFilter **f,
        const char **text );
 
+int
+filter_init( void )
+{
+       static Filter filter_objectClass_pres = { LDAP_FILTER_PRESENT };
+       static struct berval filterstr_objectClass_pres = BER_BVC("(objectClass=*)");
+
+       filter_objectClass_pres.f_desc = slap_schema.si_ad_objectClass;
+
+       slap_filter_objectClass_pres = &filter_objectClass_pres;
+       slap_filterstr_objectClass_pres = &filterstr_objectClass_pres;
+
+       return 0;
+}
+
+void
+filter_destroy( void )
+{
+       return;
+}
+
 int
 get_filter(
        Operation *op,
index 5666a49b992bbeb4cf802fc0ff2742ddee95fd16..28f30521c6913a6eec4709a5538f39a5f9461421 100644 (file)
@@ -112,6 +112,14 @@ slap_init( int mode, const char *name )
                return 1;
        }
 
+       if ( filter_init() != 0 ) {
+               slap_debug |= LDAP_DEBUG_NONE;
+               Debug( LDAP_DEBUG_ANY,
+                   "%s: filter_init failed\n",
+                   name, 0, 0 );
+               return 1;
+       }
+
        if ( entry_init() != 0 ) {
                slap_debug |= LDAP_DEBUG_NONE;
                Debug( LDAP_DEBUG_ANY,
index 8c890e506de3f189891d61ee6c0b00c03c76842e..86b61dd0e254df0555173c3e5f3174fc77ba3e16 100644 (file)
@@ -984,6 +984,8 @@ stop:
 
        controls_destroy();
 
+       filter_destroy();
+
        schema_destroy();
 
        lutil_passwd_destroy();
index 983395a8aaa7501ab14ef5be398ef2f83988bd3a..b034d061cb7ce3ceb5766f5811031b9fe3beb9d4 100644 (file)
@@ -596,7 +596,7 @@ accesslog_purge( void *ctx, void *arg )
        SlapReply rs = {REP_RESULT};
        slap_callback cb = { NULL, log_old_lookup, NULL, NULL };
        Filter f;
-       AttributeAssertion ava = {0};
+       AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
        purge_data pd = {0};
        char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE];
        char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
index da0528ec1aad2c98056ca1f008918888505a9697..87b1f15ac701a07cfc1042cb2ca168992c7de812 100644 (file)
@@ -629,12 +629,8 @@ dynlist_compare( Operation *op, SlapReply *rs )
                        goto release;
                }
 
-               BER_BVSTR( &o.ors_filterstr, "(objectClass=*)" );
-               o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val );
-               if ( o.ors_filter == NULL ) {
-                       /* FIXME: error? */
-                       goto release;
-               }
+               o.ors_filterstr = *slap_filterstr_objectClass_pres;
+               o.ors_filter = slap_filter_objectClass_pres;
 
                o.ors_scope = LDAP_SCOPE_BASE;
                o.ors_deref = LDAP_DEREF_NEVER;
@@ -647,7 +643,6 @@ dynlist_compare( Operation *op, SlapReply *rs )
                o.o_acl_priv = ACL_COMPARE;
 
                rc = o.o_bd->be_search( &o, &r );
-               filter_free_x( &o, o.ors_filter );
 
                if ( o.o_dn.bv_val != op->o_dn.bv_val ) {
                        slap_op_groups_free( &o );
index 58c5e1e81e49dba813b056f372227a7926e8bcb3..71e04db825d56d34303df1d6b5aaf11bc6d9d9eb 100644 (file)
@@ -72,12 +72,14 @@ typedef struct cached_query_s {
        Qbase                                   *qbase;
        int                                             scope;
        struct berval                   q_uuid;         /* query identifier */
+       int                                             q_sizelimit;
        struct query_template_s         *qtemp; /* template of the query */
-       time_t                          expiry_time;    /* time till the query is considered valid */
+       time_t                                          expiry_time;    /* time till the query is considered valid */
        struct cached_query_s           *next;          /* next query in the template */
        struct cached_query_s           *prev;          /* previous query in the template */
-       struct cached_query_s           *lru_up;        /* previous query in the LRU list */
-       struct cached_query_s           *lru_down;      /* next query in the LRU list */
+       struct cached_query_s           *lru_up;        /* previous query in the LRU list */
+       struct cached_query_s           *lru_down;      /* next query in the LRU list */
+       ldap_pvt_thread_rdwr_t          rwlock;
 } CachedQuery;
 
 /*
@@ -127,17 +129,36 @@ typedef struct query_template_s {
        int             no_of_queries;  /* Total number of queries in the template */
        time_t          ttl;            /* TTL for the queries of this template */
        time_t          negttl;         /* TTL for negative results */
+       time_t          limitttl;       /* TTL for sizelimit exceeding results */
        struct attr_set t_attrs;        /* filter attrs + attr_set */
 } QueryTemplate;
 
+typedef enum {
+       PC_IGNORE = 0,
+       PC_POSITIVE,
+       PC_NEGATIVE,
+       PC_SIZELIMIT
+} pc_caching_reason_t;
+
+static const char *pc_caching_reason_str[] = {
+       "IGNORE",
+       "POSITIVE",
+       "NEGATIVE",
+       "SIZELIMIT",
+
+       NULL
+};
+
 struct query_manager_s;
 
 /* prototypes for functions for 1) query containment
  * 2) query addition, 3) cache replacement
  */
-typedef CachedQuery *  (QCfunc)(Operation *op, struct query_manager_s*, Query*, QueryTemplate*);
-typedef CachedQuery *  (AddQueryfunc)(Operation *op, struct query_manager_s*, Query*, QueryTemplate*, int positive);
-typedef void   (CRfunc)(struct query_manager_s*, struct berval * );
+typedef CachedQuery *(QCfunc)(Operation *op, struct query_manager_s*,
+       Query*, QueryTemplate*);
+typedef CachedQuery *(AddQueryfunc)(Operation *op, struct query_manager_s*,
+       Query*, QueryTemplate*, pc_caching_reason_t, int wlock);
+typedef void (CRfunc)(struct query_manager_s*, struct berval*);
 
 /* LDAP query cache */
 typedef struct query_manager_s {
@@ -225,7 +246,8 @@ add_query(
        query_manager* qm,
        Query* query,
        QueryTemplate *templ,
-       int positive);
+       pc_caching_reason_t why,
+       int wlock);
 
 static int
 remove_query_data(
@@ -452,7 +474,7 @@ url2query(
                        goto error;
                }
 
-               cq = add_query( op, qm, &query, qt, 1 );
+               cq = add_query( op, qm, &query, qt, PC_POSITIVE, 0 );
                if ( cq != NULL ) {
                        cq->expiry_time = expiry_time;
                        cq->q_uuid = uuid;
@@ -1093,6 +1115,10 @@ query_containment(Operation *op, query_manager *qm,
                                        qc = find_filter( op, qbptr->scopes[tscope],
                                                        query->filter, first );
                                        if ( qc ) {
+                                               if ( qc->q_sizelimit ) {
+                                                       ldap_pvt_thread_rdwr_runlock(&templa->t_rwlock);
+                                                       return NULL;
+                                               }
                                                ldap_pvt_thread_mutex_lock(&qm->lru_mutex);
                                                if (qm->lru_top != qc) {
                                                        remove_query(qm, qc);
@@ -1128,35 +1154,57 @@ free_query (CachedQuery* qc)
 }
 
 
-/* Add query to query cache */
+/* Add query to query cache, the returned Query is locked for writing */
 static CachedQuery *
 add_query(
        Operation *op,
        query_manager* qm,
        Query* query,
        QueryTemplate *templ,
-       int positive)
+       pc_caching_reason_t why,
+       int wlock)
 {
        CachedQuery* new_cached_query = (CachedQuery*) ch_malloc(sizeof(CachedQuery));
        Qbase *qbase, qb;
        Filter *first;
        int rc;
+       time_t ttl = 0;;
 
        new_cached_query->qtemp = templ;
        BER_BVZERO( &new_cached_query->q_uuid );
-       if ( positive ) {
-               new_cached_query->expiry_time = slap_get_time() + templ->ttl;
-       } else {
-               new_cached_query->expiry_time = slap_get_time() + templ->negttl;
+       new_cached_query->q_sizelimit = 0;
+
+       switch ( why ) {
+       case PC_POSITIVE:
+               ttl = templ->ttl;
+               break;
+
+       case PC_NEGATIVE:
+               ttl = templ->negttl;
+               break;
+
+       case PC_SIZELIMIT:
+               ttl = templ->limitttl;
+               break;
+
+       default:
+               assert( 0 );
+               break;
        }
+       new_cached_query->expiry_time = slap_get_time() + ttl;
        new_cached_query->lru_up = NULL;
        new_cached_query->lru_down = NULL;
-       Debug( pcache_debug, "Added query expires at %ld\n",
-                       (long) new_cached_query->expiry_time, 0, 0 );
+       Debug( pcache_debug, "Added query expires at %ld (%s)\n",
+                       (long) new_cached_query->expiry_time,
+                       pc_caching_reason_str[ why ], 0 );
 
        new_cached_query->scope = query->scope;
        new_cached_query->filter = query->filter;
        new_cached_query->first = first = filter_first( query->filter );
+       
+       ldap_pvt_thread_rdwr_init(&new_cached_query->rwlock);
+       if (wlock)
+               ldap_pvt_thread_rdwr_wlock(&new_cached_query->rwlock);
 
        qb.base = query->base;
 
@@ -1286,7 +1334,7 @@ cache_replacement(query_manager* qm, struct berval *result)
        ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);
 
        *result = bottom->q_uuid;
-       bottom->q_uuid.bv_val = NULL;
+       BER_BVZERO( &bottom->q_uuid );
 
        Debug( pcache_debug, "Lock CR index = %p\n", (void *) temp, 0, 0 );
        ldap_pvt_thread_rdwr_wlock(&temp->t_rwlock);
@@ -1339,11 +1387,7 @@ remove_query_data(
 {
        struct query_info       *qi, *qnext;
        char                    filter_str[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(queryId=)" ) ];
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion      ava = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion      ava = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion      ava = ATTRIBUTEASSERTION_INIT;
        Filter                  filter = {LDAP_FILTER_EQUALITY};
        SlapReply               sreply = {REP_RESULT};
        slap_callback cb = { NULL, remove_func, NULL, NULL };
@@ -1527,6 +1571,9 @@ struct search_info {
        int max;
        int over;
        int count;
+       int slimit;
+       int slimit_exceeded;
+       pc_caching_reason_t caching_reason;
        Entry *head, *tail;
 };
 
@@ -1622,11 +1669,7 @@ pcache_remove_entries_from_cache(
        SlapReply       rs = { REP_RESULT };
        Filter          f = { 0 };
        char            filtbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(entryUUID=)" ) ];
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion ava = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
        AttributeName   attrs[ 2 ] = { 0 };
        int             s, rc;
 
@@ -1741,11 +1784,7 @@ pcache_remove_entry_queries_from_cache(
        SlapReply               rs = { REP_RESULT };
        Filter                  f = { 0 };
        char                    filter_str[ LDAP_LUTIL_UUIDSTR_BUFSIZE + STRLENOF( "(queryId=)" ) ];
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion      ava = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion      ava = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion      ava = ATTRIBUTEASSERTION_INIT;
        AttributeName           attrs[ 2 ] = { 0 };
        int                     rc;
 
@@ -1874,35 +1913,18 @@ static int
 pcache_op_cleanup( Operation *op, SlapReply *rs ) {
        slap_callback   *cb = op->o_callback;
        struct search_info *si = cb->sc_private;
-       if ( rs->sr_type == REP_RESULT || op->o_abandon || 
-                       rs->sr_err == SLAPD_ABANDON ) {
-               if ( si->save_attrs != NULL ) {
-                       rs->sr_attrs = si->save_attrs;
-                       op->ors_attrs = si->save_attrs;
-               }
-               op->o_callback = op->o_callback->sc_next;
-               op->o_tmpfree( cb, op->o_tmpmemctx );
-       }
-       return SLAP_CB_CONTINUE;
-}
-
-static int
-pcache_response(
-       Operation       *op,
-       SlapReply       *rs )
-{
-       struct search_info *si = op->o_callback->sc_private;
        slap_overinst *on = si->on;
        cache_manager *cm = on->on_bi.bi_private;
        query_manager*          qm = cm->qm;
 
-       if ( si->save_attrs != NULL ) {
-               rs->sr_attrs = si->save_attrs;
-               op->ors_attrs = si->save_attrs;
-       }
-
        if ( rs->sr_type == REP_SEARCH ) {
                Entry *e;
+
+               /* don't return more entries than requested by the client */
+               if ( si->slimit && rs->sr_nentries >= si->slimit ) {
+                       si->slimit_exceeded = 1;
+               }
+
                /* If we haven't exceeded the limit for this query,
                 * build a chain of answers to store. If we hit the
                 * limit, empty the chain and ignore the rest.
@@ -1914,6 +1936,7 @@ pcache_response(
                                if ( !si->head ) si->head = e;
                                if ( si->tail ) si->tail->e_private = e;
                                si->tail = e;
+
                        } else {
                                si->over = 1;
                                si->count = 0;
@@ -1926,16 +1949,43 @@ pcache_response(
                        }
                }
 
-       } else if ( rs->sr_type == REP_RESULT ) {
-               if ( si->count ||
-                       ( si->qtemp->negttl && !si->count && !si->over &&
-                               rs->sr_err == LDAP_SUCCESS )) {
-                       CachedQuery *qc = qm->addfunc(op, qm, &si->query, si->qtemp,
-                               si->count);
+       }
+
+       if ( rs->sr_type == REP_RESULT || 
+               op->o_abandon || rs->sr_err == SLAPD_ABANDON )
+       {
+               if ( si->save_attrs != NULL ) {
+                       rs->sr_attrs = si->save_attrs;
+                       op->ors_attrs = si->save_attrs;
+               }
+               if ( op->o_abandon || rs->sr_err == SLAPD_ABANDON ) {
+                       filter_free( si->query.filter );
+                       if ( si->count ) {
+                               /* duplicate query, free it */
+                               Entry *e;
+                               for (;si->head; si->head=e) {
+                                       e = si->head->e_private;
+                                       si->head->e_private = NULL;
+                                       entry_free(si->head);
+                               }
+                       }
+                       op->o_callback = op->o_callback->sc_next;
+                       op->o_tmpfree( cb, op->o_tmpmemctx );
+               } else if ( si->caching_reason != PC_IGNORE ) {
+                       CachedQuery *qc = qm->addfunc(op, qm, &si->query,
+                               si->qtemp, si->caching_reason, 1 );
 
                        if ( qc != NULL ) {
-                               if ( si->count )
+                               switch ( si->caching_reason ) {
+                               case PC_POSITIVE:
                                        cache_entries( op, rs, &qc->q_uuid );
+                                       break;
+
+                               case PC_SIZELIMIT:
+                                       qc->q_sizelimit = rs->sr_nentries;
+                                       break;
+                               }
+                               ldap_pvt_thread_rdwr_wunlock(&qc->rwlock);
                                ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
                                cm->num_cached_queries++;
                                Debug( pcache_debug, "STORED QUERIES = %lu\n",
@@ -1953,6 +2003,7 @@ pcache_response(
                                        }
                                        ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
                                }
+
                        } else if ( si->count ) {
                                /* duplicate query, free it */
                                Entry *e;
@@ -1962,10 +2013,57 @@ pcache_response(
                                        entry_free(si->head);
                                }
                        }
+
                } else {
                        filter_free( si->query.filter );
                }
        }
+
+       return SLAP_CB_CONTINUE;
+}
+
+static int
+pcache_response(
+       Operation       *op,
+       SlapReply       *rs )
+{
+       struct search_info *si = op->o_callback->sc_private;
+
+       if ( si->save_attrs != NULL ) {
+               rs->sr_attrs = si->save_attrs;
+               op->ors_attrs = si->save_attrs;
+       }
+
+       if ( rs->sr_type == REP_SEARCH ) {
+               /* don't return more entries than requested by the client */
+               if ( si->slimit_exceeded ) {
+                       return 0;
+               }
+
+       } else if ( rs->sr_type == REP_RESULT ) {
+
+               if ( si->count ) {
+                       if ( rs->sr_err == LDAP_SUCCESS ) {
+                               si->caching_reason = PC_POSITIVE;
+
+                       } else if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED
+                               && si->qtemp->limitttl )
+                       {
+                               si->caching_reason = PC_SIZELIMIT;
+                       }
+
+               } else if ( si->qtemp->negttl && !si->count && !si->over &&
+                               rs->sr_err == LDAP_SUCCESS )
+               {
+                       si->caching_reason = PC_NEGATIVE;
+               }
+
+
+               if ( si->slimit_exceeded ) {
+                       rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+               }
+       }
+
        return SLAP_CB_CONTINUE;
 }
 
@@ -2203,6 +2301,7 @@ pcache_op_search(
 
                Debug( pcache_debug, "QUERY ANSWERABLE\n", 0, 0, 0 );
                op->o_tmpfree( filter_attrs, op->o_tmpmemctx );
+               ldap_pvt_thread_rdwr_rlock(&answerable->rwlock);
                if ( BER_BVISNULL( &answerable->q_uuid )) {
                        /* No entries cached, just an empty result set */
                        i = rs->sr_err = 0;
@@ -2212,6 +2311,7 @@ pcache_op_search(
                        op->o_callback = NULL;
                        i = cm->db.bd_info->bi_op_search( op, rs );
                }
+               ldap_pvt_thread_rdwr_runlock(&answerable->rwlock);
                ldap_pvt_thread_rdwr_runlock(&qtemp->t_rwlock);
                op->o_bd = save_bd;
                op->o_callback = save_cb;
@@ -2255,6 +2355,13 @@ pcache_op_search(
                si->max = cm->num_entries_limit ;
                si->over = 0;
                si->count = 0;
+               si->slimit = 0;
+               si->slimit_exceeded = 0;
+               si->caching_reason = PC_IGNORE;
+               if ( op->ors_slimit && op->ors_slimit < cm->num_entries_limit ) {
+                       si->slimit = op->ors_slimit;
+                       op->ors_slimit = cm->num_entries_limit;
+               }
                si->head = NULL;
                si->tail = NULL;
                si->save_attrs = op->ors_attrs;
@@ -2455,9 +2562,10 @@ static ConfigTable pccfg[] = {
                        "DESC 'A set of attributes to cache' "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "proxytemplate", "filter> <attrset-index> <TTL> <negTTL",
-               4, 5, 0, ARG_MAGIC|PC_TEMP, pc_cf_gen,
+               4, 6, 0, ARG_MAGIC|PC_TEMP, pc_cf_gen,
                "( OLcfgOvAt:2.3 NAME 'olcProxyTemplate' "
-                       "DESC 'Filter template, attrset, cache TTL, optional negative TTL' "
+                       "DESC 'Filter template, attrset, cache TTL, "
+                               "optional negative TTL, optional sizelimit TTL' "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "response-callback", "head|tail(default)",
                2, 2, 0, ARG_MAGIC|PC_RESP, pc_cf_gen,
@@ -2580,17 +2688,14 @@ pc_cf_gen( ConfigArgs *c )
                        break;
                case PC_TEMP:
                        for (temp=qm->templates; temp; temp=temp->qmnext) {
-                               if ( temp->negttl ) {
-                                       bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ),
-                                               " %d %ld %ld",
-                                               temp->attr_set_index,
-                                               temp->ttl,
-                                               temp->negttl );
-                               } else {
-                                       bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ), " %d %ld",
-                                               temp->attr_set_index,
-                                               temp->ttl );
-                               }
+                               /* HEADS-UP: always print all;
+                                * if optional == 0, ignore */
+                               bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       " %d %ld %ld %ld",
+                                       temp->attr_set_index,
+                                       temp->ttl,
+                                       temp->negttl,
+                                       temp->limitttl );
                                bv.bv_len += temp->querystr.bv_len + 2;
                                bv.bv_val = ch_malloc( bv.bv_len+1 );
                                ptr = bv.bv_val;
@@ -2839,23 +2944,37 @@ pc_cf_gen( ConfigArgs *c )
                ldap_pvt_thread_rdwr_init( &temp->t_rwlock );
                temp->query = temp->query_last = NULL;
                if ( lutil_parse_time( c->argv[3], &t ) != 0 ) {
-                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "unable to parse template ttl=\"%s\"",
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                               "unable to parse template ttl=\"%s\"",
                                c->argv[3] );
                        Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                        return( 1 );
                }
                temp->ttl = (time_t)t;
-               if ( c->argc == 5 ) {
+               temp->negttl = (time_t)0;
+               temp->limitttl = (time_t)0;
+               switch ( c->argc ) {
+               case 6:
+                       if ( lutil_parse_time( c->argv[5], &t ) != 0 ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "unable to parse template sizelimit ttl=\"%s\"",
+                                       c->argv[5] );
+                               Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
+                                       return( 1 );
+                       }
+                       temp->limitttl = (time_t)t;
+                       /* fallthru */
+
+               case 5:
                        if ( lutil_parse_time( c->argv[4], &t ) != 0 ) {
                                snprintf( c->cr_msg, sizeof( c->cr_msg ),
-                                       "unable to parse template negttl=\"%s\"",
+                                       "unable to parse template negative ttl=\"%s\"",
                                        c->argv[4] );
                                Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                        return( 1 );
                        }
                        temp->negttl = (time_t)t;
-               } else {
-                       temp->negttl = 0;
+                       break;
                }
 
                temp->no_of_queries = 0;
@@ -3084,11 +3203,7 @@ pcache_db_open(
                        SlapReply       rs = { 0 };
                        BerVarray       vals = NULL;
                        Filter          f = { 0 }, f2 = { 0 };
-#ifdef LDAP_COMP_MATCH
-                       AttributeAssertion      ava = { NULL, BER_BVNULL, NULL };
-#else
-                       AttributeAssertion      ava = { NULL, BER_BVNULL };
-#endif
+                       AttributeAssertion      ava = ATTRIBUTEASSERTION_INIT;
                        AttributeName   attrs[ 2 ] = { 0 };
 
                        connection_fake_init( &conn, &opbuf, thrctx );
index a817700622eedc180dfc723b2a0a089660e3000e..bbdbf30085b373932baa4986e91d4534f44b262b 100644 (file)
@@ -585,11 +585,7 @@ syncprov_findcsn( Operation *op, find_csn_t mode )
        char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
        struct berval maxcsn;
        Filter cf;
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion eq = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion eq = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion eq = ATTRIBUTEASSERTION_INIT;
        fpres_cookie pcookie;
        sync_control *srs = NULL;
        struct slap_limits_set fc_limits;
@@ -1483,11 +1479,7 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
                SlapReply frs = { REP_RESULT };
                int rc;
                Filter mf, af;
-#ifdef LDAP_COMP_MATCH
-               AttributeAssertion eq = { NULL, BER_BVNULL, NULL };
-#else
-               AttributeAssertion eq;
-#endif
+               AttributeAssertion eq = ATTRIBUTEASSERTION_INIT;
                slap_callback cb = {0};
 
                fop = *op;
index e3fae5ded0462e31926b9080827a54058f1be69b..ec130c416012d2c7e864ee791f063ff2b932d42e 100644 (file)
@@ -1016,6 +1016,11 @@ LDAP_SLAPD_F (int) filter_has_subordinates LDAP_P(( Filter *filter ));
 #define filter_escape_value( in, out )         ldap_bv2escaped_filter_value_x( (in), (out), 0, NULL )
 #define filter_escape_value_x( in, out, ctx )  ldap_bv2escaped_filter_value_x( (in), (out), 0, ctx )
 
+LDAP_SLAPD_V (const Filter *) slap_filter_objectClass_pres;
+LDAP_SLAPD_V (const struct berval *) slap_filterstr_objectClass_pres;
+
+LDAP_SLAPD_F (int) filter_init LDAP_P(( void ));
+LDAP_SLAPD_F (void) filter_destroy LDAP_P(( void ));
 /*
  * filterentry.c
  */
index 75aa25d1a92b32aa292b047133e3796b19988f88..b04ccd3f7a52a8b7690503505767c0e72c432b4e 100644 (file)
@@ -979,6 +979,11 @@ struct AttributeAssertion {
        ComponentFilter         *aa_cf;         /* for attribute aliasing */
 #endif
 };
+#ifdef LDAP_COMP_MATCH
+#define ATTRIBUTEASSERTION_INIT { NULL, BER_BVNULL, NULL }
+#else
+#define ATTRIBUTEASSERTION_INIT { NULL, BER_BVNULL }
+#endif
 
 struct SubstringsAssertion {
        AttributeDescription    *sa_desc;
index d41caa5200d05a524f454ea1d9e47f5e63466889..af6de8893d89d25a0432a6441ae9ad73d1ebf042 100644 (file)
@@ -1840,11 +1840,7 @@ syncrepl_entry(
        SlapReply       rs_add = {REP_RESULT};
        SlapReply       rs_modify = {REP_RESULT};
        Filter f = {0};
-#ifdef LDAP_COMP_MATCH
-       AttributeAssertion ava = { NULL, BER_BVNULL, NULL };
-#else
-       AttributeAssertion ava = { NULL, BER_BVNULL };
-#endif
+       AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
        int rc = LDAP_SUCCESS;
 
        struct berval pdn = BER_BVNULL;
@@ -2264,11 +2260,7 @@ syncrepl_del_nonpresent(
 
        if ( uuids ) {
                Filter uf;
-#ifdef LDAP_COMP_MATCH
-               AttributeAssertion eq = { NULL, BER_BVNULL, NULL };
-#else
-               AttributeAssertion eq = { NULL, BER_BVNULL };
-#endif
+               AttributeAssertion eq = ATTRIBUTEASSERTION_INIT;
                int i;
 
                op->ors_attrsonly = 1;
index 886f2549f1260597cf957eb471e7a8fa1dadd283..dfffc88aad76fdf1637011837222d95b86c1a8ad 100644 (file)
@@ -1,4 +1,4 @@
-# Query 1: filter:(sn=Jon) attrs: all
+# Query 1: filter:(sn=Jon) attrs:all (expect nothing)
 # Query 2: filter:(|(cn=*Jon*)(sn=Jon*)) attrs:cn sn title uid
 dn: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
 cn: James A Jones 1
@@ -24,7 +24,7 @@ sn: Doe
 uid: johnd
 title: System Administrator, Information Technology Division
 
-# Query 3: filter:(sn=Smith*) attrs:cn sn title uid
+# Query 3: filter:(sn=Smith*) attrs:cn sn uid
 dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
 cn: Jennifer Smith
 cn: Jen Smith
@@ -55,17 +55,16 @@ sn: Doe
 uid: johnd
 title: System Administrator, Information Technology Division
 
-# Query 5: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber cn uid
-dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
- =com
-cn: Bjorn Jensen
-cn: Biiff Jensen
-uid: bjorn
-postalAddress: Info Tech Division $ 535 W. William St. $ Anytown, MI 48103
-mail: bjorn@mailgw.example.com
-telephoneNumber: +1 313 555 0355
+# Query 5: filter:(uid=johnd) attrs:mail postaladdress telephonenumber cn uid
+dn: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc=com
+cn: John Doe
+cn: Jonathon Doe
+uid: johnd
+postalAddress: ITD $ 535 W. William $ Anytown, MI 48109
+mail: johnd@mailgw.example.com
+telephoneNumber: +1 313 555 9394
 
-# Query 6: filter:(mail=*@mail.alumni.example.com) cn sn title uid
+# Query 6: filter:(mail=*@mail.alumni.example.com) attrs:cn sn title uid
 dn: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
 cn: Dorothy Stevens
 cn: Dot Stevens
@@ -101,7 +100,7 @@ sn: Hampster
 uid: uham
 title: Secretary, UM Alumni Association
 
-# Query 7: filter:(mail=*) cn sn title uid
+# Query 7: filter:(mail=*) attrs:cn sn title uid
 dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,
  dc=com
 cn: Barbara Jensen
@@ -176,7 +175,21 @@ sn: Hampster
 uid: uham
 title: Secretary, UM Alumni Association
 
-# Query 8: filter:(|(cn=*Jones)(sn=Jones)) attrs:cn sn title uid
+# Query 8: filter:(mail=*example.com) attrs:cn sn title uid
+dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,
+ dc=com
+cn: Barbara Jensen
+cn: Babs Jensen
+sn:: IEplbnNlbiA=
+uid: bjensen
+title: Mythical Manager, Research Systems
+
+# Query 9: filter:(uid=b*) attrs:mail
+dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,
+ dc=com
+mail: bjensen@mailgw.example.com
+
+# Query 10: filter:(|(cn=*Jones)(sn=Jones)) attrs:cn sn title uid
 dn: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
 cn: James A Jones 1
 cn: James Jones
@@ -194,7 +207,7 @@ sn: Doe
 uid: jjones
 title: Senior Manager, Information Technology Division
 
-# Query 9: filter:(sn=Smith) attrs:cn sn title uid
+# Query 11: filter:(sn=Smith) attrs:cn sn title uid
 dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
 cn: Jennifer Smith
 cn: Jen Smith
@@ -202,7 +215,7 @@ sn: Smith
 uid: jen
 title: Telemarketer, UM Alumni Association
 
-# Query 10: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber cn uid
+# Query 12: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber cn uid
 dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
  =com
 cn: Bjorn Jensen
@@ -212,7 +225,7 @@ postalAddress: Info Tech Division $ 535 W. William St. $ Anytown, MI 48103
 mail: bjorn@mailgw.example.com
 telephoneNumber: +1 313 555 0355
 
-# Query 11: filter:(mail=jaj@mail.alumni.example.com) cn sn title uid
+# Query 13: filter:(mail=jaj@mail.alumni.example.com) attrs:cn sn title uid
 dn: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
 cn: James A Jones 1
 cn: James Jones
@@ -221,3 +234,17 @@ sn: Jones
 uid: jaj
 title: Mad Cow Researcher, UM Alumni Association
 
+# Query 14: filter:(mail=*example.com) attrs:cn sn title uid
+dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,
+ dc=com
+cn: Barbara Jensen
+cn: Babs Jensen
+sn:: IEplbnNlbiA=
+uid: bjensen
+title: Mythical Manager, Research Systems
+
+# Query 15: filter:(uid=b*) attrs:mail
+dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,
+ dc=com
+mail: bjensen@mailgw.example.com
+
index b9257c8ff3895a639b7611a130b689dfeac44815..87bffc6700e5b6b3257b2ad21be91672b45e780a 100644 (file)
@@ -39,17 +39,20 @@ argsfile    @TESTDIR@/slapd.2.args
 database       ldap
 suffix          "dc=example,dc=com"
 rootdn          "dc=example,dc=com"
+rootpw         "secret"
 uri            "@URI1@"
 
+limits         dn="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com" size=1
+
 overlay                pcache
 proxycache     @BACKEND@ 100 2 @ENTRY_LIMIT@ @CACHETTL@
 proxyattrset 0         sn cn title uid
 proxyattrset 1         mail postaladdress telephonenumber cn uid
-proxytemplate          (|(cn=)(sn=)) 0 @CACHETTL@
-proxytemplate          (sn=) 0 @CACHETTL@
-proxytemplate          (uid=) 1 @CACHETTL@
-proxytemplate          (mail=) 0 @CACHETTL@
-       
+proxytemplate          (|(cn=)(sn=)) 0 @CACHETTL@ @NCACHETTL@ @SCACHETTL@
+proxytemplate          (sn=) 0 @CACHETTL@ @NCACHETTL@ @SCACHETTL@
+proxytemplate          (uid=) 1 @CACHETTL@ @NCACHETTL@ @SCACHETTL@
+proxytemplate          (mail=) 0 @CACHETTL@ @NCACHETTL@ @SCACHETTL@
+
 #bdb#cachesize 20
 #hdb#cachesize 20
 
index e4a73a3b41f4c6716bdeb6a35e6fcbe5ff596cb8..25dd524f0176c20a2e5ff0c4c12da47652611054 100755 (executable)
@@ -71,6 +71,8 @@ sed -e "s/@BACKEND@/${BACKEND}/"                      \
        -e "s;@PORT6@;${PORT6};"                        \
        -e "s/@SASL_MECH@/${SASL_MECH}/"                \
        -e "s/@CACHETTL@/${CACHETTL}/"                  \
+       -e "s/@NCACHETTL@/${NCACHETTL}/"                \
+       -e "s/@SCACHETTL@/${SCACHETTL}/"                \
        -e "s/@ENTRY_LIMIT@/${CACHE_ENTRY_LIMIT}/"      \
        -e "s;@TESTDIR@;${TESTDIR};"                    \
        -e "s;@DATADIR@;${DATADIR};"                    \
index 070970af97b6f51ca929afc3ce3a0d6bb2a95849..6830c1c10908aa92a5159c69cec761bbb0a13f44 100755 (executable)
@@ -14,7 +14,9 @@
 ## <http://www.OpenLDAP.org/license.html>.
 
 CACHETTL="1m"
-CACHE_ENTRY_LIMIT=10
+NCACHETTL="1m"
+SCACHETTL="1m"
+CACHE_ENTRY_LIMIT=6
 
 . $SRCDIR/scripts/defines.sh
 
@@ -109,13 +111,17 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-cat /dev/null > $SLAVEOUT
+cat /dev/null > $SEARCHOUT
 
 echo "Making queries on the proxy cache..." 
-echo "Query 1: filter:(sn=Jon) attrs: all" 
-echo "# Query 1: filter:(sn=Jon) attrs: all" >> $SLAVEOUT
+CNT=0
+
+CNT=`expr $CNT + 1`
+FILTER="(sn=Jon)"
+echo "Query $CNT: filter:$FILTER attrs:all (expect nothing)" 
+echo "# Query $CNT: filter:$FILTER attrs:all (expect nothing)" >> $SEARCHOUT
 $LDAPSEARCH -x -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'sn=Jon' >> $SLAVEOUT 2>&1
+       "$FILTER" >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -132,10 +138,13 @@ if test $RC != 0 ; then
        exit 0
 fi
 
-echo "Query 2: filter:(|(cn=*Jon*)(sn=Jon*)) attrs:cn sn title uid"  
-echo "# Query 2: filter:(|(cn=*Jon*)(sn=Jon*)) attrs:cn sn title uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(|(cn=*Jon*)(sn=Jon*))"
+ATTRS="cn sn title uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -x -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       '(|(cn=*Jon*)(sn=Jon*))' cn sn title uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -143,10 +152,13 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-echo "Query 3: filter:(sn=Smith*) attrs:cn sn uid"  
-echo "# Query 3: filter:(sn=Smith*) attrs:cn sn uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(sn=Smith*)"
+ATTRS="cn sn uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'sn=Smith*' cn sn uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -154,21 +166,27 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-echo "Query 4: filter:(sn=Doe*) attrs:cn sn title uid"  
-echo "# Query 4: filter:(sn=Doe*) attrs:cn sn title uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(sn=Doe*)"
+ATTRS="cn sn title uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'sn=Doe' cn sn title uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
        test $KILLSERVERS != no && kill -HUP $KILLPIDS
        exit $RC
 fi
-echo "Query 5: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber cn uid"  
-echo "# Query 5: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber cn uid" >> $SLAVEOUT
+
+CNT=`expr $CNT + 1`
+FILTER="(uid=johnd)"
+ATTRS="mail postaladdress telephonenumber cn uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'uid=bjorn' mail postaladdress telephonenumber cn uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -176,10 +194,13 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-echo "Query 6: filter:(mail=*@mail.alumni.example.com) cn sn title uid"  
-echo "# Query 6: filter:(mail=*@mail.alumni.example.com) cn sn title uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(mail=*@mail.alumni.example.com)"
+ATTRS="cn sn title uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'mail=*@mail.alumni.example.com' cn sn title uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -187,10 +208,13 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-echo "Query 7: filter:(mail=*) cn sn title uid"  
-echo "# Query 7: filter:(mail=*) cn sn title uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(mail=*)"
+ATTRS="cn sn title uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'mail=*' cn sn title uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -198,8 +222,64 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-# queries 2-6 are cacheable
-CACHEABILITY=0111110
+CNT=`expr $CNT + 1`
+FILTER="(mail=*example.com)"
+ATTRS="cn sn title uid"
+USERDN="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com"
+PASSWD="bjorn"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
+       -D "$USERDN" -w "$PASSWD" \
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
+RC=$?
+case $RC in
+0)
+       echo "ldapsearch should have failed!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+4)
+       echo "ldapsearch failed ($RC)"
+       ;;
+*)
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+esac
+
+CNT=`expr $CNT + 1`
+FILTER="(uid=b*)"
+ATTRS="mail"
+USERDN="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com"
+PASSWD="bjorn"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
+       -D "$USERDN" -w "$PASSWD" \
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
+RC=$?
+case $RC in
+0)
+       echo "ldapsearch should have failed!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+4)
+       echo "ldapsearch failed ($RC)"
+       ;;
+*)
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+esac
+
+FIRST=$CNT
+
+# queries 2-6,8-9 are cacheable
+CACHEABILITY=011111011
 grep CACHEABLE $LOG2 | awk '{ 
                if ($2 == "NOT") 
                        printf "Query %d not cacheable\n",NR
@@ -221,10 +301,13 @@ else
        exit 1
 fi
 
-echo "Query 8: filter:(|(cn=*Jones)(sn=Jones)) attrs:cn sn title uid"  
-echo "# Query 8: filter:(|(cn=*Jones)(sn=Jones)) attrs:cn sn title uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(|(cn=*Jones)(sn=Jones))"
+ATTRS="cn sn title uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -x -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       '(|(cn=*Jones)(sn=Jones))' cn sn title uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -232,10 +315,13 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-echo "Query 9: filter:(sn=Smith) attrs:cn sn title uid"  
-echo "# Query 9: filter:(sn=Smith) attrs:cn sn title uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(sn=Smith)"
+ATTRS="cn sn title uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'sn=Smith' cn sn title uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -243,10 +329,13 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-echo "Query 10: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber cn uid"  
-echo "# Query 10: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber cn uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(uid=bjorn)"
+ATTRS="mail postaladdress telephonenumber cn uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'uid=bjorn' mail postaladdress telephonenumber cn uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 if test $RC != 0 ; then
        echo "ldapsearch failed ($RC)!"
@@ -254,10 +343,13 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-echo "Query 11: filter:(mail=jaj@mail.alumni.example.com) cn sn title uid"  
-echo "# Query 11: filter:(mail=jaj@mail.alumni.example.com) cn sn title uid" >> $SLAVEOUT
+CNT=`expr $CNT + 1`
+FILTER="(mail=jaj@mail.alumni.example.com)"
+ATTRS="cn sn title uid"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
-       'mail=jaj@mail.alumni.example.com' cn sn title uid >> $SLAVEOUT 2>&1
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
 RC=$?
 
 if test $RC != 0 ; then
@@ -266,18 +358,75 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-#queries 8-11 are answerable
-ANSWERABILITY=1111
-grep ANSWERABLE $LOG2 | awk '{ 
-               if (NR > 7) { 
+CNT=`expr $CNT + 1`
+FILTER="(mail=*example.com)"
+ATTRS="cn sn title uid"
+USERDN="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com"
+PASSWD="bjorn"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
+       -D "$USERDN" -w "$PASSWD" \
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
+RC=$?
+case $RC in
+0)
+       echo "ldapsearch should have failed!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+4)
+       echo "ldapsearch failed ($RC)"
+       ;;
+*)
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+esac
+
+CNT=`expr $CNT + 1`
+FILTER="(uid=b*)"
+ATTRS="mail"
+USERDN="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com"
+PASSWD="bjorn"
+echo "Query $CNT: filter:$FILTER attrs:$ATTRS"  
+echo "# Query $CNT: filter:$FILTER attrs:$ATTRS" >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT2 \
+       -D "$USERDN" -w "$PASSWD" \
+       "$FILTER" $ATTRS >> $SEARCHOUT 2>> $TESTOUT
+RC=$?
+case $RC in
+0)
+       echo "ldapsearch should have failed!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+4)
+       echo "ldapsearch failed ($RC)"
+       ;;
+*)
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+       ;;
+esac
+
+#queries 10-12,15 are answerable, 13-14 are not
+#actually, 12 would be answerable, but since 8 made mail=*example.com
+#not answerable because of sizelimit, queries contained in it are no longer
+#answerable as well
+ANSWERABILITY=111001
+grep ANSWERABLE $LOG2 | awk -vFIRST=$FIRST '{ 
+               if (NR > FIRST) { 
                        if ($2 == "NOT") 
                                printf "Query %d not answerable\n",NR
                        else 
                                printf "Query %d answerable\n",NR 
                }
        }' 
-ANSWERED=`grep ANSWERABLE $LOG2 | awk '{ 
-               if (NR > 7) { 
+ANSWERED=`grep ANSWERABLE $LOG2 | awk -vFIRST=$FIRST '{ 
+               if (NR > FIRST) { 
                        if ($2 == "NOT") 
                                printf "0" 
                        else 
@@ -295,7 +444,7 @@ else
 fi
 
 echo "Filtering ldapsearch results..."
-. $LDIFFILTER < $SLAVEOUT > $SEARCHFLT
+. $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
 echo "Filtering original ldif..."
 . $LDIFFILTER < $PROXYCACHEOUT > $LDIFFLT
 echo "Comparing filter output..."