version 1.41, 2004/12/03 15:49:23
|
version 1.41.2.12, 2006/01/03 22:16:24
|
Line 1
|
Line 1
|
/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/pcache.c,v 1.40 2004/11/26 23:57:38 hyc Exp $ */ |
/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/pcache.c,v 1.41.2.11 2005/11/26 23:54:51 kurt Exp $ */ |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
* |
* |
* Copyright 2003-2004 The OpenLDAP Foundation. |
* Copyright 2003-2006 The OpenLDAP Foundation. |
* Portions Copyright 2003 IBM Corporation. |
* Portions Copyright 2003 IBM Corporation. |
* Portions Copyright 2003 Symas Corporation. |
* Portions Copyright 2003 Symas Corporation. |
* All rights reserved. |
* All rights reserved. |
Line 32
|
Line 32
|
#include "lutil.h" |
#include "lutil.h" |
#include "ldap_rq.h" |
#include "ldap_rq.h" |
|
|
|
#include "config.h" |
|
|
/* query cache structs */ |
/* query cache structs */ |
/* query */ |
/* query */ |
|
|
Line 66 typedef struct query_template_s {
|
Line 68 typedef struct query_template_s {
|
CachedQuery* query_last; /* oldest query cached for the template */ |
CachedQuery* query_last; /* oldest query cached for the template */ |
|
|
int no_of_queries; /* Total number of queries in the template */ |
int no_of_queries; /* Total number of queries in the template */ |
long ttl; /* TTL for the queries of this template */ |
time_t ttl; /* TTL for the queries of this template */ |
ldap_pvt_thread_rdwr_t t_rwlock; /* Rd/wr lock for accessing queries in the template */ |
ldap_pvt_thread_rdwr_t t_rwlock; /* Rd/wr lock for accessing queries in the template */ |
} QueryTemplate; |
} QueryTemplate; |
|
|
Line 76 typedef struct query_template_s {
|
Line 78 typedef struct query_template_s {
|
*/ |
*/ |
|
|
struct attr_set { |
struct attr_set { |
|
unsigned flags; |
|
#define PC_CONFIGURED (0x1) |
|
#define PC_REFERENCED (0x2) |
AttributeName* attrs; /* specifies the set */ |
AttributeName* attrs; /* specifies the set */ |
int count; /* number of attributes */ |
int count; /* number of attributes */ |
int* ID_array; /* array of indices of supersets of 'attrs' */ |
int* ID_array; /* array of indices of supersets of 'attrs' */ |
Line 122 typedef struct cache_manager_s {
|
Line 127 typedef struct cache_manager_s {
|
#define PCACHE_RESPONSE_CB_HEAD 0 |
#define PCACHE_RESPONSE_CB_HEAD 0 |
#define PCACHE_RESPONSE_CB_TAIL 1 |
#define PCACHE_RESPONSE_CB_TAIL 1 |
|
|
int cc_period; /* interval between successive consistency checks (sec) */ |
time_t cc_period; /* interval between successive consistency checks (sec) */ |
int cc_paused; |
int cc_paused; |
void *cc_arg; |
void *cc_arg; |
|
|
Line 184 merge_entry(
|
Line 189 merge_entry(
|
op->o_tag = LDAP_REQ_MODIFY; |
op->o_tag = LDAP_REQ_MODIFY; |
op->orm_modlist = modlist; |
op->orm_modlist = modlist; |
op->o_bd->be_modify( op, &sreply ); |
op->o_bd->be_modify( op, &sreply ); |
slap_mods_free( modlist ); |
slap_mods_free( modlist, 1 ); |
} else if ( rc == LDAP_REFERRAL || |
} else if ( rc == LDAP_REFERRAL || |
rc == LDAP_NO_SUCH_OBJECT ) { |
rc == LDAP_NO_SUCH_OBJECT ) { |
syncrepl_add_glue( op, e ); |
syncrepl_add_glue( op, e ); |
Line 634 free_query (CachedQuery* qc)
|
Line 639 free_query (CachedQuery* qc)
|
free(qc->q_uuid.bv_val); |
free(qc->q_uuid.bv_val); |
filter_free(q->filter); |
filter_free(q->filter); |
free (q->base.bv_val); |
free (q->base.bv_val); |
for (i=0; q->attrs[i].an_name.bv_val; i++) { |
if ( q->attrs ) { |
free(q->attrs[i].an_name.bv_val); |
for (i=0; q->attrs[i].an_name.bv_val; i++) { |
|
free(q->attrs[i].an_name.bv_val); |
|
} |
|
free(q->attrs); |
} |
} |
free(q->attrs); |
|
free(qc); |
free(qc); |
} |
} |
|
|
Line 726 static void cache_replacement(query_mana
|
Line 733 static void cache_replacement(query_mana
|
Debug ( LDAP_DEBUG_ANY, |
Debug ( LDAP_DEBUG_ANY, |
"Cache replacement invoked without " |
"Cache replacement invoked without " |
"any query in LRU list\n", 0, 0, 0 ); |
"any query in LRU list\n", 0, 0, 0 ); |
|
ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); |
return; |
return; |
} |
} |
|
|
Line 789 remove_query_data (
|
Line 797 remove_query_data (
|
{ |
{ |
struct query_info *qi, *qnext; |
struct query_info *qi, *qnext; |
char filter_str[64]; |
char filter_str[64]; |
AttributeAssertion ava; |
#ifdef LDAP_COMP_MATCH |
|
AttributeAssertion ava = { NULL, BER_BVNULL, NULL }; |
|
#else |
|
AttributeAssertion ava = { NULL, BER_BVNULL }; |
|
#endif |
Filter filter = {LDAP_FILTER_EQUALITY}; |
Filter filter = {LDAP_FILTER_EQUALITY}; |
SlapReply sreply = {REP_RESULT}; |
SlapReply sreply = {REP_RESULT}; |
slap_callback cb = { NULL, remove_func, NULL, NULL }; |
slap_callback cb = { NULL, remove_func, NULL, NULL }; |
Line 846 remove_query_data (
|
Line 858 remove_query_data (
|
vals[1].bv_val = NULL; |
vals[1].bv_val = NULL; |
vals[1].bv_len = 0; |
vals[1].bv_len = 0; |
mod.sml_op = LDAP_MOD_DELETE; |
mod.sml_op = LDAP_MOD_DELETE; |
|
mod.sml_flags = 0; |
mod.sml_desc = ad_queryid; |
mod.sml_desc = ad_queryid; |
mod.sml_type = ad_queryid->ad_cname; |
mod.sml_type = ad_queryid->ad_cname; |
mod.sml_values = vals; |
mod.sml_values = vals; |
Line 978 filter2template(
|
Line 991 filter2template(
|
|
|
(*filter_attrs)[*filter_cnt].an_desc = ad; |
(*filter_attrs)[*filter_cnt].an_desc = ad; |
(*filter_attrs)[*filter_cnt].an_name = ad->ad_cname; |
(*filter_attrs)[*filter_cnt].an_name = ad->ad_cname; |
(*filter_attrs)[*filter_cnt+1].an_name.bv_val = NULL; |
(*filter_attrs)[*filter_cnt].an_oc = NULL; |
(*filter_attrs)[*filter_cnt+1].an_name.bv_len = 0; |
(*filter_attrs)[*filter_cnt].an_oc_exclude = 0; |
|
BER_BVZERO( &(*filter_attrs)[*filter_cnt+1].an_name ); |
(*filter_cnt)++; |
(*filter_cnt)++; |
return 0; |
return 0; |
} |
} |
Line 1004 cache_entries(
|
Line 1018 cache_entries(
|
slap_overinst *on = si->on; |
slap_overinst *on = si->on; |
cache_manager *cm = on->on_bi.bi_private; |
cache_manager *cm = on->on_bi.bi_private; |
query_manager* qm = cm->qm; |
query_manager* qm = cm->qm; |
int i; |
|
int return_val = 0; |
int return_val = 0; |
Entry *e; |
Entry *e; |
struct berval crp_uuid; |
struct berval crp_uuid; |
Line 1073 cache_entries(
|
Line 1086 cache_entries(
|
} |
} |
|
|
static int |
static int |
proxy_cache_response( |
pcache_response( |
Operation *op, |
Operation *op, |
SlapReply *rs ) |
SlapReply *rs ) |
{ |
{ |
Line 1108 proxy_cache_response(
|
Line 1121 proxy_cache_response(
|
} |
} |
} |
} |
|
|
if (rs->sr_attrs != op->ors_attrs ) { |
if ( rs->sr_attrs != op->ors_attrs ) { |
op->o_tmpfree( rs->sr_attrs, op->o_tmpmemctx ); |
op->o_tmpfree( rs->sr_attrs, op->o_tmpmemctx ); |
} |
} |
rs->sr_attrs = si->query.save_attrs; |
|
op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); |
if ( si->query.save_attrs != NULL ) { |
op->ors_attrs = si->query.save_attrs; |
rs->sr_attrs = si->query.save_attrs; |
si->query.save_attrs = NULL; |
op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); |
|
op->ors_attrs = si->query.save_attrs; |
|
si->query.save_attrs = NULL; |
|
} |
|
|
} else if ( rs->sr_type == REP_RESULT ) { |
} else if ( rs->sr_type == REP_RESULT ) { |
if ( si->count && cache_entries( op, rs, &uuid ) == 0 ) { |
if ( si->count && cache_entries( op, rs, &uuid ) == 0 ) { |
Line 1160 add_filter_attrs(
|
Line 1176 add_filter_attrs(
|
*new_attrs = (AttributeName*)(op->o_tmpalloc((count+1)* |
*new_attrs = (AttributeName*)(op->o_tmpalloc((count+1)* |
sizeof(AttributeName), op->o_tmpmemctx)); |
sizeof(AttributeName), op->o_tmpmemctx)); |
if (attrs == NULL) { |
if (attrs == NULL) { |
(*new_attrs)[0].an_name.bv_val = "*"; |
BER_BVSTR( &(*new_attrs)[0].an_name, "*" ); |
(*new_attrs)[0].an_name.bv_len = 1; |
(*new_attrs)[0].an_desc = NULL; |
(*new_attrs)[1].an_name.bv_val = NULL; |
(*new_attrs)[0].an_oc = NULL; |
(*new_attrs)[1].an_name.bv_len = 0; |
(*new_attrs)[0].an_oc_exclude = 0; |
|
BER_BVZERO( &(*new_attrs)[1].an_name ); |
alluser = 1; |
alluser = 1; |
allop = 0; |
allop = 0; |
} else { |
} else { |
Line 1171 add_filter_attrs(
|
Line 1188 add_filter_attrs(
|
(*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; |
(*new_attrs)[i].an_desc = attrs[i].an_desc; |
} |
} |
(*new_attrs)[count].an_name.bv_val = NULL; |
BER_BVZERO( &(*new_attrs)[count].an_name ); |
(*new_attrs)[count].an_name.bv_len = 0; |
|
alluser = an_find(*new_attrs, &AllUser); |
alluser = an_find(*new_attrs, &AllUser); |
allop = an_find(*new_attrs, &AllOper); |
allop = an_find(*new_attrs, &AllOper); |
} |
} |
Line 1189 add_filter_attrs(
|
Line 1205 add_filter_attrs(
|
(count+2)*sizeof(AttributeName), op->o_tmpmemctx)); |
(count+2)*sizeof(AttributeName), op->o_tmpmemctx)); |
(*new_attrs)[count].an_name = filter_attrs[i].an_name; |
(*new_attrs)[count].an_name = filter_attrs[i].an_name; |
(*new_attrs)[count].an_desc = filter_attrs[i].an_desc; |
(*new_attrs)[count].an_desc = filter_attrs[i].an_desc; |
|
(*new_attrs)[count].an_oc = NULL; |
|
(*new_attrs)[count].an_oc_exclude = 0; |
count++; |
count++; |
(*new_attrs)[count].an_name.bv_val = NULL; |
BER_BVZERO( &(*new_attrs)[count].an_name ); |
(*new_attrs)[count].an_name.bv_len = 0; |
} |
|
} |
|
|
|
/* NOTE: this is a quick workaround to let pcache minimally interact |
|
* with pagedResults. A more articulated solutions would be to |
|
* perform the remote query without control and cache all results, |
|
* performing the pagedResults search only within the client |
|
* and the proxy. This requires pcache to understand pagedResults. */ |
|
static int |
|
pcache_chk_controls( |
|
Operation *op, |
|
SlapReply *rs ) |
|
{ |
|
const char *non = ""; |
|
const char *stripped = ""; |
|
|
|
switch( op->o_pagedresults ) { |
|
case SLAP_CONTROL_NONCRITICAL: |
|
non = "non-"; |
|
stripped = "; stripped"; |
|
/* fallthru */ |
|
|
|
case SLAP_CONTROL_CRITICAL: |
|
Debug( LDAP_DEBUG_ANY, "%s: " |
|
"%scritical pagedResults control " |
|
"disabled with proxy cache%s.\n", |
|
op->o_log_prefix, non, stripped ); |
|
|
|
slap_remove_control( op, rs, slap_cids.sc_pagedResults, NULL ); |
|
break; |
|
|
|
default: |
|
rs->sr_err = SLAP_CB_CONTINUE; |
|
break; |
} |
} |
|
|
|
return rs->sr_err; |
} |
} |
|
|
static int |
static int |
proxy_cache_search( |
pcache_op_search( |
Operation *op, |
Operation *op, |
SlapReply *rs ) |
SlapReply *rs ) |
{ |
{ |
Line 1209 proxy_cache_search(
|
Line 1262 proxy_cache_search(
|
int i = -1; |
int i = -1; |
|
|
AttributeName *filter_attrs = NULL; |
AttributeName *filter_attrs = NULL; |
AttributeName *new_attrs = NULL; |
|
|
|
Query query; |
Query query; |
|
|
Line 1232 proxy_cache_search(
|
Line 1284 proxy_cache_search(
|
Debug( LDAP_DEBUG_ANY, "query template of incoming query = %s\n", |
Debug( LDAP_DEBUG_ANY, "query template of incoming query = %s\n", |
tempstr.bv_val, 0, 0 ); |
tempstr.bv_val, 0, 0 ); |
|
|
|
/* FIXME: cannot cache/answer requests with pagedResults control */ |
|
|
|
|
/* find attr set */ |
/* find attr set */ |
attr_set = get_attr_set(op->ors_attrs, qm, cm->numattrsets); |
attr_set = get_attr_set(op->ors_attrs, qm, cm->numattrsets); |
|
|
Line 1306 proxy_cache_search(
|
Line 1361 proxy_cache_search(
|
for ( count = 0; !BER_BVISNULL( &op->ors_attrs[ count ].an_name ); count++ ) { |
for ( count = 0; !BER_BVISNULL( &op->ors_attrs[ count ].an_name ); count++ ) { |
ber_dupbv( &query.attrs[count].an_name, &op->ors_attrs[count].an_name ); |
ber_dupbv( &query.attrs[count].an_name, &op->ors_attrs[count].an_name ); |
query.attrs[count].an_desc = op->ors_attrs[count].an_desc; |
query.attrs[count].an_desc = op->ors_attrs[count].an_desc; |
|
query.attrs[count].an_oc = op->ors_attrs[count].an_oc; |
|
query.attrs[count].an_oc_exclude = op->ors_attrs[count].an_oc_exclude; |
} |
} |
if ( oc_attr_absent ) { |
if ( oc_attr_absent ) { |
query.attrs[ count ].an_desc = slap_schema.si_ad_objectClass; |
query.attrs[ count ].an_desc = slap_schema.si_ad_objectClass; |
ber_dupbv( &query.attrs[count].an_name, |
ber_dupbv( &query.attrs[count].an_name, |
&slap_schema.si_ad_objectClass->ad_cname ); |
&slap_schema.si_ad_objectClass->ad_cname ); |
|
query.attrs[ count ].an_oc = NULL; |
|
query.attrs[ count ].an_oc_exclude = 0; |
count++; |
count++; |
} |
} |
query.attrs[ count ].an_name.bv_val = NULL; |
BER_BVZERO( &query.attrs[ count ].an_name ); |
query.attrs[ count ].an_name.bv_len = 0; |
|
} |
} |
add_filter_attrs(op, &op->ors_attrs, query.attrs, filter_attrs); |
add_filter_attrs(op, &op->ors_attrs, query.attrs, filter_attrs); |
|
|
cb = op->o_tmpalloc( sizeof(*cb) + sizeof(*si), op->o_tmpmemctx); |
cb = op->o_tmpalloc( sizeof(*cb) + sizeof(*si), op->o_tmpmemctx); |
cb->sc_response = proxy_cache_response; |
cb->sc_response = pcache_response; |
cb->sc_cleanup = NULL; |
cb->sc_cleanup = NULL; |
cb->sc_private = (cb+1); |
cb->sc_private = (cb+1); |
si = cb->sc_private; |
si = cb->sc_private; |
Line 1411 consistency_check(
|
Line 1469 consistency_check(
|
cache_manager *cm = on->on_bi.bi_private; |
cache_manager *cm = on->on_bi.bi_private; |
query_manager *qm = cm->qm; |
query_manager *qm = cm->qm; |
Connection conn = {0}; |
Connection conn = {0}; |
char opbuf[OPERATION_BUFFER_SIZE]; |
OperationBuffer opbuf; |
Operation *op; |
Operation *op; |
|
|
SlapReply rs = {REP_RESULT}; |
SlapReply rs = {REP_RESULT}; |
Line 1419 consistency_check(
|
Line 1477 consistency_check(
|
int i, return_val, pause = 1; |
int i, return_val, pause = 1; |
QueryTemplate* templ; |
QueryTemplate* templ; |
|
|
op = (Operation *)opbuf; |
op = (Operation *) &opbuf; |
connection_fake_init( &conn, op, ctx ); |
connection_fake_init( &conn, op, ctx ); |
|
|
op->o_bd = &cm->db; |
op->o_bd = &cm->db; |
Line 1480 consistency_check(
|
Line 1538 consistency_check(
|
|
|
|
|
#define MAX_ATTR_SETS 500 |
#define MAX_ATTR_SETS 500 |
static void find_supersets( struct attr_set* attr_sets, int numsets ); |
|
static int compare_sets( struct attr_set* setA, int, int ); |
/* |
|
* compares two sets of attributes (indices i and j) |
|
* returns 0: if neither set is contained in the other set |
|
* 1: if set i is contained in set j |
|
* 2: if set j is contained in set i |
|
* 3: the sets are equivalent |
|
*/ |
|
|
static int |
static int |
proxy_cache_config( |
compare_sets(struct attr_set* set, int i, int j) |
BackendDB *be, |
|
const char *fname, |
|
int lineno, |
|
int argc, |
|
char **argv |
|
) |
|
{ |
{ |
slap_overinst *on = (slap_overinst *)be->bd_info; |
int k,l,numI,numJ; |
|
int common=0; |
|
int result=0; |
|
|
|
if (( set[i].attrs == NULL ) && ( set[j].attrs == NULL )) |
|
return 3; |
|
|
|
if ( set[i].attrs == NULL ) |
|
return 2; |
|
|
|
if ( set[j].attrs == NULL ) |
|
return 1; |
|
|
|
numI = set[i].count; |
|
numJ = set[j].count; |
|
|
|
for ( l=0; l < numI; l++ ) { |
|
for ( k = 0; k < numJ; k++ ) { |
|
if ( strcmp( set[i].attrs[l].an_name.bv_val, |
|
set[j].attrs[k].an_name.bv_val ) == 0 ) |
|
common++; |
|
} |
|
} |
|
|
|
if ( common == numI ) |
|
result = 1; |
|
|
|
if ( common == numJ ) |
|
result += 2; |
|
|
|
return result; |
|
} |
|
|
|
static void |
|
find_supersets ( struct attr_set* attr_sets, int numsets ) |
|
{ |
|
int num[MAX_ATTR_SETS]; |
|
int i, j, res; |
|
int* id_array; |
|
for ( i = 0; i < MAX_ATTR_SETS; i++ ) |
|
num[i] = 0; |
|
|
|
for ( i = 0; i < numsets; i++ ) { |
|
attr_sets[i].ID_array = (int*) ch_malloc( sizeof( int ) ); |
|
attr_sets[i].ID_array[0] = -1; |
|
} |
|
|
|
for ( i = 0; i < numsets; i++ ) { |
|
for ( j=i+1; j < numsets; j++ ) { |
|
res = compare_sets( attr_sets, i, j ); |
|
switch ( res ) { |
|
case 0: |
|
break; |
|
case 3: |
|
case 1: |
|
id_array = attr_sets[i].ID_array; |
|
attr_sets[i].ID_array = (int *) ch_realloc( id_array, |
|
( num[i] + 2 ) * sizeof( int )); |
|
attr_sets[i].ID_array[num[i]] = j; |
|
attr_sets[i].ID_array[num[i]+1] = -1; |
|
num[i]++; |
|
if (res == 1) |
|
break; |
|
case 2: |
|
id_array = attr_sets[j].ID_array; |
|
attr_sets[j].ID_array = (int *) ch_realloc( id_array, |
|
( num[j] + 2 ) * sizeof( int )); |
|
attr_sets[j].ID_array[num[j]] = i; |
|
attr_sets[j].ID_array[num[j]+1] = -1; |
|
num[j]++; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
enum { |
|
PC_MAIN = 1, |
|
PC_ATTR, |
|
PC_TEMP, |
|
PC_RESP |
|
}; |
|
|
|
static ConfigDriver pc_cf_gen; |
|
static ConfigLDAPadd pc_ldadd; |
|
static ConfigCfAdd pc_cfadd; |
|
|
|
static ConfigTable pccfg[] = { |
|
{ "proxycache", "backend> <max_entries> <numattrsets> <entry limit> " |
|
"<cycle_time", |
|
6, 6, 0, ARG_MAGIC|ARG_NO_DELETE|PC_MAIN, pc_cf_gen, |
|
"( OLcfgOvAt:2.1 NAME 'olcProxyCache' " |
|
"DESC 'ProxyCache basic parameters' " |
|
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, |
|
{ "proxyattrset", "index> <attributes...", |
|
2, 0, 0, ARG_MAGIC|PC_ATTR, pc_cf_gen, |
|
"( OLcfgOvAt:2.2 NAME 'olcProxyAttrset' " |
|
"DESC 'A set of attributes to cache' " |
|
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
|
{ "proxytemplate", "filter> <attrset-index> <TTL", |
|
4, 4, 0, ARG_MAGIC|PC_TEMP, pc_cf_gen, |
|
"( OLcfgOvAt:2.3 NAME 'olcProxyTemplate' " |
|
"DESC 'Filter template, attrset, and cache TTL' " |
|
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
|
{ "response-callback", "head|tail(default)", |
|
2, 2, 0, ARG_MAGIC|PC_RESP, pc_cf_gen, |
|
"( OLcfgOvAt:2.4 NAME 'olcProxyResponseCB' " |
|
"DESC 'Response callback position in overlay stack' " |
|
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
|
{ NULL, NULL, 0, 0, 0, ARG_IGNORED } |
|
}; |
|
|
|
static ConfigOCs pcocs[] = { |
|
{ "( OLcfgOvOc:2.1 " |
|
"NAME 'olcPcacheConfig' " |
|
"DESC 'ProxyCache configuration' " |
|
"SUP olcOverlayConfig " |
|
"MUST ( olcProxyCache $ olcProxyAttrset $ olcProxyTemplate ) " |
|
"MAY olcProxyResponseCB )", Cft_Overlay, pccfg, NULL, pc_cfadd }, |
|
{ "( OLcfgOvOc:2.2 " |
|
"NAME 'olcPcacheDatabase' " |
|
"DESC 'Cache database configuration' " |
|
"AUXILIARY )", Cft_Misc, pccfg, pc_ldadd }, |
|
{ NULL, 0, NULL } |
|
}; |
|
|
|
static int |
|
pc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) |
|
{ |
|
slap_overinst *on; |
|
cache_manager *cm; |
|
|
|
if ( p->ce_type != Cft_Overlay || !p->ce_bi || |
|
p->ce_bi->bi_cf_ocs != pcocs ) |
|
return LDAP_CONSTRAINT_VIOLATION; |
|
|
|
on = (slap_overinst *)p->ce_bi; |
|
cm = on->on_bi.bi_private; |
|
ca->be = &cm->db; |
|
return LDAP_SUCCESS; |
|
} |
|
|
|
static int |
|
pc_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ) |
|
{ |
|
CfEntryInfo *pe = p->e_private; |
|
slap_overinst *on = (slap_overinst *)pe->ce_bi; |
|
cache_manager *cm = on->on_bi.bi_private; |
|
struct berval bv; |
|
|
|
/* FIXME: should not hardcode "olcDatabase" here */ |
|
bv.bv_len = sprintf( ca->msg, "olcDatabase=%s", cm->db.bd_info->bi_type ); |
|
bv.bv_val = ca->msg; |
|
ca->be = &cm->db; |
|
|
|
/* We can only create this entry if the database is table-driven |
|
*/ |
|
if ( cm->db.bd_info->bi_cf_ocs ) |
|
config_build_entry( op, rs, pe, ca, &bv, cm->db.bd_info->bi_cf_ocs, |
|
&pcocs[1] ); |
|
|
|
return 0; |
|
} |
|
|
|
static int |
|
pc_cf_gen( ConfigArgs *c ) |
|
{ |
|
slap_overinst *on = (slap_overinst *)c->bi; |
cache_manager* cm = on->on_bi.bi_private; |
cache_manager* cm = on->on_bi.bi_private; |
query_manager* qm = cm->qm; |
query_manager* qm = cm->qm; |
QueryTemplate* temp; |
QueryTemplate* temp; |
AttributeName* attr_name; |
AttributeName* attr_name; |
AttributeName* attrarray; |
AttributeName* attrarray; |
const char* text=NULL; |
const char* text=NULL; |
char *save_argv0 = NULL; |
int i, num, rc = 0; |
|
char *ptr; |
|
unsigned long t; |
|
|
|
if ( c->op == SLAP_CONFIG_EMIT ) { |
|
struct berval bv; |
|
switch( c->type ) { |
|
case PC_MAIN: |
|
bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%s %d %d %d %ld", |
|
cm->db.bd_info->bi_type, cm->max_entries, cm->numattrsets, |
|
cm->num_entries_limit, cm->cc_period ); |
|
bv.bv_val = c->msg; |
|
value_add_one( &c->rvalue_vals, &bv ); |
|
break; |
|
case PC_ATTR: |
|
for (i=0; i<cm->numattrsets; i++) { |
|
if ( !qm->attr_sets[i].count ) continue; |
|
|
|
bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%d", i ); |
|
|
|
/* count the attr length */ |
|
for ( attr_name = qm->attr_sets[i].attrs; |
|
attr_name->an_name.bv_val; attr_name++ ) |
|
bv.bv_len += attr_name->an_name.bv_len + 1; |
|
|
|
bv.bv_val = ch_malloc( bv.bv_len+1 ); |
|
ptr = lutil_strcopy( bv.bv_val, c->msg ); |
|
for ( attr_name = qm->attr_sets[i].attrs; |
|
attr_name->an_name.bv_val; attr_name++ ) { |
|
*ptr++ = ' '; |
|
ptr = lutil_strcopy( ptr, attr_name->an_name.bv_val ); |
|
} |
|
ber_bvarray_add( &c->rvalue_vals, &bv ); |
|
} |
|
if ( !c->rvalue_vals ) |
|
rc = 1; |
|
break; |
|
case PC_TEMP: |
|
for (i=0; i<cm->numtemplates; i++) { |
|
bv.bv_len = snprintf( c->msg, sizeof( c->msg ), " %d %ld", |
|
qm->templates[i].attr_set_index, |
|
qm->templates[i].ttl ); |
|
bv.bv_len += qm->templates[i].querystr.bv_len + 2; |
|
bv.bv_val = ch_malloc( bv.bv_len+1 ); |
|
ptr = bv.bv_val; |
|
*ptr++ = '"'; |
|
ptr = lutil_strcopy( ptr, qm->templates[i].querystr.bv_val ); |
|
*ptr++ = '"'; |
|
strcpy( ptr, c->msg ); |
|
ber_bvarray_add( &c->rvalue_vals, &bv ); |
|
} |
|
if ( !c->rvalue_vals ) |
|
rc = 1; |
|
break; |
|
case PC_RESP: |
|
if ( cm->response_cb == PCACHE_RESPONSE_CB_HEAD ) { |
|
BER_BVSTR( &bv, "head" ); |
|
} else { |
|
BER_BVSTR( &bv, "tail" ); |
|
} |
|
value_add_one( &c->rvalue_vals, &bv ); |
|
break; |
|
} |
|
return rc; |
|
} else if ( c->op == LDAP_MOD_DELETE ) { |
|
return 1; /* FIXME */ |
|
#if 0 |
|
switch( c->type ) { |
|
case PC_ATTR: |
|
case PC_TEMP: |
|
} |
|
return rc; |
|
#endif |
|
} |
|
|
int index, i; |
switch( c->type ) { |
int num; |
case PC_MAIN: |
int rc = 0; |
if ( cm->numattrsets > 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive already provided" ); |
if ( strncasecmp( argv[0], "proxycache-", STRLENOF( "proxycache-" ) ) == 0 ) { |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
save_argv0 = argv[0]; |
|
argv[0] += STRLENOF( "proxycache-" ); |
|
} |
|
|
|
if ( strcasecmp( argv[0], "proxycache" ) == 0 ) { |
|
if ( argc < 6 ) { |
|
fprintf( stderr, "%s: line %d: missing arguments in \"proxycache" |
|
" <backend> <max_entries> <numattrsets> <entry limit> " |
|
"<cycle_time>\"\n", fname, lineno ); |
|
return( 1 ); |
return( 1 ); |
} |
} |
|
|
cm->db.bd_info = backend_info( argv[1] ); |
if ( lutil_atoi( &cm->numattrsets, c->argv[3] ) != 0 ) { |
if ( !cm->db.bd_info ) { |
snprintf( c->msg, sizeof( c->msg ), "unable to parse num attrsets=\"%s\" (arg #3)", |
fprintf( stderr, "%s: line %d: backend %s unknown\n", |
c->argv[3] ); |
fname, lineno, argv[1] ); |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
if ( cm->numattrsets <= 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "numattrsets (arg #3) must be positive" ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
if ( cm->numattrsets > MAX_ATTR_SETS ) { |
|
snprintf( c->msg, sizeof( c->msg ), "numattrsets (arg #3) must be <= %d", MAX_ATTR_SETS ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
return( 1 ); |
return( 1 ); |
} |
} |
if ( cm->db.bd_info->bi_db_init( &cm->db ) ) return( 1 ); |
|
|
|
/* This type is in use, needs to be opened */ |
if ( !backend_db_init( c->argv[1], &cm->db )) { |
cm->db.bd_info->bi_nDB++; |
snprintf( c->msg, sizeof( c->msg ), "unknown backend type (arg #1)" ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
|
cm->max_entries = atoi( argv[2] ); |
if ( lutil_atoi( &cm->max_entries, c->argv[2] ) != 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "unable to parse max entries=\"%s\" (arg #2)", |
|
c->argv[2] ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
if ( cm->max_entries <= 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "max entries (arg #2) must be positive.\n" ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
|
cm->numattrsets = atoi( argv[3] ); |
if ( lutil_atoi( &cm->num_entries_limit, c->argv[4] ) != 0 ) { |
if ( cm->numattrsets > MAX_ATTR_SETS ) { |
snprintf( c->msg, sizeof( c->msg ), "unable to parse entry limit=\"%s\" (arg #4)", |
fprintf( stderr, "%s: line %d: numattrsets must be <= %d\n", |
c->argv[4] ); |
fname, lineno, MAX_ATTR_SETS ); |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
if ( cm->num_entries_limit <= 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "entry limit (arg #4) must be positive" ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
if ( cm->num_entries_limit > cm->max_entries ) { |
|
snprintf( c->msg, sizeof( c->msg ), "entry limit (arg #4) must be less than max entries %d (arg #2)", cm->max_entries ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
return( 1 ); |
return( 1 ); |
} |
} |
|
|
cm->num_entries_limit = atoi( argv[4] ); |
if ( lutil_parse_time( c->argv[5], &t ) != 0 ) { |
cm->cc_period = atoi( argv[5] ); |
snprintf( c->msg, sizeof( c->msg ), "unable to parse period=\"%s\" (arg #5)", |
Debug( LDAP_DEBUG_ANY, |
c->argv[5] ); |
"Total # of attribute sets to be cached = %d\n", |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
cm->cc_period = (time_t)t; |
|
Debug( LDAP_DEBUG_TRACE, |
|
"Total # of attribute sets to be cached = %d.\n", |
cm->numattrsets, 0, 0 ); |
cm->numattrsets, 0, 0 ); |
qm->attr_sets = ( struct attr_set * )ch_malloc( cm->numattrsets * |
qm->attr_sets = ( struct attr_set * )ch_calloc( cm->numattrsets, |
sizeof( struct attr_set )); |
sizeof( struct attr_set ) ); |
for ( i = 0; i < cm->numattrsets; i++ ) { |
break; |
qm->attr_sets[i].attrs = NULL; |
case PC_ATTR: |
|
if ( cm->numattrsets == 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive not provided yet" ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
} |
} |
|
if ( lutil_atoi( &num, c->argv[1] ) != 0 ) { |
} else if ( strcasecmp( argv[0], "proxyattrset" ) == 0 ) { |
snprintf( c->msg, sizeof( c->msg ), "unable to parse attrset #=\"%s\"", |
if ( argc < 3 ) { |
c->argv[1] ); |
fprintf( stderr, "%s: line %d: missing arguments in \"proxyattrset " |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
"<index> <attributes>\"\n", fname, lineno ); |
|
return( 1 ); |
return( 1 ); |
} |
} |
Debug( LDAP_DEBUG_ANY, "Attribute Set # %d\n", |
|
atoi( argv[1] ), 0, 0 ); |
if ( num < 0 || num >= cm->numattrsets ) { |
if (atoi(argv[1]) >= cm->numattrsets) { |
snprintf( c->msg, sizeof( c->msg ), "attrset index %d out of bounds (must be %s%d)", |
fprintf( stderr, "%s; line %d index out of bounds \n", |
num, cm->numattrsets > 1 ? "0->" : "", cm->numattrsets - 1 ); |
fname, lineno ); |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
return 1; |
return 1; |
} |
} |
index = atoi( argv[1] ); |
qm->attr_sets[num].flags |= PC_CONFIGURED; |
if ( argv[2] && strcmp( argv[2], "*" ) ) { |
if ( c->argc > 2 && strcmp( c->argv[2], "*" ) ) { |
qm->attr_sets[index].count = argc - 2; |
qm->attr_sets[num].count = c->argc - 2; |
qm->attr_sets[index].attrs = (AttributeName*)ch_malloc( |
qm->attr_sets[num].attrs = (AttributeName*)ch_malloc( |
(argc-1) * sizeof( AttributeName )); |
(c->argc-1) * sizeof( AttributeName )); |
attr_name = qm->attr_sets[index].attrs; |
attr_name = qm->attr_sets[num].attrs; |
for ( i = 2; i < argc; i++ ) { |
for ( i = 2; i < c->argc; i++ ) { |
Debug( LDAP_DEBUG_ANY, "\t %s\n", |
ber_str2bv( c->argv[i], 0, 1, &attr_name->an_name); |
argv[i], 0, 0 ); |
|
ber_str2bv( argv[i], 0, 1, |
|
&attr_name->an_name); |
|
attr_name->an_desc = NULL; |
attr_name->an_desc = NULL; |
slap_bv2ad( &attr_name->an_name, |
if ( slap_bv2ad( &attr_name->an_name, |
&attr_name->an_desc, &text ); |
&attr_name->an_desc, &text ) ) |
|
{ |
|
strcpy( c->msg, text ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
ch_free( qm->attr_sets[num].attrs ); |
|
qm->attr_sets[num].attrs = NULL; |
|
qm->attr_sets[num].count = 0; |
|
return 1; |
|
} |
|
attr_name->an_oc = NULL; |
|
attr_name->an_oc_exclude = 0; |
attr_name++; |
attr_name++; |
attr_name->an_name.bv_val = NULL; |
BER_BVZERO( &attr_name->an_name ); |
attr_name->an_name.bv_len = 0; |
|
} |
} |
} |
} |
} else if ( strcasecmp( argv[0], "proxytemplate" ) == 0 ) { |
break; |
if ( argc != 4 ) { |
case PC_TEMP: |
fprintf( stderr, "%s: line %d: missing argument(s) in " |
if ( cm->numattrsets == 0 ) { |
"\"proxytemplate <filter> <proj attr set> <TTL>\" line\n", |
snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive not provided yet" ); |
fname, lineno ); |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
return( 1 ); |
return( 1 ); |
} |
} |
if (( i = atoi( argv[2] )) >= cm->numattrsets ) { |
if ( lutil_atoi( &i, c->argv[2] ) != 0 ) { |
Debug( LDAP_DEBUG_ANY, |
snprintf( c->msg, sizeof( c->msg ), "unable to parse template #=\"%s\"", |
"%s: line %d, template index invalid\n", |
c->argv[2] ); |
fname, lineno, 0 ); |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
|
|
if ( i < 0 || i >= cm->numattrsets ) { |
|
snprintf( c->msg, sizeof( c->msg ), "template index %d invalid (%s%d)", |
|
i, cm->numattrsets > 1 ? "0->" : "", cm->numattrsets - 1 ); |
|
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
return 1; |
return 1; |
} |
} |
num = cm->numtemplates; |
num = cm->numtemplates; |
Line 1602 proxy_cache_config(
|
Line 1944 proxy_cache_config(
|
temp = qm->templates + num; |
temp = qm->templates + num; |
ldap_pvt_thread_rdwr_init( &temp->t_rwlock ); |
ldap_pvt_thread_rdwr_init( &temp->t_rwlock ); |
temp->query = temp->query_last = NULL; |
temp->query = temp->query_last = NULL; |
temp->ttl = atoi( argv[3] ); |
if ( lutil_parse_time( c->argv[3], &t ) != 0 ) { |
temp->no_of_queries = 0; |
snprintf( c->msg, sizeof( c->msg ), "unable to parse template ttl=\"%s\"", |
if ( argv[1] == NULL ) { |
c->argv[3] ); |
Debug( LDAP_DEBUG_ANY, |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
"Templates string not specified " |
return( 1 ); |
"for template %d\n", num, 0, 0 ); |
|
return 1; |
|
} |
} |
ber_str2bv( argv[1], 0, 1, &temp->querystr ); |
temp->ttl = (time_t)t; |
Debug( LDAP_DEBUG_ANY, "Template:\n", 0, 0, 0 ); |
|
Debug( LDAP_DEBUG_ANY, " query template: %s\n", |
temp->no_of_queries = 0; |
|
|
|
ber_str2bv( c->argv[1], 0, 1, &temp->querystr ); |
|
Debug( LDAP_DEBUG_TRACE, "Template:\n", 0, 0, 0 ); |
|
Debug( LDAP_DEBUG_TRACE, " query template: %s\n", |
temp->querystr.bv_val, 0, 0 ); |
temp->querystr.bv_val, 0, 0 ); |
temp->attr_set_index = i; |
temp->attr_set_index = i; |
Debug( LDAP_DEBUG_ANY, " attributes: \n", 0, 0, 0 ); |
qm->attr_sets[i].flags |= PC_REFERENCED; |
|
Debug( LDAP_DEBUG_TRACE, " attributes: \n", 0, 0, 0 ); |
if ( ( attrarray = qm->attr_sets[i].attrs ) != NULL ) { |
if ( ( attrarray = qm->attr_sets[i].attrs ) != NULL ) { |
for ( i=0; attrarray[i].an_name.bv_val; i++ ) |
for ( i=0; attrarray[i].an_name.bv_val; i++ ) |
Debug( LDAP_DEBUG_ANY, "\t%s\n", |
Debug( LDAP_DEBUG_TRACE, "\t%s\n", |
attrarray[i].an_name.bv_val, 0, 0 ); |
attrarray[i].an_name.bv_val, 0, 0 ); |
} |
} |
temp++; |
temp++; |
temp->querystr.bv_val = NULL; |
temp->querystr.bv_val = NULL; |
cm->numtemplates++; |
cm->numtemplates++; |
|
break; |
} else if ( strcasecmp( argv[0], "response-callback" ) == 0 ) { |
case PC_RESP: |
/* set to "tail" to put the response callback |
if ( strcasecmp( c->argv[1], "head" ) == 0 ) { |
* at the end of the callback list; this is required |
|
* in case other overlays are present, so that the |
|
* final entry is cached. */ |
|
|
|
if ( argc < 2 ) { |
|
Debug( LDAP_DEBUG_ANY, |
|
"missing specifier for \"response-callback {head(default)|tail}\" " |
|
"callback position\n", 0, 0, 0 ); |
|
return 1; |
|
} |
|
|
|
if ( strcasecmp( argv[1], "head" ) == 0 ) { |
|
cm->response_cb = PCACHE_RESPONSE_CB_HEAD; |
cm->response_cb = PCACHE_RESPONSE_CB_HEAD; |
|
|
} else if ( strcasecmp( argv[1], "tail" ) == 0 ) { |
} else if ( strcasecmp( c->argv[1], "tail" ) == 0 ) { |
cm->response_cb = PCACHE_RESPONSE_CB_TAIL; |
cm->response_cb = PCACHE_RESPONSE_CB_TAIL; |
|
|
} else { |
} else { |
Debug( LDAP_DEBUG_ANY, |
snprintf( c->msg, sizeof( c->msg ), "unknown specifier" ); |
"unknown specifier %s for \"response-callback {head(default)|tail}\" " |
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); |
"callback position\n", argv[1], 0, 0 ); |
|
return 1; |
return 1; |
} |
} |
|
break; |
} |
} |
/* anything else */ |
return rc; |
else { |
} |
rc = cm->db.bd_info->bi_db_config( &cm->db, fname, lineno, argc, argv ); |
|
} |
|
|
|
if ( save_argv0 ) { |
static int |
argv[0] = save_argv0; |
pcache_db_config( |
} |
BackendDB *be, |
|
const char *fname, |
|
int lineno, |
|
int argc, |
|
char **argv |
|
) |
|
{ |
|
slap_overinst *on = (slap_overinst *)be->bd_info; |
|
cache_manager* cm = on->on_bi.bi_private; |
|
|
return rc; |
/* Something for the cache database? */ |
|
if ( cm->db.bd_info && cm->db.bd_info->bi_db_config ) |
|
return cm->db.bd_info->bi_db_config( &cm->db, fname, lineno, |
|
argc, argv ); |
|
return SLAP_CONF_UNKNOWN; |
} |
} |
|
|
static int |
static int |
proxy_cache_init( |
pcache_db_init( |
BackendDB *be |
BackendDB *be |
) |
) |
{ |
{ |
Line 1709 proxy_cache_init(
|
Line 2052 proxy_cache_init(
|
} |
} |
|
|
static int |
static int |
proxy_cache_open( |
pcache_db_open( |
BackendDB *be |
BackendDB *be |
) |
) |
{ |
{ |
slap_overinst *on = (slap_overinst *)be->bd_info; |
slap_overinst *on = (slap_overinst *)be->bd_info; |
cache_manager *cm = on->on_bi.bi_private; |
cache_manager *cm = on->on_bi.bi_private; |
int rc = 0; |
query_manager* qm = cm->qm; |
int i; |
int i, ncf = 0, rf = 0, nrf = 0, rc = 0; |
|
|
|
/* check attr sets */ |
|
for ( i = 0; i < cm->numattrsets; i++) { |
|
if ( !( qm->attr_sets[i].flags & PC_CONFIGURED ) ) { |
|
if ( qm->attr_sets[i].flags & PC_REFERENCED ) { |
|
Debug( LDAP_DEBUG_ANY, "pcache: attr set #%d not configured but referenced.\n", i, 0, 0 ); |
|
rf++; |
|
|
|
} else { |
|
Debug( LDAP_DEBUG_ANY, "pcache: warning, attr set #%d not configured.\n", i, 0, 0 ); |
|
} |
|
ncf++; |
|
|
|
} else if ( !( qm->attr_sets[i].flags & PC_REFERENCED ) ) { |
|
Debug( LDAP_DEBUG_ANY, "pcache: attr set #%d configured but not referenced.\n", i, 0, 0 ); |
|
nrf++; |
|
} |
|
} |
|
|
|
if ( ncf || rf || nrf ) { |
|
Debug( LDAP_DEBUG_ANY, "pcache: warning, %d attr sets configured but not referenced.\n", nrf, 0, 0 ); |
|
Debug( LDAP_DEBUG_ANY, "pcache: warning, %d attr sets not configured.\n", ncf, 0, 0 ); |
|
Debug( LDAP_DEBUG_ANY, "pcache: %d attr sets not configured but referenced.\n", rf, 0, 0 ); |
|
|
/* consistency check (add more...) */ |
if ( rf > 0 ) { |
for ( i = 0; i < cm->numattrsets; i++ ) { |
|
if ( cm->qm->attr_sets[i].attrs == NULL ) { |
|
fprintf( stderr, "proxy_cache_open(): " |
|
"attr set %d (of %d) missing\n", |
|
i, cm->numattrsets ); |
|
return 1; |
return 1; |
} |
} |
} |
} |
Line 1740 proxy_cache_open(
|
Line 2101 proxy_cache_open(
|
if ( slapMode & SLAP_SERVER_MODE ) { |
if ( slapMode & SLAP_SERVER_MODE ) { |
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); |
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); |
ldap_pvt_runqueue_insert( &slapd_rq, cm->cc_period, |
ldap_pvt_runqueue_insert( &slapd_rq, cm->cc_period, |
consistency_check, on ); |
consistency_check, on, |
|
"pcache_consistency", be->be_suffix[0].bv_val ); |
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); |
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); |
|
|
/* Cached database must have the rootdn */ |
/* Cached database must have the rootdn */ |
if ( BER_BVISNULL( &cm->db.be_rootndn ) |
if ( BER_BVISNULL( &cm->db.be_rootndn ) |
|| BER_BVISEMPTY( &cm->db.be_rootndn ) ) |
|| BER_BVISEMPTY( &cm->db.be_rootndn ) ) |
{ |
{ |
fprintf( stderr, "proxy_cache_open(): " |
Debug( LDAP_DEBUG_ANY, "pcache_db_open(): " |
"underlying database of type \"%s\"\n" |
"underlying database of type \"%s\"\n" |
" serving naming context \"%s\"\n" |
" serving naming context \"%s\"\n" |
" has no \"rootdn\", required by \"proxycache\".\n", |
" has no \"rootdn\", required by \"proxycache\".\n", |
on->on_info->oi_orig->bi_type, |
on->on_info->oi_orig->bi_type, |
cm->db.be_suffix[0].bv_val ); |
cm->db.be_suffix[0].bv_val, 0 ); |
return 1; |
return 1; |
} |
} |
} |
} |
Line 1761 proxy_cache_open(
|
Line 2123 proxy_cache_open(
|
} |
} |
|
|
static int |
static int |
proxy_cache_close( |
pcache_db_close( |
BackendDB *be |
BackendDB *be |
) |
) |
{ |
{ |
Line 1803 proxy_cache_close(
|
Line 2165 proxy_cache_close(
|
} |
} |
|
|
static int |
static int |
proxy_cache_destroy( |
pcache_db_destroy( |
BackendDB *be |
BackendDB *be |
) |
) |
{ |
{ |
slap_overinst *on = (slap_overinst *)be->bd_info; |
slap_overinst *on = (slap_overinst *)be->bd_info; |
cache_manager *cm = on->on_bi.bi_private; |
cache_manager *cm = on->on_bi.bi_private; |
query_manager *qm = cm->qm; |
query_manager *qm = cm->qm; |
int rc = 0; |
|
|
|
if ( cm->db.bd_info->bi_db_destroy ) { |
/* cleanup stuff inherited from the original database... */ |
rc = cm->db.bd_info->bi_db_destroy( &cm->db ); |
cm->db.be_suffix = NULL; |
|
cm->db.be_nsuffix = NULL; |
|
BER_BVZERO( &cm->db.be_rootdn ); |
|
BER_BVZERO( &cm->db.be_rootndn ); |
|
BER_BVZERO( &cm->db.be_rootpw ); |
|
/* FIXME: there might be more... */ |
|
|
|
if ( cm->db.be_private != NULL ) { |
|
backend_destroy_one( &cm->db, 0 ); |
} |
} |
ldap_pvt_thread_mutex_destroy(&qm->lru_mutex); |
|
ldap_pvt_thread_mutex_destroy(&cm->cache_mutex); |
ldap_pvt_thread_mutex_destroy( &qm->lru_mutex ); |
ldap_pvt_thread_mutex_destroy(&cm->remove_mutex); |
ldap_pvt_thread_mutex_destroy( &cm->cache_mutex ); |
|
ldap_pvt_thread_mutex_destroy( &cm->remove_mutex ); |
free( qm ); |
free( qm ); |
free( cm ); |
free( cm ); |
return rc; |
|
} |
|
|
|
static void |
|
find_supersets ( struct attr_set* attr_sets, int numsets ) |
|
{ |
|
int num[MAX_ATTR_SETS]; |
|
int i, j, res; |
|
int* id_array; |
|
for ( i = 0; i < MAX_ATTR_SETS; i++ ) |
|
num[i] = 0; |
|
|
|
for ( i = 0; i < numsets; i++ ) { |
return 0; |
attr_sets[i].ID_array = (int*) ch_malloc( sizeof( int ) ); |
|
attr_sets[i].ID_array[0] = -1; |
|
} |
|
|
|
for ( i = 0; i < numsets; i++ ) { |
|
for ( j=i+1; j < numsets; j++ ) { |
|
res = compare_sets( attr_sets, i, j ); |
|
switch ( res ) { |
|
case 0: |
|
break; |
|
case 3: |
|
case 1: |
|
id_array = attr_sets[i].ID_array; |
|
attr_sets[i].ID_array = (int *) ch_realloc( id_array, |
|
( num[i] + 2 ) * sizeof( int )); |
|
attr_sets[i].ID_array[num[i]] = j; |
|
attr_sets[i].ID_array[num[i]+1] = -1; |
|
num[i]++; |
|
if (res == 1) |
|
break; |
|
case 2: |
|
id_array = attr_sets[j].ID_array; |
|
attr_sets[j].ID_array = (int *) ch_realloc( id_array, |
|
( num[j] + 2 ) * sizeof( int )); |
|
attr_sets[j].ID_array[num[j]] = i; |
|
attr_sets[j].ID_array[num[j]+1] = -1; |
|
num[j]++; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
|
* compares two sets of attributes (indices i and j) |
|
* returns 0: if neither set is contained in the other set |
|
* 1: if set i is contained in set j |
|
* 2: if set j is contained in set i |
|
* 3: the sets are equivalent |
|
*/ |
|
|
|
static int |
|
compare_sets(struct attr_set* set, int i, int j) |
|
{ |
|
int k,l,numI,numJ; |
|
int common=0; |
|
int result=0; |
|
|
|
if (( set[i].attrs == NULL ) && ( set[j].attrs == NULL )) |
|
return 3; |
|
|
|
if ( set[i].attrs == NULL ) |
|
return 2; |
|
|
|
if ( set[j].attrs == NULL ) |
|
return 1; |
|
|
|
numI = set[i].count; |
|
numJ = set[j].count; |
|
|
|
for ( l=0; l < numI; l++ ) { |
|
for ( k = 0; k < numJ; k++ ) { |
|
if ( strcmp( set[i].attrs[l].an_name.bv_val, |
|
set[j].attrs[k].an_name.bv_val ) == 0 ) |
|
common++; |
|
} |
|
} |
|
|
|
if ( common == numI ) |
|
result = 1; |
|
|
|
if ( common == numJ ) |
|
result += 2; |
|
|
|
return result; |
|
} |
} |
|
|
static slap_overinst proxy_cache; |
static slap_overinst pcache; |
|
|
int pcache_init() |
int pcache_initialize() |
{ |
{ |
LDAPAttributeType *at; |
LDAPAttributeType *at; |
int code; |
int code; |
Line 1921 int pcache_init()
|
Line 2205 int pcache_init()
|
at = ldap_str2attributetype( queryid_schema, &code, &err, |
at = ldap_str2attributetype( queryid_schema, &code, &err, |
LDAP_SCHEMA_ALLOW_ALL ); |
LDAP_SCHEMA_ALLOW_ALL ); |
if ( !at ) { |
if ( !at ) { |
fprintf( stderr, "AttributeType Load failed %s %s\n", |
Debug( LDAP_DEBUG_ANY, |
ldap_scherr2str(code), err ); |
"pcache_initialize: ldap_str2attributetype failed %s %s\n", |
|
ldap_scherr2str(code), err, 0 ); |
return code; |
return code; |
} |
} |
code = at_add( at, &err ); |
code = at_add( at, 0, NULL, &err ); |
if ( !code ) { |
if ( !code ) { |
slap_str2ad( at->at_names[0], &ad_queryid, &err ); |
slap_str2ad( at->at_names[0], &ad_queryid, &err ); |
} |
} |
ldap_memfree( at ); |
ldap_memfree( at ); |
if ( code ) { |
if ( code ) { |
fprintf( stderr, "AttributeType Load failed %s %s\n", |
Debug( LDAP_DEBUG_ANY, |
scherr2str(code), err ); |
"pcache_initialize: at_add failed %s %s\n", |
|
scherr2str(code), err, 0 ); |
return code; |
return code; |
} |
} |
|
|
proxy_cache.on_bi.bi_type = "proxycache"; |
pcache.on_bi.bi_type = "pcache"; |
proxy_cache.on_bi.bi_db_init = proxy_cache_init; |
pcache.on_bi.bi_db_init = pcache_db_init; |
proxy_cache.on_bi.bi_db_config = proxy_cache_config; |
pcache.on_bi.bi_db_config = pcache_db_config; |
proxy_cache.on_bi.bi_db_open = proxy_cache_open; |
pcache.on_bi.bi_db_open = pcache_db_open; |
proxy_cache.on_bi.bi_db_close = proxy_cache_close; |
pcache.on_bi.bi_db_close = pcache_db_close; |
proxy_cache.on_bi.bi_db_destroy = proxy_cache_destroy; |
pcache.on_bi.bi_db_destroy = pcache_db_destroy; |
proxy_cache.on_bi.bi_op_search = proxy_cache_search; |
|
|
pcache.on_bi.bi_op_search = pcache_op_search; |
|
|
|
pcache.on_bi.bi_chk_controls = pcache_chk_controls; |
|
|
|
pcache.on_bi.bi_cf_ocs = pcocs; |
|
|
|
code = config_register_schema( pccfg, pcocs ); |
|
if ( code ) return code; |
|
|
return overlay_register( &proxy_cache ); |
return overlay_register( &pcache ); |
} |
} |
|
|
#if SLAPD_OVER_PROXYCACHE == SLAPD_MOD_DYNAMIC |
#if SLAPD_OVER_PROXYCACHE == SLAPD_MOD_DYNAMIC |
int init_module(int argc, char *argv[]) { |
int init_module(int argc, char *argv[]) { |
return pcache_init(); |
return pcache_initialize(); |
} |
} |
#endif |
#endif |
|
|