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;
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;
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;
}
}
switch (fs->f_choice) {
+ case LDAP_FILTER_OR:
case LDAP_FILTER_AND:
fs = fs->f_and;
fi = fi->f_and;
fs=fs->f_next;
fi=fi->f_next;
break;
+ case LDAP_FILTER_NOT:
+ res=0;
+ break;
default:
break;
}
cache_manager* cm = li->cm;
query_manager* qm = cm->qm;
+ Operation *oper;
+
time_t curr_time;
int count, rc = 0, *msgid = NULL;
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);
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 );
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;
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;
/*
* 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;
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 ) {
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 */
}
}
static struct metaconn*
metaConnect(
- Operation *op,
+ Operation* op,
SlapReply *rs,
int op_type,
struct berval *nbase,
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;
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)));
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++ )
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;
QueryTemplate* templ;
- op.o_bd = li->glue_be;
+ op->o_bd = li->glue_be;
for(;;) {
ldap_pvt_thread_sleep(cm->cc_period);
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",
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
$(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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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@
+
+
-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}/"
PROGDIR=./progs
DBDIR=./test-db
REPLDIR=./test-repl
+CACHEDIR=./test-cache
CONF=$DATADIR/slapd.conf
MCONF=$DATADIR/slapd-master.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
DBCONF=$DBDIR/slapd.conf
ADDCONF=$DBDIR/slapadd.conf
REPLCONF=$REPLDIR/slapd.conf
+CACHECONF=$CACHEDIR/slapd.conf
TOOLARGS="-x $LDAP_TOOLARGS"
TOOLPROTO="-P 3"
--- /dev/null
+#! /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