]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-meta/cache-search.c
Fix prev commit, return generated passwd
[openldap] / servers / slapd / back-meta / cache-search.c
index c6e7127317a2d8ffb94880f8ca05f1d6b82d832b..e31b1c18119838fe2c091a72c027385fd4eca6fd 100644 (file)
@@ -1,22 +1,25 @@
-/*
- * Copyright (c) 2003 by International Business Machines, Inc.
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * International Business Machines, Inc. (hereinafter called IBM) grants
- * permission under its copyrights to use, copy, modify, and distribute this
- * Software with or without fee, provided that the above copyright notice and
- * all paragraphs of this notice appear in all copies, and that the name of IBM
- * not be used in connection with the marketing of any product incorporating
- * the Software or modifications thereof, without specific, written prior
- * permission.
+ * Copyright 1999-2003 The OpenLDAP Foundation.
+ * Portions Copyright 2003 IBM Corporation.
+ * All rights reserved.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
- * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
- * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
  *
- * 
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by the Howard Chu for inclusion
+ * in OpenLDAP Software and subsequently enhanced by Pierangelo
+ * Masarati and Apurva Kumar.
+ */
+/* This is an altered version */
+/*
  * This software is based on the backends back-ldap and back-meta, implemented
  * by Howard Chu <hyc@highlandsun.com>, Mark Valence
  * <kurash@sassafras.com>, Pierangelo Masarati <ando@sys-net.it> and other
 #include <ac/string.h>
 #include <ac/time.h>
 
+#include "ldap_pvt.h"
 #include "lutil.h"
 #include "slap.h"
 #include "../back-ldap/back-ldap.h"
 #include "back-meta.h"
-#include "ldap_pvt.h"
 #undef ldap_debug      /* silence a warning in ldap-int.h */
 #include "ldap_log.h"
 #include "../../../libraries/libldap/ldap-int.h"
-#include <sys/time.h>
 
