]> git.sur5r.net Git - openldap/commitdiff
Proxy cache updates (with a test suite)
authorJong Hyuk Choi <jongchoi@openldap.org>
Sat, 21 Jun 2003 00:21:57 +0000 (00:21 +0000)
committerJong Hyuk Choi <jongchoi@openldap.org>
Sat, 21 Jun 2003 00:21:57 +0000 (00:21 +0000)
- IBM India Research (Apurva)

servers/slapd/back-meta/cache-merge.c
servers/slapd/back-meta/cache-query.c
servers/slapd/back-meta/cache-search.c
tests/Makefile.in
tests/data/slapd-cache-master.conf [new file with mode: 0644]
tests/data/slapd-proxycache.conf [new file with mode: 0644]
tests/scripts/conf.sh
tests/scripts/defines.sh
tests/scripts/test019-proxycaching [new file with mode: 0755]

index 3f59c3022b7185b99fbe0dda64914940d66a572e..28fd72f4b40802601e577a25274b72a957597a36 100644 (file)
@@ -246,13 +246,34 @@ merge_func (
                mod->sml_bvalues = (struct berval*) malloc(
                                (count+1) * sizeof( struct berval) );
 
+               mod->sml_nvalues = (struct berval*) malloc(
+                               (count+1) * sizeof( struct berval) );
+
                for ( i = 0; i < count; i++ ) {
                        ber_dupbv(mod->sml_bvalues+i, a_new->a_vals+i); 
+                       if ( a_new->a_desc->ad_type->sat_equality &&
+                               a_new->a_desc->ad_type->sat_equality->smr_normalize ) {
+                               rc = a_new->a_desc->ad_type->sat_equality->smr_normalize(
+                                       0,
+                                       a_new->a_desc->ad_type->sat_syntax,
+                                       a_new->a_desc->ad_type->sat_equality,
+                                       a_new->a_vals+i, mod->sml_nvalues+i, NULL );
+                               if (rc) {
+                                       info->err = MERGE_ERR; 
+                                       return 0; 
+                               } 
+                       }
+                       else {  
+                               ber_dupbv( mod->sml_nvalues+i, a_new->a_vals+i ); 
+                       } 
                }
 
                mod->sml_bvalues[count].bv_val = 0; 
                mod->sml_bvalues[count].bv_len = 0; 
 
+               mod->sml_nvalues[count].bv_val = 0; 
+               mod->sml_nvalues[count].bv_len = 0; 
+
                mod->sml_desc = NULL;
                slap_bv2ad(&mod->sml_type, &mod->sml_desc, &text); 
                mod->sml_next =NULL;
@@ -266,10 +287,17 @@ merge_func (
        mod->sml_op = LDAP_MOD_ADD;
        mod->sml_desc = slap_schema.si_ad_queryid; 
        ber_dupbv(&mod->sml_type, &mod->sml_desc->ad_cname); 
+
        mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
        ber_dupbv( mod->sml_bvalues, uuid );
        mod->sml_bvalues[1].bv_val = NULL;
        mod->sml_bvalues[1].bv_len = 0;
+
+       mod->sml_nvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+       ber_dupbv( mod->sml_nvalues, uuid );
+       mod->sml_nvalues[1].bv_val = NULL;
+       mod->sml_nvalues[1].bv_len = 0;
+
        *modtail = mod;
        mod->sml_next = NULL; 
 
@@ -279,6 +307,7 @@ merge_func (
        op_tmp.orm_modlist = modhead;
 
        op_tmp.o_callback->sc_response = null_response; 
+       /* FIXME: &op_tmp ??? */
        if (be->be_modify(&op_tmp, &sreply ) != 0 ) {
                /* FIXME: cleanup ? */
                info->err = MERGE_ERR;
index 58e986dbe232604fe1c2d5ed996881e69aa7bafb..99db22d87835fe899ce510b68581969393deeee1 100644 (file)
@@ -117,6 +117,7 @@ query_containment(query_manager* qm,
                                                }
                                        } 
                                        switch (fs->f_choice) {
+                                       case LDAP_FILTER_OR: 
                                        case LDAP_FILTER_AND:
                                                fs = fs->f_and;
                                                fi = fi->f_and;
@@ -161,6 +162,9 @@ query_containment(query_manager* qm,
                                                fs=fs->f_next;
                                                fi=fi->f_next;  
                                                break;
+                                       case LDAP_FILTER_NOT:
+                                               res=0;
+                                               break;
                                        default:
                                                break;
                                        } 
index 3a0171a8a9b7113e5772c72f549aec10ce213de3..d91680344bd4c7069bbc37c8da33b6c34085ed19 100644 (file)
@@ -241,6 +241,8 @@ meta_back_cache_search(
        cache_manager*          cm = li->cm; 
        query_manager*          qm = cm->qm; 
 
+       Operation               *oper;
+
        time_t                  curr_time; 
 
        int count, rc = 0, *msgid = NULL; 
@@ -306,11 +308,13 @@ meta_back_cache_search(
        Debug( LDAP_DEBUG_ANY, "Threads++ = %d\n", cm->threads, 0, 0 );
 #endif /* !NEW_LOGGING */
        ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); 
-    
+       
        ldap_pvt_thread_mutex_lock(&cm->cc_mutex); 
        if (!cm->cc_thread_started) {
+               oper = (Operation*)malloc(sizeof(Operation)); 
+               *oper = *op; 
                cm->cc_thread_started = 1; 
-                ldap_pvt_thread_create(&(cm->cc_thread), 1, consistency_check, (void*)op); 
+                ldap_pvt_thread_create(&(cm->cc_thread), 1, consistency_check, (void*)oper); 
        }       
        ldap_pvt_thread_mutex_unlock(&cm->cc_mutex); 
 
@@ -402,8 +406,8 @@ meta_back_cache_search(
 
                ldap_pvt_thread_rdwr_runlock(&qm->templates[i].t_rwlock); 
        } else {
-               Operation       op_tmp = *op;
-
+               Operation       op_tmp;
+               op_tmp = *op;
 #ifdef NEW_LOGGING
                LDAP_LOG( BACK_META, DETAIL1, "QUERY NOT ANSWERABLE\n",
                                        0, 0, 0 );
@@ -411,14 +415,14 @@ meta_back_cache_search(
                Debug( LDAP_DEBUG_ANY, "QUERY NOT ANSWERABLE\n", 0, 0, 0 );
 #endif /* !NEW_LOGGING */
 
-               if ( op_tmp.ors_scope == LDAP_SCOPE_BASE ) {
+               if ( op->ors_scope == LDAP_SCOPE_BASE ) {
                        op_type = META_OP_REQUIRE_SINGLE;
                } else {
                        op_type = META_OP_ALLOW_MULTIPLE;
                }
 
                lc = metaConnect(&op_tmp, rs, op_type,
-                               &op_tmp.o_req_ndn, result);
+                               &op->o_req_ndn, result);
 
                if (result->type != SUCCESS) 
                        goto Catch; 
@@ -430,14 +434,6 @@ meta_back_cache_search(
                ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); 
                
                if (cacheable) {
-#ifdef NEW_LOGGING
-                       LDAP_LOG( BACK_META, DETAIL1,
-                                       "QUERY TEMPLATE CACHEABLE\n",
-                                       0, 0, 0);
-#else /* !NEW_LOGGING */
-                       Debug( LDAP_DEBUG_ANY, "QUERY TEMPLATE CACHEABLE\n",
-                                       0, 0, 0);
-#endif /* !NEW_LOGGING */
                        add_filter_attrs(&new_attrs, attrs, filter_attrs);
                } else {
                        new_attrs = attrs; 
@@ -462,6 +458,7 @@ meta_back_cache_search(
                /*
                 * Inits searches
                 */
+
                for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
                        char    *realbase = ( char * )op->o_req_dn.bv_val;
                        int     realscope = op->ors_scope;
@@ -618,9 +615,14 @@ meta_back_cache_search(
                        msgid[ i ] = ldap_search( lsc->ld, mbase, realscope,
                                                mapped_filter, mapped_attrs,
                                                op->ors_attrsonly ); 
+
                        if ( msgid[ i ] == -1 ) {
+                               result->type = CONN_ERR; 
+                               goto Catch; 
+                               /*
                                lsc->candidate = META_NOT_CANDIDATE;
                                continue;
+                               */
                        }
 
                        if ( mapped_attrs ) {
@@ -679,6 +681,15 @@ meta_back_cache_search(
                                goto Catch; 
                        filter = 0; 
                        attrs = 0; 
+               } else {
+#ifdef NEW_LOGGING
+                       LDAP_LOG( BACK_META, DETAIL1,
+                                       "QUERY NOT CACHEABLE no\n",
+                                       0, 0, 0);
+#else /* !NEW_LOGGING */
+                       Debug( LDAP_DEBUG_ANY, "QUERY NOT CACHEABLE no\n",
+                                       0, 0, 0);
+#endif /* !NEW_LOGGING */
                }
        }
 
@@ -1012,7 +1023,7 @@ is_one_level_rdn(
 
 static struct metaconn*  
 metaConnect(
-       Operation               *op, 
+       Operation*              op, 
        SlapReply               *rs,
        int                     op_type, 
        struct berval           *nbase, 
@@ -1035,8 +1046,11 @@ add_filter_attrs(
        AttributeName* attrs, 
        AttributeName* filter_attrs )
 {
-       struct berval all_user = BER_BVC(LDAP_ALL_USER_ATTRIBUTES);
-       struct berval all_op = BER_BVC(LDAP_ALL_OPERATIONAL_ATTRIBUTES);
+       struct berval all_user = { sizeof(LDAP_ALL_USER_ATTRIBUTES) -1,
+                                  LDAP_ALL_USER_ATTRIBUTES };
+
+       struct berval all_op = { sizeof(LDAP_ALL_OPERATIONAL_ATTRIBUTES) -1,
+                                       LDAP_ALL_OPERATIONAL_ATTRIBUTES}; 
 
        int alluser = 0; 
        int allop = 0; 
@@ -1044,40 +1058,36 @@ add_filter_attrs(
        int count; 
 
        /* duplicate attrs */
-       for (count=0; attrs[count].an_name.bv_val; count++) 
-               ;
-       *new_attrs =  (AttributeName*)(malloc((count+1)*sizeof(AttributeName))); 
-       for (i=0; i<count; i++) {
-               /*
-               ber_dupbv(&((*new_attrs)[i].an_name), &(attrs[i].an_name)); 
-               */
-               (*new_attrs)[i].an_name = attrs[i].an_name; 
-               (*new_attrs)[i].an_desc = attrs[i].an_desc;  
+        if (attrs == NULL) {
+               count = 1; 
+       } else { 
+               for (count=0; attrs[count].an_name.bv_val; count++) 
+                       ;
        }
-       (*new_attrs)[count].an_name.bv_val = NULL; 
-       (*new_attrs)[count].an_name.bv_len = 0; 
-
-
-       if ((*new_attrs)[0].an_name.bv_val == NULL) {
-               *new_attrs = (AttributeName*)(malloc(2*sizeof(AttributeName))); 
+       *new_attrs = (AttributeName*)(malloc((count+1)*sizeof(AttributeName))); 
+       if (attrs == NULL) { 
                (*new_attrs)[0].an_name.bv_val = "*"; 
                (*new_attrs)[0].an_name.bv_len = 1; 
-               (*new_attrs)[1].an_name.bv_val = NULL; 
-               (*new_attrs)[1].an_name.bv_len = 0; 
                alluser = 1; 
-               count = 1; 
-       } else {
+               allop = 0; 
+       } else {  
+               for (i=0; i<count; i++) {
+                       (*new_attrs)[i].an_name = attrs[i].an_name; 
+                       (*new_attrs)[i].an_desc = attrs[i].an_desc;  
+               }
                alluser = an_find(*new_attrs, &all_user); 
                allop = an_find(*new_attrs, &all_op); 
        }
+       (*new_attrs)[count].an_name.bv_val = NULL; 
+       (*new_attrs)[count].an_name.bv_len = 0; 
 
        for ( i=0; filter_attrs[i].an_name.bv_val; i++ ) {
                if ( an_find(*new_attrs, &filter_attrs[i].an_name ))
                        continue; 
-               if ( is_at_operational(filter_attrs[i].an_desc->ad_type)
-                                               && allop )
-                       continue; 
-               else if (alluser) 
+               if ( is_at_operational(filter_attrs[i].an_desc->ad_type) ) {
+                       if (allop) 
+                               continue; 
+               else if (alluser) 
                        continue; 
                *new_attrs = (AttributeName*)(realloc(*new_attrs,
                                        (count+2)*sizeof(AttributeName))); 
@@ -1423,8 +1433,12 @@ attrscmp(
        AttributeName* attrs)
 {
        int i, count1, count2; 
-       if ((attrs_in==NULL) || (attrs==NULL)) 
-               return 1; 
+       if ( attrs_in == NULL ) {
+               return (attrs ? 0 : 1); 
+       } 
+       if ( attrs == NULL ) 
+               return 0; 
+       
        for ( count1=0;
              attrs_in && attrs_in[count1].an_name.bv_val != NULL;
              count1++ )
@@ -1640,12 +1654,11 @@ is_temp_answerable(
 static void* 
 consistency_check(void* operation)
 {
-       Operation* op_tmp = (Operation*)operation; 
+       Operation* op = (Operation*)operation; 
 
-       Operation op = *op_tmp; 
        SlapReply rs = {REP_RESULT}; 
 
-       struct metainfo *li = ( struct metainfo * )op.o_bd->be_private;
+       struct metainfo *li = ( struct metainfo * )op->o_bd->be_private;
        cache_manager*  cm = li->cm; 
        query_manager* qm = cm->qm; 
        CachedQuery* query, *query_prev; 
@@ -1656,7 +1669,7 @@ consistency_check(void* operation)
        QueryTemplate* templ;
 
 
-       op.o_bd = li->glue_be;
+       op->o_bd = li->glue_be;
       
         for(;;) {
                ldap_pvt_thread_sleep(cm->cc_period);     
@@ -1696,7 +1709,7 @@ consistency_check(void* operation)
                                ldap_pvt_thread_rdwr_wunlock(&templ->t_rwlock);  
                                uuid.bv_val = query->q_uuid; 
                                uuid.bv_len = strlen(query->q_uuid); 
-                               return_val = remove_query_data(&op, &rs, &uuid, &result); 
+                               return_val = remove_query_data(op, &rs, &uuid, &result); 
 #ifdef NEW_LOGGING
                                LDAP_LOG( BACK_META, DETAIL1,
                                                "STALE QUERY REMOVED, SIZE=%d\n",
@@ -1772,14 +1785,11 @@ cache_back_sentry(
                rs->sr_entry->e_nname = ndn; 
 
                op->o_callback = cb; 
-               return 0;
-
+               return 0; 
        } else if (rs->sr_type == REP_RESULT) { 
                op->o_callback = NULL; 
                send_ldap_result( op, rs ); 
                return 0; 
        }
-
-       return -1;
 }
 #endif
index a2b48b948a41e3aebc3bd987fc9aa06f799d7eef..4d6becc43668cbceb1edbf4e9270307d94f694a2 100644 (file)
@@ -70,9 +70,9 @@ test-nis-schema-ldbm:
        $(srcdir)/scripts/startup_nis_ldap_server.sh $(srcdir) ldbm
 
 clean-local:   FORCE
-       -$(RM) -r test-db/[!C]* test-repl/[!C]* *leak *gmon *core
+       -$(RM) -r test-db/[!C]* test-repl/[!C]* test-cache/[!C]* *leak *gmon *core
 
 veryclean-local: FORCE
        @-$(RM) data schema ucdata
-       -$(RM) -r test-db test-repl
+       -$(RM) -r test-db test-repl test-cache
 
diff --git a/tests/data/slapd-cache-master.conf b/tests/data/slapd-cache-master.conf
new file mode 100644 (file)
index 0000000..3dad68c
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# master slapd config -- for proxy cache testing
+#
+ucdata-path    ./ucdata
+include ./schema/core.schema
+include ./schema/cosine.schema
+include ./schema/inetorgperson.schema
+include ./schema/openldap.schema
+#
+pidfile     ./test-db/slapd.pid
+argsfile    ./test-db/slapd.args
+
+modulepath      ../servers/slapd/back-@BACKEND@/
+@MODULELOAD@
+
+#######################################################################
+# database definitions
+#######################################################################
+
+database       @BACKEND@
+suffix         "o=University of Michigan,c=US"
+directory      ./test-db
+rootdn         "cn=Manager,o=University of Michigan,c=US"
+rootpw         secret
+index          objectClass     eq
+index          cn,sn,uid       pres,eq,sub
+
diff --git a/tests/data/slapd-proxycache.conf b/tests/data/slapd-proxycache.conf
new file mode 100644 (file)
index 0000000..583fd66
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# proxy cache slapd config 
+#
+ucdata-path    ./ucdata
+include ./schema/core.schema
+include ./schema/cosine.schema
+include ./schema/inetorgperson.schema
+include ./schema/openldap.schema
+
+pidfile     ./test-cache/slapd.pid
+argsfile    ./test-cache/slapd.args
+
+access to * by write
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+database ldbm
+
+suffix "o=University of Michigan,c=US,cn=cache" 
+cachesize 20
+directory ./test-cache
+index          objectClass     eq
+index          cn,sn,uid,mail  pres,eq,sub
+
+database       meta
+rewriteEngine on
+rewriteContext cacheResult
+rewriteRule "(.*)o=University of Michigan,c=US" "%1o=University of Michigan,c=US,cn=cache" ":"
+rewriteContext cacheBase
+rewriteRule "(.*)o=University of Michigan,c=US" "%1o=university of michigan,c=us,cn=cache" ":"
+rewriteContext cacheReturn 
+rewriteRule "(.*)o=University of Michigan,c=US,cn=cache" "%1o=University of Michigan,c=US" ":"
+
+suffix          "o=University of Michigan,c=US"
+uri            ldap://127.0.0.1:9009/o=University%20of%20Michigan,c=US
+cacheparams    10000 15000 2 @ENTRY_LIMIT@ @CACHETTL@
+
+attrset 0      sn cn title
+attrset 1      mail postaladdress telephonenumber
+addtemplate    (|(cn=)(sn=)) 0 @CACHETTL@
+addtemplate    (sn=) 0 @CACHETTL@
+addtemplate    (uid=) 1 @CACHETTL@
+addtemplate    (mail=) 0 @CACHETTL@
+       
+
index 147a9a2ccb45149f457a9a3004eba96e88a12273..dbc01efdb18a5ea5b77c9c1205154098af189160 100755 (executable)
@@ -13,4 +13,6 @@ sed -e "s/@BACKEND@/${BACKEND}/"      \
        -e "s/^#${BACKEND}#//"                  \
        -e "s/^#${MON}#//"                              \
        -e "s/@PORT@/${PORT}/"                  \
-       -e "s/@SLAVEPORT@/${SLAVEPORT}/"
+       -e "s/@SLAVEPORT@/${SLAVEPORT}/" \
+        -e "s/@CACHETTL@/${CACHETTL}/"   \
+        -e "s/@ENTRY_LIMIT@/${CACHE_ENTRY_LIMIT}/"   
index c45092ccb611e10fd257b4cf4e4fa97cbce56d69..2b983e5304e27349025a75663bac68d7d40f7959 100755 (executable)
@@ -5,6 +5,7 @@ DATADIR=$SRCDIR/data
 PROGDIR=./progs
 DBDIR=./test-db
 REPLDIR=./test-repl
+CACHEDIR=./test-cache
 
 CONF=$DATADIR/slapd.conf
 MCONF=$DATADIR/slapd-master.conf
@@ -14,6 +15,8 @@ RCONF=$DATADIR/slapd-referrals.conf
 MASTERCONF=$DATADIR/slapd-repl-master.conf
 SRMASTERCONF=$DATADIR/slapd-syncrepl-master.conf
 SLAVECONF=$DATADIR/slapd-repl-slave.conf
+PROXYCACHECONF=$DATADIR/slapd-proxycache.conf
+CACHEMASTERCONF=$DATADIR/slapd-cache-master.conf
 SRREFSLAVECONF=$DATADIR/slapd-syncrepl-slave-refresh.conf
 SRPERSLAVECONF=$DATADIR/slapd-syncrepl-slave-persist.conf
 REFSLAVECONF=$DATADIR/slapd-ref-slave.conf
@@ -25,6 +28,7 @@ GLUECONF=$DATADIR/slapd-glue.conf
 DBCONF=$DBDIR/slapd.conf
 ADDCONF=$DBDIR/slapadd.conf
 REPLCONF=$REPLDIR/slapd.conf
+CACHECONF=$CACHEDIR/slapd.conf
 
 TOOLARGS="-x $LDAP_TOOLARGS"
 TOOLPROTO="-P 3"
diff --git a/tests/scripts/test019-proxycaching b/tests/scripts/test019-proxycaching
new file mode 100755 (executable)
index 0000000..504134c
--- /dev/null
@@ -0,0 +1,244 @@
+#! /bin/sh
+
+CACHETTL=60
+CACHE_ENTRY_LIMIT=10
+
+SRCDIR="."
+if test $# -ge 1 ; then
+       SRCDIR=$1; shift
+fi
+
+. $SRCDIR/scripts/args.sh
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+BACKEND=ldbm
+
+# Test proxy caching:
+# - start master
+# - start proxy cache
+# - populate master 
+# - perform first set of searches at the proxy
+# - verify cacheability
+# - perform second set of searches at the proxy 
+# - verify answerability
+
+#if test ! -x $SLAPD ; then
+#      echo ">>>>> $SLAPD is not executable or does not exist."
+#      echo ">>>>> Test skipped."
+#      exit 0
+#fi
+
+if test ! -d $DBDIR
+then 
+       mkdir $DBDIR
+fi
+
+if test ! -d $CACHEDIR
+then 
+       mkdir $CACHEDIR
+fi
+
+echo "Cleaning up in $DBDIR..."
+rm -f $DBDIR/[!C]*
+echo "Cleaning up in $CACHEDIR..."
+rm -rf $CACHEDIR/[!C]*
+echo $DBDIR
+
+echo "Starting master slapd on TCP/IP port $PORT..."
+. $CONFFILTER < $CACHEMASTERCONF > $DBCONF
+$SLAPD -f $DBCONF -h $MASTERURI -d $LVL > $MASTERLOG 2>&1 &
+PID=$!
+
+sleep 5
+
+echo "Using ldapadd to populate the master directory..."
+$LDAPADD -x -D "$MANAGERDN" -h $LOCALHOST -p $PORT -w $PASSWD < \
+       $LDIFORDERED > out 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapadd failed ($RC)!"
+       kill -HUP $PID 
+       exit $RC
+fi
+
+echo "Starting proxy cache on TCP/IP port $SLAVEPORT..."
+. $CONFFILTER < $PROXYCACHECONF > $CACHECONF
+$SLAPD -f $CACHECONF -h $SLAVEURI -d $LVL > $SLAVELOG 2>&1 &
+CACHEPID=$!
+
+sleep 8
+echo "Making queries on the proxy cache..." 
+echo "Query 1: filter:(sn=Jon) attrs: all" 
+$LDAPSEARCH -x -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'sn=Jon' > $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+
+echo "Query 2: filter:(|(cn=*Jon*)(sn=Jon*)) attrs:cn sn title"  
+$LDAPSEARCH -x -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       '(|(cn=*Jon*)(sn=Jon*))' cn sn title >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+
+echo "Query 3: filter:(sn=Smith*) attrs:cn sn title"  
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'sn=Smith*' cn sn title >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+
+echo "Query 4: filter:(sn=Doe*) attrs:cn sn title"  
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'sn=Doe' cn sn title >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+echo "Query 5: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber"  
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'uid=bjorn' mail postaladdress telephonenumber >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+
+echo "Query 6: filter:(mail=*@example.com) cn sn title"  
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'mail=*@mail.alumni.example.com' cn sn title >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+
+echo "Query 7: filter:(mail=*) cn sn title"  
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'mail=*' cn sn title >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+# queries 2-6 are cacheable
+CACHEABILITY=0111110
+grep CACHEABLE $SLAVELOG | awk '{ 
+                                 if ($2 == "NOT") 
+                                   printf "Query %d not cacheable\n",NR
+                                 else 
+                                   printf "Query %d cacheable\n",NR
+                               }' 
+CACHED=`grep CACHEABLE $SLAVELOG | awk '{ 
+                                         if ($2 == "NOT") 
+                                           printf "0" 
+                                         else 
+                                           printf "1" 
+                                       }'`
+
+if test $CACHEABILITY = $CACHED
+then
+       echo "successfully verified cacheability"
+else 
+       echo "error in verifying cacheability"
+       kill -HUP $PID $CACHEPID
+       exit 1
+fi
+
+echo "Query 8: filter:(|(cn=*Jones)(sn=Jones)) attrs:cn sn title"  
+$LDAPSEARCH -x -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       '(|(cn=*Jones)(sn=Jones))' cn sn title >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+
+echo "Query 9: filter:(sn=Smith) attrs:cn sn title"  
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'sn=Smith' cn sn title >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+
+echo "Query 10: filter:(uid=bjorn) attrs:mail postaladdress telephonenumber"  
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'uid=bjorn' mail postaladdress telephonenumber >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+
+echo "Query 11: filter:(mail=*@example.com) cn sn title"  
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $SLAVEPORT \
+       'mail=jaj@mail.alumni.example.com' cn sn title >> $SLAVEOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       kill -HUP $PID $CACHEPID
+       exit $RC
+fi
+sleep 3
+#queries 8-11 are answerable
+ANSWERABILITY=1111
+grep ANSWERABLE $SLAVELOG | awk '{ 
+                                   if (NR > 7) { 
+                                     if ($2 == "NOT") 
+                                       printf "Query %d not answerable\n",NR
+                                     else 
+                                       printf "Query %d answerable\n",NR 
+                                    }
+                                 }' 
+ANSWERED=`grep ANSWERABLE $SLAVELOG | awk '{ 
+                                            if (NR > 7) { 
+                                              if ($2 == "NOT") 
+                                                printf "0" 
+                                              else 
+                                                printf "1"
+                                            } 
+                                          }'`
+if test $ANSWERABILITY = $ANSWERED
+then
+       echo "successfully verified answerability"
+else 
+       echo "error in verifying answerability"
+       kill -HUP $PID $CACHEPID
+       exit 1
+fi
+
+echo "Proxy cache successfully tested" 
+kill -HUP $PID $CACHEPID