/* $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.
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 */
Query query;
QueryTemplate *qtemp;
AttributeName* save_attrs; /* original attributes, saved for response */
+ int swap_saved_attrs;
int max;
int over;
int count;
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 );
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,
* 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 );
si->tail = e;
} else {
+over:;
si->over = 1;
si->count = 0;
for (;si->head; si->head=e) {
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 */
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);
{
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;
}
}
BER_BVZERO( &(*new_attrs)[j].an_name );
- return count;
+ return j;
}
/* NOTE: this is a quick workaround to let pcache minimally interact
}
si->head = NULL;
si->tail = NULL;
+ si->swap_saved_attrs = 1;
si->save_attrs = op->ors_attrs;
op->ors_attrs = qtemp->t_attrs.attrs;
"( 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 }
};
"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' "
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 );
}
on = (slap_overinst *)p->ce_bi;
cm = on->on_bi.bi_private;
ca->be = &cm->db;
- ca->cleanup = pc_ldadd_cleanup;
- ca->private = on;
+ /* Defer open if this is an LDAPadd */
+ if ( CONFIG_ONLINE_ADD( ca ))
+ ca->cleanup = pc_ldadd_cleanup;
+ else
+ cm->defer_db_open = 0;
+ ca->ca_private = on;
return LDAP_SUCCESS;
}
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;
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;
}