-#ifdef LDAP_CACHING 
 static Entry* 
 meta_create_entry(
        Backend         *be,
@@ -123,12 +124,11 @@ is_one_level_rdn(
 
 static struct metaconn*  
 metaConnect(
-       struct metainfo* li, 
-       Connection* conn, 
-       Operation* op, 
-       int op_type, 
-       struct berval* nbase, 
-       struct exception* result 
+       Operation               *op, 
+       SlapReply               *rs,
+       int                     op_type, 
+       struct berval           *nbase, 
+       struct exception        *result 
 );
 
 static void
@@ -142,6 +142,7 @@ static int
 handleLdapResult(
        struct metaconn* lc, 
        Operation* op, 
+       SlapReply *rs,
        int* msgid, Backend* be, 
        AttributeName* attrs, 
        int attrsonly, 
@@ -189,10 +190,10 @@ attrscmp(
 
 static char* 
 cache_entries(
+       Operation       *op,
+       SlapReply       *rs,
        Entry** entry_array, 
        cache_manager* cm, 
-       Backend* be, 
-       Connection* conn, 
        struct exception* result
 ); 
 
@@ -204,26 +205,23 @@ is_temp_answerable(
        int template_id
 );
 
-static void
+static void*
 consistency_check(
-       Backend* be,
-       Backend* glue_be, 
-       Connection* conn
+       void    *op
 ); 
 
 static int
 cache_back_sentry(
-       Backend* be, 
-       Connection* conn,
        Operation* op, 
-       Entry* e, 
-       AttributeName* attrs, 
-       int attrsonly, 
-       LDAPControl** ctrls
+       SlapReply *rs
 );
 
+
 int
 meta_back_cache_search(
+       Operation       *op,
+       SlapReply       *rs )
+       /*
        Backend         *be,
        Connection      *conn,
        Operation       *op,
@@ -237,14 +235,16 @@ meta_back_cache_search(
        struct berval   *filterstr,
        AttributeName   *attributes,
        int             attrsonly
-)
+) */
 {
-       struct metainfo         *li = ( struct metainfo * )be->be_private;
+       struct metainfo         *li = ( struct metainfo * )op->o_bd->be_private;
        struct metaconn         *lc;
        struct metasingleconn   *lsc;
        cache_manager*          cm = li->cm; 
        query_manager*          qm = cm->qm; 
 
+       Operation               *oper;
+
        time_t                  curr_time; 
 
        int count, rc = 0, *msgid = NULL; 
@@ -255,10 +255,10 @@ meta_back_cache_search(
        int i = -1, last = 0, candidates = 0, op_type;
 
        struct berval   mfilter;
-       struct berval   *cachebase = NULL;  
-       struct berval   *ncachebase = NULL;  
+       struct berval   cachebase = { 0L, NULL };  
+       struct berval   ncachebase = { 0L, NULL };  
        struct berval   cache_suffix; 
-       struct berval   tempstr = {0, 0}; 
+       struct berval   tempstr = { 0L, NULL }; 
 
        AttributeName   *filter_attrs = NULL; 
        AttributeName   *new_attrs = NULL; 
@@ -276,24 +276,26 @@ meta_back_cache_search(
        int             num_entries = 0;
        int             curr_limit;
        int             fattr_cnt=0; 
+       int             oc_attr_absent = 1;
 
-   
        struct exception result[1]; 
 
-       Filter* filter = str2filter(filterstr->bv_val); 
-       slap_callback cb = {NULL, NULL, cache_back_sentry, NULL}; 
+       Filter* filter = str2filter(op->ors_filterstr.bv_val); 
+       slap_callback cb = {cache_back_sentry, NULL}; 
 
-       cb.sc_private = be
+       cb.sc_private = op->o_bd
 
-       if (attributes) {
-               for ( count=0; attributes[ count ].an_name.bv_val; count++ )
-                       ;
-               attrs = (AttributeName*)malloc( ( count + 1 ) *
-                                               sizeof(AttributeName));
-               for ( count=0; attributes[ count ].an_name.bv_val; count++ ) {
+       if (op->ors_attrs) {
+               for ( count=0; op->ors_attrs[ count ].an_name.bv_val; count++ ) {
+                       if ( op->ors_attrs[count].an_desc == slap_schema.si_ad_objectClass )
+                               oc_attr_absent = 0;
+               }
+               attrs = (AttributeName*)malloc( ( count + 1 + oc_attr_absent )
+                                                               *sizeof(AttributeName));
+               for ( count=0; op->ors_attrs[ count ].an_name.bv_val; count++ ) {
                        ber_dupbv(&attrs[ count ].an_name,
-                                               &attributes[ count ].an_name);
-                       attrs[count].an_desc = attributes[count].an_desc; 
+                                               &op->ors_attrs[ count ].an_name);
+                       attrs[count].an_desc = op->ors_attrs[count].an_desc; 
                }
                attrs[ count ].an_name.bv_val = NULL;
                attrs[ count ].an_name.bv_len = 0;
@@ -309,7 +311,16 @@ 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*)oper); 
+       }       
+       ldap_pvt_thread_mutex_unlock(&cm->cc_mutex); 
+
        filter2template(filter, &tempstr, &filter_attrs, &fattr_cnt, result);  
        if (result->type != SUCCESS) 
                goto Catch; 
@@ -328,8 +339,8 @@ meta_back_cache_search(
     
        query.filter = filter; 
        query.attrs = attrs; 
-       query.base = *base
-       query.scope = scope; 
+       query.base = op->o_req_dn
+       query.scope = op->ors_scope; 
 
        /* check for query containment */
        if (attr_set > -1) {
@@ -344,10 +355,10 @@ meta_back_cache_search(
 #ifdef NEW_LOGGING
                        LDAP_LOG( BACK_META, DETAIL2,
                                        "Entering QC, querystr = %s\n",
-                                       filterstr->bv_val, 0, 0 );
+                                       op->ors_filterstr.bv_val, 0, 0 );
 #else /* !NEW_LOGGING */
                        Debug( LDAP_DEBUG_NONE, "Entering QC, querystr = %s\n",
-                                               filterstr->bv_val, 0, 0 );
+                                       op->ors_filterstr.bv_val, 0, 0 );
 #endif /* !NEW_LOGGING */
                        answerable = (*(qm->qcfunc))(qm, &query, i);
 
@@ -356,29 +367,58 @@ meta_back_cache_search(
                }
        }
 
+       if ( attrs && oc_attr_absent ) {
+               for ( count = 0; attrs[count].an_name.bv_val; count++) ;
+               attrs[ count ].an_name.bv_val = "objectClass";
+               attrs[ count ].an_name.bv_len = strlen( "objectClass" );
+               attrs[ count ].an_desc = slap_schema.si_ad_objectClass;
+               attrs[ count + 1 ].an_name.bv_val = NULL;
+               attrs[ count + 1 ].an_name.bv_len = 0;
+       }
+
        if (answerable) {
+               Operation       op_tmp;
+
 #ifdef NEW_LOGGING
                LDAP_LOG( BACK_META, DETAIL1, "QUERY ANSWERABLE\n", 0, 0, 0 );
 #else /* !NEW_LOGGING */
                Debug( LDAP_DEBUG_ANY, "QUERY ANSWERABLE\n", 0, 0, 0 );
 #endif /* !NEW_LOGGING */
-               rewriteSession(li->rwinfo, "cacheBase", nbase->bv_val,
-                                       conn, &cbase, result); 
+               rewriteSession(li->rwinfo, "cacheBase", op->o_req_dn.bv_val,
+                                       op->o_conn, &cbase, result); 
                if (result->type != SUCCESS) { 
                        ldap_pvt_thread_rdwr_runlock(&qm->templates[i].t_rwlock); 
                        goto Catch; 
                }
-               cachebase = ber_str2bv(cbase, strlen(cbase), 0, NULL);  
-               dnNormalize(NULL, cachebase, &ncachebase); 
-       
-               op->o_caching_on = 1;   
-               op->o_callback = &cb; 
-               li->glue_be->be_search(li->glue_be, conn, op, cachebase,
-                               ncachebase, scope, deref, slimit, tlimit,
-                               filter, filterstr, attrs, attrsonly);
+               if ( cbase == NULL ) {
+                       cachebase = op->o_req_dn;
+               } else {
+                       cachebase.bv_val = cbase;
+                       cachebase.bv_len = strlen(cbase);
+               }
+               dnNormalize(0, NULL, NULL, &cachebase, &ncachebase,
+                               op->o_tmpmemctx); 
+
+               /* FIXME: safe default? */
+               op_tmp = *op;
+
+               op_tmp.o_bd = li->glue_be;
+               op_tmp.o_req_dn = cachebase;
+               op_tmp.o_req_ndn = ncachebase;
+
+               op_tmp.o_callback = &cb; 
+
+               li->glue_be->be_search(&op_tmp, rs);
+               free( ncachebase.bv_val );
+               if ( cachebase.bv_val != op->o_req_dn.bv_val ) {
+                       /* free only if rewritten */
+                       free( cachebase.bv_val );
+               }
 
                ldap_pvt_thread_rdwr_runlock(&qm->templates[i].t_rwlock); 
        } else {
+               Operation       op_tmp;
+               op_tmp = *op;
 #ifdef NEW_LOGGING
                LDAP_LOG( BACK_META, DETAIL1, "QUERY NOT ANSWERABLE\n",
                                        0, 0, 0 );
@@ -386,13 +426,14 @@ meta_back_cache_search(
                Debug( LDAP_DEBUG_ANY, "QUERY NOT ANSWERABLE\n", 0, 0, 0 );
 #endif /* !NEW_LOGGING */
 
-               if ( 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(li, conn, op, op_type, nbase, result);
+               lc = metaConnect(&op_tmp, rs, op_type,
+                               &op->o_req_ndn, result);
 
                if (result->type != SUCCESS) 
                        goto Catch; 
@@ -404,14 +445,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; 
@@ -438,38 +471,39 @@ meta_back_cache_search(
                 */
 
                for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
-                       char    *realbase = ( char * )base->bv_val;
-                       int     realscope = scope;
+                       char    *realbase = ( char * )op->o_req_dn.bv_val;
+                       int     realscope = op->ors_scope;
                        ber_len_t suffixlen;
                        char    *mapped_filter, **mapped_attrs;
 
                        /* FIXME: Check for more than one targets */
                        if ( meta_back_is_candidate(
-                                       &li->targets[i]->suffix, nbase ))
+                                       &li->targets[i]->suffix,
+                                       &op->o_req_ndn ))
                                lsc->candidate = META_CANDIDATE; 
 
                        if ( lsc->candidate != META_CANDIDATE ) 
                                continue;
 
-                       if ( deref != -1 ) {
+                       if ( op->ors_deref != -1 ) {
                                ldap_set_option( lsc->ld, LDAP_OPT_DEREF,
-                                               ( void * )&deref);
+                                               ( void * )&op->ors_deref);
                        }
-                       if ( tlimit != -1 ) {
+                       if ( op->ors_tlimit != -1 ) {
                                ldap_set_option( lsc->ld, LDAP_OPT_TIMELIMIT,
-                                               ( void * )&tlimit);
+                                               ( void * )&op->ors_tlimit);
                        }
-                       if ( slimit != -1 ) {
+                       if ( op->ors_slimit != -1 ) {
                                ldap_set_option( lsc->ld, LDAP_OPT_SIZELIMIT,
-                                               ( void * )&slimit);
+                                               ( void * )&op->ors_slimit);
                        }
 
                        /*
                         * modifies the base according to the scope, if required
                         */
                        suffixlen = li->targets[ i ]->suffix.bv_len;
-                       if ( suffixlen > nbase->bv_len ) {
-                               switch ( scope ) {
+                       if ( suffixlen > op->o_req_ndn.bv_len ) {
+                               switch ( op->ors_scope ) {
                                case LDAP_SCOPE_SUBTREE:
                                        /*
                                         * make the target suffix the new base
@@ -479,7 +513,7 @@ meta_back_cache_search(
                                         */
                                        if ( dnIsSuffix(
                                                &li->targets[ i ]->suffix,
-                                               nbase ) ) {
+                                               &op->o_req_ndn ) ) {
                                                realbase =
                                                li->targets[i]->suffix.bv_val;
                                        } else {
@@ -496,10 +530,10 @@ meta_back_cache_search(
                                case LDAP_SCOPE_ONELEVEL:
                                        if ( is_one_level_rdn(
                                                li->targets[ i ]->suffix.bv_val,
-                                               suffixlen - nbase->bv_len - 1 )
+                                               suffixlen - op->o_req_ndn.bv_len - 1 )
                                                && dnIsSuffix(
                                                &li->targets[ i ]->suffix,
-                                               nbase ) ) {
+                                               &op->o_req_ndn ) ) {
                                                /*
                                                 * if there is exactly one
                                                 * level, make the target suffix
@@ -511,6 +545,7 @@ meta_back_cache_search(
                                                realscope = LDAP_SCOPE_BASE;
                                                break;
                                        } /* else continue with the next case */
+
                                case LDAP_SCOPE_BASE:
                                        /*
                                         * this target is no longer candidate
@@ -524,8 +559,9 @@ meta_back_cache_search(
                         * Rewrite the search base, if required
                         */
 
-                       rewriteSession(li->targets[i]->rwinfo, "searchBase",
-                                       realbase, conn, &mbase, result); 
+                       rewriteSession(li->targets[i]->rwmap.rwm_rw,
+                                       "searchBase",
+                                       realbase, op->o_conn, &mbase, result); 
 
                        if (result->type != SUCCESS)
                                goto Catch; 
@@ -537,8 +573,9 @@ meta_back_cache_search(
                        /*
                         * Rewrite the search filter, if required
                         */
-                       rewriteSession( li->targets[i]->rwinfo, "searchFilter",
-                                       filterstr->bv_val, conn,
+                       rewriteSession( li->targets[i]->rwmap.rwm_rw,
+                                       "searchFilter",
+                                       op->ors_filterstr.bv_val, op->o_conn,
                                        &mfilter.bv_val, result);
                        if (result->type != SUCCESS) 
                                goto Catch; 
@@ -550,45 +587,37 @@ meta_back_cache_search(
                                if ( mfilter.bv_val != NULL ) {
                                        free( mfilter.bv_val );
                                }
-                               mfilter = *filterstr;
+                               mfilter = op->ors_filterstr;
                        }
 
+#if 0
                        /*
                         * Maps attributes in filter
                         */
                        mapped_filter = ldap_back_map_filter(
-                                       &li->targets[i]->at_map,
-                                       &li->targets[i]->oc_map, &mfilter, 0 );
+                                       &li->targets[i]->rwmap.rwm_at,
+                                       &li->targets[i]->rwmap.rwm_oc,
+                                       &mfilter, 0 );
                        if ( mapped_filter == NULL ) {
                                mapped_filter = ( char * )mfilter.bv_val;
                        } else {
-                               if ( mfilter.bv_val != filterstr->bv_val ) {
+                               if ( mfilter.bv_val != op->ors_filterstr.bv_val ) {
                                        free( mfilter.bv_val );
                                }
                        }
                        mfilter.bv_val = NULL;
                        mfilter.bv_len = 0;
+#else
+                       mapped_filter = (char *) mfilter.bv_val;
+#endif
 
                        /*
                         * Maps required attributes
                         */
-                       mapped_attrs = ldap_back_map_attrs(
-                                       &li->targets[ i ]->at_map,
-                                       new_attrs, 0 );
-                       if ( mapped_attrs == NULL && new_attrs) {
-                               for ( count=0;
-                                     new_attrs[ count ].an_name.bv_val;
-                                     count++)
-                                       ;
-                               mapped_attrs = ch_malloc( ( count + 1 ) *
-                                                       sizeof(char *));
-                               for ( count=0;
-                                     new_attrs[ count ].an_name.bv_val;
-                                     count++ ) {
-                                       mapped_attrs[ count ] =
-                                               new_attrs[count].an_name.bv_val;
-                               }
-                               mapped_attrs[ count ] = NULL;
+                       if ( ldap_back_map_attrs(
+                                       &li->targets[ i ]->rwmap.rwm_at,
+                                       new_attrs, 0, &mapped_attrs ) ) {
+                               goto Catch;
                        }
 
                        /*
@@ -596,10 +625,15 @@ meta_back_cache_search(
                         */
                        msgid[ i ] = ldap_search( lsc->ld, mbase, realscope,
                                                mapped_filter, mapped_attrs,
-                                               attrsonly ); 
+                                               op->ors_attrsonly );
+
                        if ( msgid[ i ] == -1 ) {
+                               result->type = CONN_ERR; 
+                               goto Catch; 
+                               /*
                                lsc->candidate = META_NOT_CANDIDATE;
                                continue;
+                               */
                        }
 
                        if ( mapped_attrs ) {
@@ -607,7 +641,7 @@ meta_back_cache_search(
                                mapped_attrs = NULL;
                        }
 
-                       if ( mapped_filter != filterstr->bv_val ) {
+                       if ( mapped_filter != op->ors_filterstr.bv_val ) {
                                free( mapped_filter );
                                mapped_filter = NULL;
                        }
@@ -620,29 +654,34 @@ meta_back_cache_search(
                        ++candidates;
                }
 
-               num_entries = handleLdapResult(lc, op, msgid, be, attrs,
-                               attrsonly, candidates, cacheable, &entry_array,
-                               curr_limit, slimit, result); 
+               num_entries = handleLdapResult(lc, &op_tmp, rs, msgid,
+                               op->o_bd, attrs,
+                               op->ors_attrsonly, candidates, 
+                               cacheable, &entry_array,
+                               curr_limit, op->ors_slimit, result); 
 
                if (result->type != SUCCESS) 
                        goto Catch; 
                if (cacheable && (num_entries <= curr_limit)) {
+
 #ifdef NEW_LOGGING
                        LDAP_LOG( BACK_META, DETAIL1,
                                        "QUERY CACHEABLE\n", 0, 0, 0 );
 #else /* !NEW_LOGGING */
                        Debug( LDAP_DEBUG_ANY, "QUERY CACHEABLE\n", 0, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       uuid = cache_entries(entry_array, cm, li->glue_be,
-                                                       conn, result); 
+                       op_tmp.o_bd = li->glue_be;
+                       uuid = cache_entries(&op_tmp, rs, entry_array, cm, result); 
 #ifdef NEW_LOGGING
                        LDAP_LOG( BACK_META, DETAIL1,
                                        "Added query %s UUID %s ENTRIES %d\n",
-                                       filterstr->bv_val, uuid, num_entries );
+                                       op->ors_filterstr.bv_val,
+                                       uuid, num_entries );
 #else /* !NEW_LOGGING */
                        Debug( LDAP_DEBUG_ANY,
                                        "Added query %s UUID %s ENTRIES %d\n",
-                                       filterstr->bv_val, uuid, num_entries );
+                                       op->ors_filterstr.bv_val,
+                                       uuid, num_entries );
 #endif /* !NEW_LOGGING */
            
                        if (result->type != SUCCESS) 
@@ -652,14 +691,37 @@ meta_back_cache_search(
                                goto Catch; 
                        filter = 0; 
                        attrs = 0; 
+
+                       /* FIXME : launch do_syncrepl() threads around here
+                        *
+                        * entryUUID and entryCSN need also to be requested by :
+                        */
+                       /*
+                       msgid[ i ] = ldap_search( lsc->ld, mbase, realscope,
+                                               mapped_filter, mapped_attrs, op->ors_attrsonly );
+                       */
+                       /* Also, mbase, realscope, mapped_filter, mapped_attrs need
+                        * be managed as arrays. Each element needs to be retained by this point.
+                        */
+
+               } 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 */
                }
        }
 
-Catch: 
+Catch:;
        switch (result->type) {
                case SUCCESS: 
-                       rc=0; 
-                       break; 
+                       rc = 0; 
+                       break;
+
                case FILTER_ERR: 
 #ifdef NEW_LOGGING
                        LDAP_LOG( BACK_META, DETAIL1,
@@ -669,6 +731,7 @@ Catch:
                                        0, 0, 0 );
 #endif /* !NEW_LOGGING */
                        break; 
+
                case CONN_ERR: 
                        rc = -1; 
 #ifdef NEW_LOGGING
@@ -680,10 +743,10 @@ Catch:
                                "Could not connect to a remote server\n",
                                0, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       send_ldap_result(conn, op, LDAP_OTHER,  
-                                       NULL, "Connection error",
-                                       NULL, NULL );
-                       break; 
+                       send_ldap_error(op, rs, LDAP_OTHER,
+                                       "Connection error" );
+                       break;
+                       
                case RESULT_ERR: 
                        rc = -1; 
 #ifdef NEW_LOGGING
@@ -694,19 +757,19 @@ Catch:
                                "Error in handling ldap_result\n", 0, 0, 0 );
 #endif /* !NEW_LOGGING */
                        break; 
+
                case REWRITING_ERR: 
                        rc = -1; 
                        if (result->rc == REWRITE_REGEXEC_UNWILLING) {
-                               send_ldap_result( conn, op,
+                               send_ldap_error( op, rs,
                                                LDAP_UNWILLING_TO_PERFORM,
-                                               NULL, "Unwilling to perform",
-                                               NULL, NULL );
+                                               "Unwilling to perform" );
                        } else {
-                               send_ldap_result( conn, op, LDAP_OTHER,
-                                               NULL, "Rewrite error",
-                                               NULL, NULL );
+                               send_ldap_error( op, rs, LDAP_OTHER,
+                                               "Rewrite error" );
                        }
-                       break; 
+                       break;
+
                case MERGE_ERR: 
                        rc = -1; 
 #ifdef NEW_LOGGING
@@ -716,7 +779,8 @@ Catch:
                        Debug( LDAP_DEBUG_ANY,
                                "Error in merging entry \n", 0, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       break; 
+                       break;
+
                case REMOVE_ERR: 
                        rc = -1; 
 #ifdef NEW_LOGGING
@@ -727,18 +791,13 @@ Catch:
                        Debug( LDAP_DEBUG_ANY, "Error in removing query \n",
                                        0, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       break; 
+                       break;
+
                default:
                        /* assert(0); */
+                       break;
        }
 
-       ldap_pvt_thread_mutex_lock(&cm->consistency_mutex); 
-       curr_time = slap_get_time(); 
-       if (curr_time - cm->consistency_time > cm->consistency_cycle_time) {
-               cm->consistency_time = curr_time; 
-               consistency_check(be, li->glue_be, conn); 
-       }       
-       ldap_pvt_thread_mutex_unlock(&cm->consistency_mutex); 
 
        if ( msgid ) {
                ch_free( msgid );
@@ -788,11 +847,15 @@ meta_create_entry (
        struct berval           a, mapped;
        Entry*                  ent;
        BerElement              ber = *e->lm_ber;
-       Attribute               *attr, **attrp;
-       struct berval           dummy = { 0, NULL };
-       struct berval           *bv, bdn;
-       const char              *text;
-        char*                  ename = NULL; 
+       Attribute               *attr, *soc_attr, **attrp;
+       struct berval   dummy = { 0, NULL };
+       struct berval   *bv, bdn;
+       const char              *text = NULL;
+       char*                   ename = NULL; 
+       struct berval   sc = { 0, NULL };
+       char                    textbuf[SLAP_TEXT_BUFLEN];
+       size_t                  textlen = sizeof(textbuf);
+
        if ( ber_scanf( &ber, "{m{", &bdn ) == LBER_ERROR ) {
                result->type = CREATE_ENTRY_ERR;        
                return NULL; 
@@ -802,7 +865,7 @@ meta_create_entry (
        /*
         * Rewrite the dn of the result, if needed
         */
-       rewriteSession( li->targets[ target ]->rwinfo, "searchResult",
+       rewriteSession( li->targets[ target ]->rwmap.rwm_rw, "searchResult",
                        bdn.bv_val, lc->conn, &ent->e_name.bv_val, result );  
 
        if (result->type != SUCCESS) {
@@ -828,12 +891,14 @@ meta_create_entry (
         * from the one known to the meta, and a DN with unknown
         * attributes is returned.
         * 
-        * FIXME: should we log anything, or delegate to dnNormalize2?
+        * FIXME: should we log anything, or delegate to dnNormalize?
         */
-       dnNormalize2( NULL, &ent->e_name, &ent->e_nname ); 
+       dnNormalize( 0, NULL, NULL, &ent->e_name, &ent->e_nname, NULL ); 
 
        /*
-       if ( dnNormalize2( NULL, &ent->e_name, &ent->e_nname ) != LDAP_SUCCESS ) {
+       if ( dnNormalize( 0, NULL, NULL, &ent->e_name, &ent->e_nname )
+               != LDAP_SUCCESS )
+       {
                return LDAP_INVALID_DN_SYNTAX;
        }
        */
@@ -853,7 +918,8 @@ meta_create_entry (
        attrp = &ent->e_attrs;
 
        while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
-               ldap_back_map( &li->targets[ target ]->at_map, &a, &mapped, 1 );
+               ldap_back_map( &li->targets[ target ]->rwmap.rwm_at, 
+                               &a, &mapped, 1 );
                if ( mapped.bv_val == NULL ) {
                        continue;
                }
@@ -864,6 +930,7 @@ meta_create_entry (
                attr->a_flags = 0;
                attr->a_next = 0;
                attr->a_desc = NULL;
+               attr->a_nvals = NULL;
                if ( slap_bv2ad( &mapped, &attr->a_desc, &text ) != LDAP_SUCCESS) {
                        if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text ) 
                                        != LDAP_SUCCESS) {
@@ -890,14 +957,18 @@ meta_create_entry (
                if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR 
                                || attr->a_vals == NULL ) {
                        attr->a_vals = &dummy;
+#if 0
                } else if ( attr->a_desc == slap_schema.si_ad_objectClass ||
                                attr->a_desc ==
                                slap_schema.si_ad_structuralObjectClass) {
+#else
+               } else if ( attr->a_desc == slap_schema.si_ad_objectClass ) {
+#endif
                        int i, last;
                        for ( last = 0; attr->a_vals[ last ].bv_val; ++last )
                                ;
                        for ( i = 0, bv = attr->a_vals; bv->bv_val; bv++,i++ ) {
-                               ldap_back_map( &li->targets[ target]->oc_map,
+                               ldap_back_map( &li->targets[ target]->rwmap.rwm_oc,
                                                bv, &mapped, 1 );
                                if ( mapped.bv_val == NULL ) {
                                        free( bv->bv_val );
@@ -913,6 +984,22 @@ meta_create_entry (
                                        ber_dupbv( bv, &mapped );
                                }
                        }
+
+                       structural_class( attr->a_vals, &sc, NULL, &text, textbuf, textlen );
+                       soc_attr = (Attribute*) ch_malloc( sizeof( Attribute ));
+                       soc_attr->a_desc = slap_schema.si_ad_structuralObjectClass;
+                       soc_attr->a_vals = (BerVarray) ch_malloc( 2* sizeof( BerValue ));
+                       ber_dupbv( &soc_attr->a_vals[0], &sc );
+                       soc_attr->a_vals[1].bv_len = 0;
+                       soc_attr->a_vals[1].bv_val = NULL;
+                       soc_attr->a_nvals = (BerVarray) ch_malloc( 2* sizeof( BerValue ));
+                       ber_dupbv( &soc_attr->a_nvals[0], &sc );
+                       soc_attr->a_nvals[1].bv_len = 0;
+                       soc_attr->a_nvals[1].bv_val = NULL;
+
+                       *attrp = soc_attr;
+                       attrp = &soc_attr->a_next;
+
                /*
                 * It is necessary to try to rewrite attributes with
                 * dn syntax because they might be used in ACLs as
@@ -929,7 +1016,7 @@ meta_create_entry (
                        int i;
                        for ( i = 0, bv = attr->a_vals; bv->bv_val; bv++,i++ ) {
                                char *newval;
-                               rewriteSession(li->targets[ target ]->rwinfo,
+                               rewriteSession(li->targets[ target ]->rwmap.rwm_rw,
                                                "searchResult", bv->bv_val,
                                                lc->conn, &newval, result); 
                                if (result->type != SUCCESS) {
@@ -964,6 +1051,7 @@ meta_create_entry (
                *attrp = attr;
                attrp = &attr->a_next;
        }
+
        return ent; 
 }
 
@@ -983,16 +1071,16 @@ is_one_level_rdn(
 
 static struct metaconn*  
 metaConnect(
-       struct metainfo* li, 
-       Connection* conn, 
-       Operation* op, 
-       int op_type, 
-       struct berval* nbase, 
-       struct exception* result)
+       Operation*              op, 
+       SlapReply               *rs,
+       int                     op_type, 
+       struct berval           *nbase, 
+       struct exception        *result)
 {
-       struct metaconn* lc; 
+       struct metaconn         *lc; 
+
        result->type = SUCCESS; 
-       lc = meta_back_getconn( li, conn, op, op_type, nbase, NULL );
+       lc = meta_back_getconn( op, rs, op_type, nbase, NULL );
        if (!lc) {
                result->type = CONN_ERR; 
                return 0; 
@@ -1018,29 +1106,27 @@ 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_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;  
+               }
+               (*new_attrs)[count].an_name.bv_val = NULL; 
+               (*new_attrs)[count].an_name.bv_len = 0; 
                alluser = an_find(*new_attrs, &all_user); 
                allop = an_find(*new_attrs, &all_op); 
        }
@@ -1048,10 +1134,10 @@ add_filter_attrs(
        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))); 
@@ -1070,6 +1156,7 @@ static int
 handleLdapResult(
        struct metaconn* lc,
        Operation* op, 
+       SlapReply *rs,
        int* msgid, Backend* be, 
        AttributeName* attrs, 
        int attrsonly, 
@@ -1114,9 +1201,12 @@ handleLdapResult(
                        }
 
                        if ((entry = get_result_entry(be, lc, lsc,
-                                               msgid, i, &tv, result))) { 
-                               send_search_entry( be, lc->conn, op, entry,
-                                               attrs, attrsonly, NULL );
+                                               msgid, i, &tv, result))) {
+                               rs->sr_entry = entry;
+                               rs->sr_attrs = op->ors_attrs; 
+                               send_search_entry( op, rs );
+                               rs->sr_entry = NULL;
+                               rs->sr_attrs = NULL; 
                                if ((cacheable) &&
                                                (num_entries < curr_limit))  {
                                        rewriteSession( li->rwinfo,
@@ -1152,7 +1242,8 @@ handleLdapResult(
                        } else if (result->rc == -1) {
                                break; 
                        } else {
-                               sres = ldap_back_map_result(result->rc);
+                               rs->sr_err = result->rc;
+                               sres = ldap_back_map_result(rs);
                                if (mres == LDAP_SUCCESS &&
                                                sres != LDAP_SUCCESS) {
                                        mres = sres; 
@@ -1176,9 +1267,10 @@ handleLdapResult(
                        Debug( LDAP_DEBUG_ANY, "ldap_result error, rc = -1\n",
                                        0, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       send_search_result( lc->conn, op, LDAP_OTHER, NULL,
-                                       NULL, NULL, NULL, num_entries );
+                       rs->sr_err = LDAP_OTHER;
+                       send_ldap_result( op, rs );
                        return 0; 
+
                case CREATE_ENTRY_ERR: 
 #ifdef NEW_LOGGING
                        LDAP_LOG( BACK_META, DETAIL1,
@@ -1188,10 +1280,11 @@ handleLdapResult(
                        Debug( LDAP_DEBUG_ANY, "Error in parsing result \n",
                                        0, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       send_search_result( lc->conn, op, LDAP_OTHER, NULL,
-                                       NULL, NULL, NULL, num_entries );
+                       rs->sr_err = LDAP_OTHER;
+                       send_ldap_result( op, rs );
                        result->type = RESULT_ERR; 
                        return 0; 
+
                case SLIMIT_ERR: 
 #ifdef NEW_LOGGING
                        LDAP_LOG( BACK_META, DETAIL1, "Size limit exceeded \n",
@@ -1200,11 +1293,11 @@ handleLdapResult(
                        Debug( LDAP_DEBUG_ANY, "Size limit exceeded \n",
                                        0, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       send_search_result( lc->conn, op,
-                                       LDAP_SIZELIMIT_EXCEEDED,
-                                       NULL, NULL, NULL, NULL, num_entries );
+                       rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+                       send_ldap_result( op, rs );
                        result->type = RESULT_ERR; 
-                       return 0; 
+                       return 0;
+
                case ABANDON_ERR: 
 #ifdef NEW_LOGGING
                        LDAP_LOG( BACK_META, DETAIL1,
@@ -1216,8 +1309,10 @@ handleLdapResult(
 #endif /* !NEW_LOGGING */
                        result->type = RESULT_ERR; 
                        return 0; 
+
                default:
                        /* assert( 0 ); */
+                       break;
                }
                if ( gotit == 0 ) {
                        tv.tv_sec = 0;
@@ -1229,8 +1324,14 @@ handleLdapResult(
                }
        }
 
-       send_search_result( lc->conn, op, mres, match, err,
-                               NULL, NULL, num_entries );
+       rs->sr_err = mres;
+       rs->sr_text = err;
+       rs->sr_matched = match;
+
+       send_ldap_result( op, rs );
+
+       rs->sr_text = NULL;
+       rs->sr_matched = NULL;
 
        if (err) 
                free(err); 
@@ -1382,8 +1483,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++ )
@@ -1404,21 +1509,21 @@ attrscmp(
 
 static char* 
 cache_entries(
+       Operation       *op,
+       SlapReply       *rs,
        Entry** entry_array, 
        cache_manager* cm, 
-       Backend* be, 
-       Connection* conn, 
        struct exception* result)
 {
-       int i; 
-       int return_val; 
-       int cache_size; 
-       Entrye; 
-       struct berval query_uuid; 
-       struct berval crp_uuid; 
-       char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ], *crpid; 
-       char crpuuid[40]; 
-       query_managerqm = cm->qm;
+       int             i; 
+       int             return_val; 
+       int             cache_size; 
+       Entry           *e; 
+       struct berval   query_uuid; 
+       struct berval   crp_uuid; 
+       char            uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ], *crpid; 
+       char            crpuuid[40]; 
+       query_manager   *qm = cm->qm;
     
        result->type = SUCCESS; 
        query_uuid.bv_len = lutil_uuidstr(uuidbuf, sizeof(uuidbuf)); 
@@ -1463,7 +1568,7 @@ cache_entries(
                                                "Removing query UUID %s\n",
                                                crpuuid, 0, 0 );
 #endif /* !NEW_LOGGING */
-                                       return_val = remove_query_data(be, conn,
+                                       return_val = remove_query_data(op, rs,
                                                        &crp_uuid, result); 
 #ifdef NEW_LOGGING
                                        LDAP_LOG( BACK_META, DETAIL1,
@@ -1480,11 +1585,11 @@ cache_entries(
                                        cm->num_cached_queries--; 
 #ifdef NEW_LOGGING
                                        LDAP_LOG( BACK_META, DETAIL1,
-                                               "STORED QUERIES = %d\n",
+                                               "STORED QUERIES = %lu\n",
                                                cm->num_cached_queries, 0, 0 );
 #else /* !NEW_LOGGING */
                                        Debug( LDAP_DEBUG_ANY,
-                                               "STORED QUERIES = %d\n",
+                                               "STORED QUERIES = %lu\n",
                                                cm->num_cached_queries, 0, 0 );
 #endif /* !NEW_LOGGING */
                                        ldap_pvt_thread_mutex_unlock(
@@ -1495,28 +1600,31 @@ cache_entries(
 #ifdef NEW_LOGGING
                                        LDAP_LOG( BACK_META, DETAIL1,
                                                "QUERY REMOVED, CACHE SIZE="
-                                               "%d bytes %d entries\n",
+                                               "%lu bytes %d entries\n",
                                                cm->cache_size,
                                                cm->total_entries, 0 );
 #else /* !NEW_LOGGING */
                                        Debug( LDAP_DEBUG_ANY,
                                                "QUERY REMOVED, CACHE SIZE="
-                                               "%d bytes %d entries\n",
+                                               "%lu bytes %d entries\n",
                                                cm->cache_size,
                                                cm->total_entries, 0 );
 #endif /* !NEW_LOGGING */
                                }
                        }
                }
-               return_val = merge_entry(be, conn, e, &query_uuid, result);
+
+               rs->sr_entry = e;
+               return_val = merge_entry(op, rs, &query_uuid, result);
+               rs->sr_entry = NULL;
                cm->cache_size += return_val;
 #ifdef NEW_LOGGING
                LDAP_LOG( BACK_META, DETAIL1,
-                       "ENTRY ADDED/MERGED, CACHE SIZE=%d bytes\n",
+                       "ENTRY ADDED/MERGED, CACHE SIZE=%lu bytes\n",
                        cm->cache_size, 0, 0 );
 #else /* !NEW_LOGGING */
                Debug( LDAP_DEBUG_ANY,
-                       "ENTRY ADDED/MERGED, CACHE SIZE=%d bytes\n",
+                       "ENTRY ADDED/MERGED, CACHE SIZE=%lu bytes\n",
                        cm->cache_size, 0, 0 );
 #endif /* !NEW_LOGGING */
 #ifdef NEW_LOGGING
@@ -1550,10 +1658,10 @@ cache_entries(
        ldap_pvt_thread_mutex_lock(&cm->cache_mutex); 
        cm->num_cached_queries++; 
 #ifdef NEW_LOGGING
-       LDAP_LOG( BACK_META, DETAIL1, "STORED QUERIES = %d\n",
+       LDAP_LOG( BACK_META, DETAIL1, "STORED QUERIES = %lu\n",
                        cm->num_cached_queries, 0, 0 );
 #else /* !NEW_LOGGING */
-       Debug( LDAP_DEBUG_ANY, "STORED QUERIES = %d\n",
+       Debug( LDAP_DEBUG_ANY, "STORED QUERIES = %lu\n",
                        cm->num_cached_queries, 0, 0 );
 #endif /* !NEW_LOGGING */
        ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); 
@@ -1593,10 +1701,14 @@ is_temp_answerable(
        return 0; 
 }
 
-static void 
-consistency_check(Backend* be, Backend* glue_be, Connection* conn)
+static void* 
+consistency_check(void* operation)
 {
-       struct metainfo *li = ( struct metainfo * )be->be_private;
+       Operation* op = (Operation*)operation; 
+
+       SlapReply rs = {REP_RESULT}; 
+
+       struct metainfo *li = ( struct metainfo * )op->o_bd->be_private;
        cache_manager*  cm = li->cm; 
        query_manager* qm = cm->qm; 
        CachedQuery* query, *query_prev; 
@@ -1604,121 +1716,132 @@ consistency_check(Backend* be, Backend* glue_be, Connection* conn)
        struct berval uuid;  
        struct exception result; 
        int i, return_val; 
-       QueryTemplate* templ; 
-    
+       QueryTemplate* templ;
+
+
+       op->o_bd = li->glue_be;
       
-       for (i=0; qm->templates[i].querystr; i++) {
-               templ = qm->templates + i; 
-               query = templ->query_last; 
-               curr_time = slap_get_time(); 
-               ldap_pvt_thread_mutex_lock(&cm->remove_mutex); 
-               while (query && (query->expiry_time < curr_time)) {
-                       ldap_pvt_thread_mutex_lock(&qm->lru_mutex); 
-                       remove_query(qm, query); 
-                       ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); 
+        for(;;) {
+               ldap_pvt_thread_sleep(cm->cc_period);     
+               for (i=0; qm->templates[i].querystr; i++) {
+                       templ = qm->templates + i; 
+                       query = templ->query_last; 
+                       curr_time = slap_get_time(); 
+                       ldap_pvt_thread_mutex_lock(&cm->remove_mutex); 
+                       while (query && (query->expiry_time < curr_time)) {
+                               ldap_pvt_thread_mutex_lock(&qm->lru_mutex); 
+                               remove_query(qm, query); 
+                               ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); 
 #ifdef NEW_LOGGING
-                       LDAP_LOG( BACK_META, DETAIL1, "Lock CR index = %d\n",
-                                       i, 0, 0 );
+                               LDAP_LOG( BACK_META, DETAIL1, "Lock CR index = %d\n",
+                                               i, 0, 0 );
 #else /* !NEW_LOGGING */
-                       Debug( LDAP_DEBUG_ANY, "Lock CR index = %d\n",
-                                       i, 0, 0 );
+                               Debug( LDAP_DEBUG_ANY, "Lock CR index = %d\n",
+                                               i, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       ldap_pvt_thread_rdwr_wlock(&templ->t_rwlock);  
-                       remove_from_template(query, templ); 
+                               ldap_pvt_thread_rdwr_wlock(&templ->t_rwlock);  
+                               remove_from_template(query, templ); 
 #ifdef NEW_LOGGING
-                       LDAP_LOG( BACK_META, DETAIL1,
-                                       "TEMPLATE %d QUERIES-- %d\n",
-                                       i, templ->no_of_queries, 0 );
+                               LDAP_LOG( BACK_META, DETAIL1,
+                                               "TEMPLATE %d QUERIES-- %d\n",
+                                               i, templ->no_of_queries, 0 );
 #else /* !NEW_LOGGING */
-                       Debug( LDAP_DEBUG_ANY, "TEMPLATE %d QUERIES-- %d\n",
-                                       i, templ->no_of_queries, 0 );
+                               Debug( LDAP_DEBUG_ANY, "TEMPLATE %d QUERIES-- %d\n",
+                                               i, templ->no_of_queries, 0 );
 #endif /* !NEW_LOGGING */
 #ifdef NEW_LOGGING
-                       LDAP_LOG( BACK_META, DETAIL1, "Unlock CR index = %d\n",
-                                       i, 0, 0 );
+                               LDAP_LOG( BACK_META, DETAIL1, "Unlock CR index = %d\n",
+                                               i, 0, 0 );
 #else /* !NEW_LOGGING */
-                       Debug( LDAP_DEBUG_ANY, "Unlock CR index = %d\n",
-                                       i, 0, 0 );
+                               Debug( LDAP_DEBUG_ANY, "Unlock CR index = %d\n",
+                                               i, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       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(glue_be, conn,
-                                               &uuid, &result); 
+                               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); 
 #ifdef NEW_LOGGING
-                       LDAP_LOG( BACK_META, DETAIL1,
-                                       "STALE QUERY REMOVED, SIZE=%d\n",
-                                       return_val, 0, 0 );
-#else /* !NEW_LOGGING */
-                       Debug( LDAP_DEBUG_ANY, "STALE QUERY REMOVED, SIZE=%d\n",
+                               LDAP_LOG( BACK_META, DETAIL1,
+                                               "STALE QUERY REMOVED, SIZE=%d\n",
                                                return_val, 0, 0 );
+#else /* !NEW_LOGGING */
+                               Debug( LDAP_DEBUG_ANY, "STALE QUERY REMOVED, SIZE=%d\n",
+                                                       return_val, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       ldap_pvt_thread_mutex_lock(&cm->cache_mutex); 
-                       cm->total_entries -= result.rc; 
-                       cm->num_cached_queries--; 
+                               ldap_pvt_thread_mutex_lock(&cm->cache_mutex); 
+                               cm->total_entries -= result.rc; 
+                               cm->num_cached_queries--; 
 #ifdef NEW_LOGGING
-                       LDAP_LOG( BACK_META, DETAIL1, "STORED QUERIES = %d\n",
-                                       cm->num_cached_queries, 0, 0 );
+                               LDAP_LOG( BACK_META, DETAIL1, "STORED QUERIES = %lu\n",
+                                               cm->num_cached_queries, 0, 0 );
 #else /* !NEW_LOGGING */
-                       Debug( LDAP_DEBUG_ANY, "STORED QUERIES = %d\n",
-                                       cm->num_cached_queries, 0, 0 );
+                               Debug( LDAP_DEBUG_ANY, "STORED QUERIES = %lu\n",
+                                               cm->num_cached_queries, 0, 0 );
 #endif /* !NEW_LOGGING */
-                       ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); 
-                       cm->cache_size = (return_val > cm->cache_size) ?
-                                               0: (cm->cache_size-return_val);
+                               ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); 
+                               cm->cache_size = (return_val > cm->cache_size) ?
+                                                       0: (cm->cache_size-return_val);
 #ifdef NEW_LOGGING
-                       LDAP_LOG( BACK_META, DETAIL1,
-                               "STALE QUERY REMOVED, CACHE SIZE=%d bytes %d "
-                               "entries\n", cm->cache_size,
-                               cm->total_entries, 0 );
+                               LDAP_LOG( BACK_META, DETAIL1,
+                                       "STALE QUERY REMOVED, CACHE SIZE=%lu bytes %d "
+                                       "entries\n", cm->cache_size,
+                                       cm->total_entries, 0 );
 #else /* !NEW_LOGGING */
-                       Debug( LDAP_DEBUG_ANY,
-                               "STALE QUERY REMOVED, CACHE SIZE=%d bytes %d "
-                               "entries\n", cm->cache_size,
-                               cm->total_entries, 0 );
+                               Debug( LDAP_DEBUG_ANY,
+                                       "STALE QUERY REMOVED, CACHE SIZE=%lu bytes %d "
+                                       "entries\n", cm->cache_size,
+                                       cm->total_entries, 0 );
 #endif /* !NEW_LOGGING */
-                       query_prev = query; 
-                       query = query->prev; 
-                       free_query(query_prev); 
+                               query_prev = query; 
+                               query = query->prev; 
+                               free_query(query_prev); 
+                       }
+                       ldap_pvt_thread_mutex_unlock(&cm->remove_mutex); 
                }
-               ldap_pvt_thread_mutex_unlock(&cm->remove_mutex); 
        }
 }
 
 static int
 cache_back_sentry(
-       Backend* glue_be, 
-       Connection* conn,
        Operation* op, 
-       Entry* e, 
-       AttributeName* attrs, 
-       int attrsonly, 
-       LDAPControl** ctrls )
+       SlapReply *rs )
 { 
-       slap_callback* cb = op->o_callback; 
-       Backend* be = (Backend*)(cb->sc_private); 
-       struct metainfo *li = ( struct metainfo * )be->be_private;
+       slap_callback           *cb = op->o_callback; 
+       /*struct metainfo       *li = ( struct metainfo * )op->o_bd->be_private;*/
+       Backend* be = (Backend*)(cb->sc_private);
+       struct metainfo         *li = ( struct metainfo * )be->be_private;
  
-       char* ename = NULL; 
-       struct exception result; 
-       struct berval dn; 
-       struct berval ndn; 
-
-       dn = e->e_name; 
-       ndn = e->e_nname; 
-
-       rewriteSession( li->rwinfo,
-               "cacheReturn", e->e_name.bv_val, conn, &ename, &result );  
-       ber_str2bv(ename, strlen(ename), 0, &e->e_name); 
-       ber_dupbv(&e->e_nname, &e->e_name); 
-
-       op->o_callback = NULL; 
-       send_search_entry(be, conn, op, e, attrs, attrsonly, ctrls); 
+       char                    *ename = NULL;
+       struct exception        result;
+       struct berval           dn;
+       struct berval           ndn;
  
-       e->e_name = dn; 
-       e->e_nname = ndn; 
+       if (rs->sr_type == REP_SEARCH) {
+               dn = rs->sr_entry->e_name; 
+               ndn = rs->sr_entry->e_nname; 
+
+               rewriteSession( li->rwinfo, "cacheReturn",
+                               rs->sr_entry->e_name.bv_val, op->o_conn,
+                               &ename, &result );  
+               ber_str2bv(ename, strlen(ename), 0, &rs->sr_entry->e_name); 
+               /* FIXME: should we normalize this? */
+               ber_dupbv(&rs->sr_entry->e_nname, &rs->sr_entry->e_name); 
+
+               op->o_callback = NULL; 
+
+               send_search_entry( op, rs );
+        
+               rs->sr_entry->e_name = dn; 
+               rs->sr_entry->e_nname = ndn; 
+
+               op->o_callback = cb; 
+               return LDAP_SUCCESS; 
+
+       } else if (rs->sr_type == REP_RESULT) { 
+               op->o_callback = NULL; 
+               send_ldap_result( op, rs ); 
+               return LDAP_SUCCESS; 
+       }
 
-       op->o_callback = cb; 
-       return 0;  
+       return LDAP_SUCCESS;
 }
-#endif