]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/pcache.c
More #5728 fallout
[openldap] / servers / slapd / overlays / pcache.c
index 618a7bca45c71ac1156f50286b376a6cf704de77..450290fcc3ecbaa9eda4eae7257a14fefb0ae179 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2003-2007 The OpenLDAP Foundation.
+ * Copyright 2003-2008 The OpenLDAP Foundation.
  * Portions Copyright 2003 IBM Corporation.
  * Portions Copyright 2003 Symas Corporation.
  * All rights reserved.
@@ -182,6 +182,7 @@ typedef struct cache_manager_s {
        unsigned long   num_cached_queries;             /* total number of cached queries */
        unsigned long   max_queries;                    /* upper bound on # of cached queries */
        int             save_queries;                   /* save cached queries across restarts */
+       int     check_cacheability;             /* check whether a query is cacheable */
        int     numattrsets;                    /* number of attribute sets */
        int     cur_entries;                    /* current number of entries cached */
        int     max_entries;                    /* max number of entries cached */
@@ -1593,6 +1594,7 @@ struct search_info {
        Query query;
        QueryTemplate *qtemp;
        AttributeName*  save_attrs;     /* original attributes, saved for response */
+       int swap_saved_attrs;
        int max;
        int over;
        int count;
@@ -1901,14 +1903,19 @@ cache_entries(
        Entry           *e;
        struct berval   crp_uuid;
        char            uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
-       Operation op_tmp = *op;
+       Operation       *op_tmp;
+       Connection      conn = {0};
+       OperationBuffer opbuf;
+       void            *thrctx = ldap_pvt_thread_pool_context();
 
        query_uuid->bv_len = lutil_uuidstr(uuidbuf, sizeof(uuidbuf));
        ber_str2bv(uuidbuf, query_uuid->bv_len, 1, query_uuid);
 
-       op_tmp.o_bd = &cm->db;
-       op_tmp.o_dn = cm->db.be_rootdn;
-       op_tmp.o_ndn = cm->db.be_rootndn;
+       connection_fake_init2( &conn, &opbuf, thrctx, 0 );
+       op_tmp = &opbuf.ob_op;
+       op_tmp->o_bd = &cm->db;
+       op_tmp->o_dn = cm->db.be_rootdn;
+       op_tmp->o_ndn = cm->db.be_rootndn;
 
        Debug( pcache_debug, "UUID for query being added = %s\n",
                        uuidbuf, 0, 0 );
@@ -1918,10 +1925,10 @@ cache_entries(
                e->e_private = NULL;
                while ( cm->cur_entries > (cm->max_entries) ) {
                        BER_BVZERO( &crp_uuid );
-                       remove_query_and_data( &op_tmp, rs, cm, &crp_uuid );
+                       remove_query_and_data( op_tmp, rs, cm, &crp_uuid );
                }
 
-               return_val = merge_entry(&op_tmp, e, query_uuid);
+               return_val = merge_entry(op_tmp, e, query_uuid);
                ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
                cm->cur_entries += return_val;
                Debug( pcache_debug,
@@ -1955,6 +1962,14 @@ pcache_op_cleanup( Operation *op, SlapReply *rs ) {
                 * limit, empty the chain and ignore the rest.
                 */
                if ( !si->over ) {
+                       /* check if the entry contains undefined
+                        * attributes/objectClasses (ITS#5680) */
+                       if ( cm->check_cacheability && test_filter( op, rs->sr_entry, si->query.filter ) != LDAP_COMPARE_TRUE ) {
+                               Debug( pcache_debug, "%s: query not cacheable because of schema issues in DN \"%s\"\n",
+                                       op->o_log_prefix, rs->sr_entry->e_name.bv_val, 0 );
+                               goto over;
+                       }
+
                        if ( si->count < si->max ) {
                                si->count++;
                                e = entry_dup( rs->sr_entry );
@@ -1963,6 +1978,7 @@ pcache_op_cleanup( Operation *op, SlapReply *rs ) {
                                si->tail = e;
 
                        } else {
+over:;
                                si->over = 1;
                                si->count = 0;
                                for (;si->head; si->head=e) {
@@ -1979,11 +1995,12 @@ pcache_op_cleanup( Operation *op, SlapReply *rs ) {
        if ( rs->sr_type == REP_RESULT || 
                op->o_abandon || rs->sr_err == SLAPD_ABANDON )
        {
-               if ( si->save_attrs != NULL ) {
+               if ( si->swap_saved_attrs ) {
                        rs->sr_attrs = si->save_attrs;
                        op->ors_attrs = si->save_attrs;
                }
-               if ( op->o_abandon || rs->sr_err == SLAPD_ABANDON ) {
+               if ( (op->o_abandon || rs->sr_err == SLAPD_ABANDON) && 
+                               si->caching_reason == PC_IGNORE ) {
                        filter_free( si->query.filter );
                        if ( si->count ) {
                                /* duplicate query, free it */
@@ -2009,6 +2026,13 @@ pcache_op_cleanup( Operation *op, SlapReply *rs ) {
                                case PC_SIZELIMIT:
                                        qc->q_sizelimit = rs->sr_nentries;
                                        break;
+
+                               case PC_NEGATIVE:
+                                       break;
+
+                               default:
+                                       assert( 0 );
+                                       break;
                                }
                                ldap_pvt_thread_rdwr_wunlock(&qc->rwlock);
                                ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
@@ -2054,7 +2078,7 @@ pcache_response(
 {
        struct search_info *si = op->o_callback->sc_private;
 
-       if ( si->save_attrs != NULL ) {
+       if ( si->swap_saved_attrs ) {
                rs->sr_attrs = si->save_attrs;
                op->ors_attrs = si->save_attrs;
        }
@@ -2151,7 +2175,7 @@ add_filter_attrs(
        }
        BER_BVZERO( &(*new_attrs)[j].an_name );
 
-       return count;
+       return j;
 }
 
 /* NOTE: this is a quick workaround to let pcache minimally interact
@@ -2403,6 +2427,7 @@ pcache_op_search(
                }
                si->head = NULL;
                si->tail = NULL;
+               si->swap_saved_attrs = 1;
                si->save_attrs = op->ors_attrs;
 
                op->ors_attrs = qtemp->t_attrs.attrs;
@@ -2621,6 +2646,11 @@ static ConfigTable pccfg[] = {
                "( OLcfgOvAt:2.6 NAME 'olcProxySaveQueries' "
                        "DESC 'Save cached queries for hot restart' "
                        "SYNTAX OMsBoolean )", NULL, NULL },
+       { "proxyCheckCacheability", "TRUE|FALSE",
+               2, 2, 0, ARG_ON_OFF|ARG_OFFSET, (void *)offsetof(cache_manager, check_cacheability),
+               "( OLcfgOvAt:2.7 NAME 'olcProxyCheckCacheability' "
+                       "DESC 'Check whether the results of a query are cacheable, e.g. for schema issues' "
+                       "SYNTAX OMsBoolean )", NULL, NULL },
 
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
@@ -2640,7 +2670,7 @@ static ConfigOCs pcocs[] = {
                "DESC 'ProxyCache configuration' "
                "SUP olcOverlayConfig "
                "MUST ( olcProxyCache $ olcProxyAttrset $ olcProxyTemplate ) "
-               "MAY ( olcProxyResponseCB $ olcProxyCacheQueries $ olcProxySaveQueries ) )",
+               "MAY ( olcProxyResponseCB $ olcProxyCacheQueries $ olcProxySaveQueries $ olcProxyCheckCacheability ) )",
                Cft_Overlay, pccfg, NULL, pc_cfadd },
        { "( OLcfgOvOc:2.2 "
                "NAME 'olcPcacheDatabase' "
@@ -2654,7 +2684,7 @@ static int pcache_db_open2( slap_overinst *on, ConfigReply *cr );
 static int
 pc_ldadd_cleanup( ConfigArgs *c )
 {
-       slap_overinst *on = c->private;
+       slap_overinst *on = c->ca_private;
        return pcache_db_open2( on, &c->reply );
 }
 
@@ -2676,7 +2706,7 @@ pc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
                ca->cleanup = pc_ldadd_cleanup;
        else
                cm->defer_db_open = 0;
-       ca->private = on;
+       ca->ca_private = on;
        return LDAP_SUCCESS;
 }
 
@@ -3133,6 +3163,7 @@ pcache_db_init(
        cm->cur_entries = 0;
        cm->max_queries = 10000;
        cm->save_queries = 0;
+       cm->check_cacheability = 0;
        cm->response_cb = PCACHE_RESPONSE_CB_TAIL;
        cm->defer_db_open = 1;
        cm->cc_period = 1000;
@@ -3200,7 +3231,7 @@ pcache_db_open2(
        query_manager*  qm = cm->qm;
        int rc;
 
-       rc = backend_startup_one( &cm->db, NULL );
+       rc = backend_startup_one( &cm->db, cr );
        if ( rc == 0 ) {
                cm->defer_db_open = 0;
        }