version 1.41.2.5, 2005/06/08 21:50:17
|
version 1.41.2.19, 2007/07/23 20:08:32
|
Line 1
|
Line 1
|
/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/pcache.c,v 1.54 2005/06/04 07:44:39 hyc Exp $ */ |
/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/pcache.c,v 1.41.2.18 2007/06/13 14:28:11 ralf 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-2005 The OpenLDAP Foundation. |
* Copyright 2003-2007 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 68 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 */ |
|
time_t negttl; /* TTL for negative results */ |
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; |
|
|
/* |
/* |
* Represents a set of projected attributes and any |
* Represents a set of projected attributes. |
* supersets among all specified sets of attributes. |
|
*/ |
*/ |
|
|
struct attr_set { |
struct attr_set { |
|
unsigned flags; |
|
#define PC_CONFIGURED (0x1) |
|
#define PC_REFERENCED (0x2) |
|
#define PC_GOT_OC (0x4) |
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' */ |
|
}; |
}; |
|
|
struct query_manager_s; |
struct query_manager_s; |
Line 88 struct query_manager_s;
|
Line 91 struct query_manager_s;
|
/* prototypes for functions for 1) query containment |
/* prototypes for functions for 1) query containment |
* 2) query addition, 3) cache replacement |
* 2) query addition, 3) cache replacement |
*/ |
*/ |
typedef int (QCfunc)(struct query_manager_s*, Query*, int ); |
typedef CachedQuery * (QCfunc)(Operation *op, struct query_manager_s*, Query*, int ); |
typedef void (AddQueryfunc)(struct query_manager_s*, Query*, int, struct berval*); |
typedef void (AddQueryfunc)(struct query_manager_s*, Query*, int, struct berval*); |
typedef void (CRfunc)(struct query_manager_s*, struct berval * ); |
typedef void (CRfunc)(struct query_manager_s*, struct berval * ); |
|
|
Line 124 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; |
|
|
ldap_pvt_thread_mutex_t cache_mutex; |
ldap_pvt_thread_mutex_t cache_mutex; |
ldap_pvt_thread_mutex_t remove_mutex; |
|
|
|
query_manager* qm; /* query cache managed by the cache manager */ |
query_manager* qm; /* query cache managed by the cache manager */ |
} cache_manager; |
} cache_manager; |
|
|
|
static int pcache_debug; |
|
|
static AttributeDescription *ad_queryid; |
static AttributeDescription *ad_queryid; |
static char *queryid_schema = "( 1.3.6.1.4.1.4203.666.1.12 NAME 'queryid' " |
static char *queryid_schema = "( 1.3.6.1.4.1.4203.666.1.12 NAME 'queryid' " |
"DESC 'list of queries the entry belongs to' " |
"DESC 'list of queries the entry belongs to' " |
Line 186 merge_entry(
|
Line 190 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 261 add_query_on_top (query_manager* qm, Cac
|
Line 265 add_query_on_top (query_manager* qm, Cac
|
|
|
qc->lru_down = top; |
qc->lru_down = top; |
qc->lru_up = NULL; |
qc->lru_up = NULL; |
Debug( LDAP_DEBUG_ANY, "Base of added query = %s\n", |
Debug( pcache_debug, "Base of added query = %s\n", |
q->base.bv_val, 0, 0 ); |
q->base.bv_val, 0, 0 ); |
} |
} |
|
|
Line 294 remove_query (query_manager* qm, CachedQ
|
Line 298 remove_query (query_manager* qm, CachedQ
|
qc->lru_up = qc->lru_down = NULL; |
qc->lru_up = qc->lru_down = NULL; |
} |
} |
|
|
static void |
|
invert_string( struct berval *bv ) |
|
{ |
|
int i; |
|
char c; |
|
|
|
for (i=0; i<bv->bv_len/2; i++) { |
|
c = bv->bv_val[i]; |
|
bv->bv_val[i] = bv->bv_val[bv->bv_len-i-1]; |
|
bv->bv_val[bv->bv_len-i-1] = c; |
|
} |
|
} |
|
|
|
/* find and remove string2 from string1 |
/* find and remove string2 from string1 |
* from start if position = 1, |
* from start if position = 1, |
* from end if position = 3, |
* from end if position = 3, |
* from anywhere if position = 2 |
* from anywhere if position = 2 |
|
* string1 is overwritten if position = 2. |
*/ |
*/ |
|
|
static int |
static int |
find_and_remove(struct berval* ber1, struct berval* ber2, int position) |
find_and_remove(struct berval* ber1, struct berval* ber2, int position) |
{ |
{ |
char* temp; |
|
int len; |
|
int ret=0; |
int ret=0; |
|
|
char* arg1, *arg2; |
if ( !ber2->bv_val ) |
char* string1=ber1->bv_val; |
|
char* string2=ber2->bv_val; |
|
|
|
if (string2 == NULL) |
|
return 1; |
return 1; |
if (string1 == NULL) |
if ( !ber1->bv_val ) |
return 0; |
return 0; |
|
|
if (position == 3) { |
switch( position ) { |
invert_string(ber1); |
case 1: |
invert_string(ber2); |
if ( ber1->bv_len >= ber2->bv_len && !memcmp( ber1->bv_val, |
} |
ber2->bv_val, ber2->bv_len )) { |
|
ret = 1; |
arg1 = string1; |
ber1->bv_val += ber2->bv_len; |
arg2 = string2; |
ber1->bv_len -= ber2->bv_len; |
|
} |
temp = strstr(arg1, arg2); |
break; |
|
case 2: { |
len = ber2->bv_len; |
char *temp; |
|
ber1->bv_val[ber1->bv_len] = '\0'; |
if ( temp && (position == 2 || temp == arg1) ) { |
temp = strstr( ber1->bv_val, ber2->bv_val ); |
string1 = temp+len; |
if ( temp ) { |
strcpy( arg1, string1 ); |
strcpy( temp, temp+ber2->bv_len ); |
ber1->bv_len -= len; |
ber1->bv_len -= ber2->bv_len; |
ret = 1; |
ret = 1; |
} |
} |
if ( position == 3 ) { |
break; |
invert_string(ber1); |
} |
invert_string(ber2); |
case 3: |
|
if ( ber1->bv_len >= ber2->bv_len && |
|
!memcmp( ber1->bv_val+ber1->bv_len-ber2->bv_len, ber2->bv_val, |
|
ber2->bv_len )) { |
|
ret = 1; |
|
ber1->bv_len -= ber2->bv_len; |
|
} |
|
break; |
} |
} |
return ret; |
return ret; |
} |
} |
|
|
|
|
static struct berval* |
static struct berval* |
merge_init_final(struct berval* init, struct berval* any, struct berval* final) |
merge_init_final(Operation *op, struct berval* init, struct berval* any, |
|
struct berval* final) |
{ |
{ |
struct berval* merged, *temp; |
struct berval* merged, *temp; |
int i, any_count, count; |
int i, any_count, count; |
Line 371 merge_init_final(struct berval* init, st
|
Line 365 merge_init_final(struct berval* init, st
|
if (final->bv_val) |
if (final->bv_val) |
count++; |
count++; |
|
|
merged = (struct berval*)(ch_malloc((count+1)*sizeof(struct berval))); |
merged = (struct berval*)op->o_tmpalloc( (count+1)*sizeof(struct berval), |
|
op->o_tmpmemctx ); |
temp = merged; |
temp = merged; |
|
|
if (init->bv_val) { |
if (init->bv_val) { |
*temp++ = *init; |
ber_dupbv_x( temp, init, op->o_tmpmemctx ); |
|
temp++; |
} |
} |
|
|
for (i=0; i<any_count; i++) { |
for (i=0; i<any_count; i++) { |
*temp++ = *any++; |
ber_dupbv_x( temp, any, op->o_tmpmemctx ); |
|
temp++; any++; |
} |
} |
|
|
if (final->bv_val){ |
if (final->bv_val){ |
*temp++ = *final; |
ber_dupbv_x( temp, final, op->o_tmpmemctx ); |
|
temp++; |
} |
} |
temp->bv_val = NULL; |
BER_BVZERO( temp ); |
temp->bv_len = 0; |
|
return merged; |
return merged; |
} |
} |
|
|
|
/* Each element in stored must be found in incoming. Incoming is overwritten. |
|
*/ |
static int |
static int |
strings_containment(struct berval* stored, struct berval* incoming) |
strings_containment(struct berval* stored, struct berval* incoming) |
{ |
{ |
Line 416 strings_containment(struct berval* store
|
Line 415 strings_containment(struct berval* store
|
} |
} |
|
|
static int |
static int |
substr_containment_substr(Filter* stored, Filter* incoming) |
substr_containment_substr(Operation *op, Filter* stored, Filter* incoming) |
{ |
{ |
int i; |
|
int rc = 0; |
int rc = 0; |
int any_count = 0; |
|
|
|
struct berval init_incoming; |
struct berval init_incoming; |
struct berval final_incoming; |
struct berval final_incoming; |
struct berval *any_incoming = NULL; |
|
struct berval *remaining_incoming = NULL; |
struct berval *remaining_incoming = NULL; |
|
|
if ((!(incoming->f_sub_initial.bv_val) && (stored->f_sub_initial.bv_val)) |
if ((!(incoming->f_sub_initial.bv_val) && (stored->f_sub_initial.bv_val)) |
|| (!(incoming->f_sub_final.bv_val) && (stored->f_sub_final.bv_val))) |
|| (!(incoming->f_sub_final.bv_val) && (stored->f_sub_final.bv_val))) |
return 0; |
return 0; |
|
|
|
init_incoming = incoming->f_sub_initial; |
ber_dupbv(&init_incoming, &(incoming->f_sub_initial)); |
final_incoming = incoming->f_sub_final; |
ber_dupbv(&final_incoming, &(incoming->f_sub_final)); |
|
|
|
if (incoming->f_sub_any) { |
|
for ( any_count=0; incoming->f_sub_any[any_count].bv_val != NULL; |
|
any_count++ ) |
|
; |
|
|
|
any_incoming = (struct berval*)ch_malloc((any_count+1) * |
|
sizeof(struct berval)); |
|
|
|
for (i=0; i<any_count; i++) { |
|
ber_dupbv(&(any_incoming[i]), &(incoming->f_sub_any[i])); |
|
} |
|
any_incoming[any_count].bv_val = NULL; |
|
any_incoming[any_count].bv_len = 0; |
|
} |
|
|
|
if (find_and_remove(&init_incoming, |
if (find_and_remove(&init_incoming, |
&(stored->f_sub_initial), 1) && find_and_remove(&final_incoming, |
&(stored->f_sub_initial), 1) && find_and_remove(&final_incoming, |
Line 458 substr_containment_substr(Filter* stored
|
Line 438 substr_containment_substr(Filter* stored
|
rc = 1; |
rc = 1; |
goto final; |
goto final; |
} |
} |
remaining_incoming = merge_init_final(&init_incoming, |
remaining_incoming = merge_init_final(op, &init_incoming, |
any_incoming, &final_incoming); |
incoming->f_sub_any, &final_incoming); |
rc = strings_containment(stored->f_sub_any, remaining_incoming); |
rc = strings_containment(stored->f_sub_any, remaining_incoming); |
|
ber_bvarray_free_x( remaining_incoming, op->o_tmpmemctx ); |
} |
} |
final: |
final: |
free(init_incoming.bv_val); |
|
free(final_incoming.bv_val); |
|
if (any_incoming) ber_bvarray_free( any_incoming ); |
|
free(remaining_incoming); |
|
|
|
return rc; |
return rc; |
} |
} |
|
|
static int |
static int |
substr_containment_equality(Filter* stored, Filter* incoming) |
substr_containment_equality(Operation *op, Filter* stored, Filter* incoming) |
{ |
{ |
struct berval incoming_val[2]; |
struct berval incoming_val[2]; |
int rc = 0; |
int rc = 0; |
|
|
ber_dupbv(incoming_val, &(incoming->f_av_value)); |
incoming_val[1] = incoming->f_av_value; |
incoming_val[1].bv_val = NULL; |
|
incoming_val[1].bv_len = 0; |
|
|
|
if (find_and_remove(incoming_val, |
if (find_and_remove(incoming_val+1, |
&(stored->f_sub_initial), 1) && find_and_remove(incoming_val, |
&(stored->f_sub_initial), 1) && find_and_remove(incoming_val+1, |
&(stored->f_sub_final), 3)) { |
&(stored->f_sub_final), 3)) { |
if (stored->f_sub_any == NULL){ |
if (stored->f_sub_any == NULL){ |
rc = 1; |
rc = 1; |
goto final; |
goto final; |
} |
} |
|
ber_dupbv_x( incoming_val, incoming_val+1, op->o_tmpmemctx ); |
|
BER_BVZERO( incoming_val+1 ); |
rc = strings_containment(stored->f_sub_any, incoming_val); |
rc = strings_containment(stored->f_sub_any, incoming_val); |
|
op->o_tmpfree( incoming_val[0].bv_val, op->o_tmpmemctx ); |
} |
} |
final: |
final: |
free(incoming_val[0].bv_val); |
|
return rc; |
return rc; |
} |
} |
|
|
/* check whether query is contained in any of |
/* check whether query is contained in any of |
* the cached queries in template template_index |
* the cached queries in template template_index |
*/ |
*/ |
static int |
static CachedQuery * |
query_containment(query_manager *qm, |
query_containment(Operation *op, query_manager *qm, |
Query *query, |
Query *query, |
int template_index) |
int template_index) |
{ |
{ |
Line 517 query_containment(query_manager *qm,
|
Line 493 query_containment(query_manager *qm,
|
|
|
MatchingRule* mrule = NULL; |
MatchingRule* mrule = NULL; |
if (inputf != NULL) { |
if (inputf != NULL) { |
Debug( LDAP_DEBUG_ANY, "Lock QC index = %d\n", |
Debug( pcache_debug, "Lock QC index = %d\n", |
template_index, 0, 0 ); |
template_index, 0, 0 ); |
ldap_pvt_thread_rdwr_rlock(&(templa[template_index].t_rwlock)); |
ldap_pvt_thread_rdwr_rlock(&(templa[template_index].t_rwlock)); |
for(qc=templa[template_index].query; qc != NULL; qc= qc->next) { |
for(qc=templa[template_index].query; qc != NULL; qc= qc->next) { |
Line 548 query_containment(query_manager *qm,
|
Line 524 query_containment(query_manager *qm,
|
&(fs->f_ava->aa_value), &text); |
&(fs->f_ava->aa_value), &text); |
if (rc != LDAP_SUCCESS) { |
if (rc != LDAP_SUCCESS) { |
ldap_pvt_thread_rdwr_runlock(&(templa[template_index].t_rwlock)); |
ldap_pvt_thread_rdwr_runlock(&(templa[template_index].t_rwlock)); |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"Unlock: Exiting QC index=%d\n", |
"Unlock: Exiting QC index=%d\n", |
template_index, 0, 0 ); |
template_index, 0, 0 ); |
return 0; |
return NULL; |
} |
} |
} |
} |
switch (fs->f_choice) { |
switch (fs->f_choice) { |
Line 565 query_containment(query_manager *qm,
|
Line 541 query_containment(query_manager *qm,
|
/* check if the equality query can be |
/* check if the equality query can be |
* answered with cached substring query */ |
* answered with cached substring query */ |
if ((fi->f_choice == LDAP_FILTER_EQUALITY) |
if ((fi->f_choice == LDAP_FILTER_EQUALITY) |
&& substr_containment_equality( |
&& substr_containment_equality( op, |
fs, fi)) |
fs, fi)) |
res=1; |
res=1; |
/* check if the substring query can be |
/* check if the substring query can be |
* answered with cached substring query */ |
* answered with cached substring query */ |
if ((fi->f_choice ==LDAP_FILTER_SUBSTRINGS |
if ((fi->f_choice ==LDAP_FILTER_SUBSTRINGS |
) && substr_containment_substr( |
) && substr_containment_substr( op, |
fs, fi)) |
fs, fi)) |
res= 1; |
res= 1; |
fs=fs->f_next; |
fs=fs->f_next; |
Line 615 query_containment(query_manager *qm,
|
Line 591 query_containment(query_manager *qm,
|
add_query_on_top(qm, qc); |
add_query_on_top(qm, qc); |
} |
} |
ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); |
ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); |
return 1; |
return qc; |
} |
} |
} |
} |
} |
} |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"Not answerable: Unlock QC index=%d\n", |
"Not answerable: Unlock QC index=%d\n", |
template_index, 0, 0 ); |
template_index, 0, 0 ); |
ldap_pvt_thread_rdwr_runlock(&(templa[template_index].t_rwlock)); |
ldap_pvt_thread_rdwr_runlock(&(templa[template_index].t_rwlock)); |
} |
} |
return 0; |
return NULL; |
} |
} |
|
|
static void |
static void |
free_query (CachedQuery* qc) |
free_query (CachedQuery* qc) |
{ |
{ |
Query* q = (Query*)qc; |
Query* q = (Query*)qc; |
int i; |
|
|
|
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); |
if ( q->attrs ) { |
free(q->attrs); |
for (i=0; q->attrs[i].an_name.bv_val; i++) { |
|
free(q->attrs[i].an_name.bv_val); |
|
} |
|
free(q->attrs); |
|
} |
|
free(qc); |
free(qc); |
} |
} |
|
|
Line 657 static void add_query(
|
Line 627 static void add_query(
|
QueryTemplate* templ = (qm->templates)+template_index; |
QueryTemplate* templ = (qm->templates)+template_index; |
Query* new_query; |
Query* new_query; |
new_cached_query->template_id = template_index; |
new_cached_query->template_id = template_index; |
new_cached_query->q_uuid = *uuid; |
if ( uuid ) { |
|
new_cached_query->q_uuid = *uuid; |
|
new_cached_query->expiry_time = slap_get_time() + templ->ttl; |
|
} else { |
|
BER_BVZERO( &new_cached_query->q_uuid ); |
|
new_cached_query->expiry_time = slap_get_time() + templ->negttl; |
|
} |
new_cached_query->lru_up = NULL; |
new_cached_query->lru_up = NULL; |
new_cached_query->lru_down = NULL; |
new_cached_query->lru_down = NULL; |
new_cached_query->expiry_time = slap_get_time() + templ->ttl; |
Debug( pcache_debug, "Added query expires at %ld\n", |
Debug( LDAP_DEBUG_ANY, "Added query expires at %ld\n", |
|
(long) new_cached_query->expiry_time, 0, 0 ); |
(long) new_cached_query->expiry_time, 0, 0 ); |
new_query = (Query*)new_cached_query; |
new_query = (Query*)new_cached_query; |
|
|
Line 671 static void add_query(
|
Line 646 static void add_query(
|
new_query->attrs = query->attrs; |
new_query->attrs = query->attrs; |
|
|
/* Adding a query */ |
/* Adding a query */ |
Debug( LDAP_DEBUG_ANY, "Lock AQ index = %d\n", |
Debug( pcache_debug, "Lock AQ index = %d\n", |
template_index, 0, 0 ); |
template_index, 0, 0 ); |
ldap_pvt_thread_rdwr_wlock(&templ->t_rwlock); |
ldap_pvt_thread_rdwr_wlock(&templ->t_rwlock); |
if (templ->query == NULL) |
if (templ->query == NULL) |
Line 682 static void add_query(
|
Line 657 static void add_query(
|
new_cached_query->prev = NULL; |
new_cached_query->prev = NULL; |
templ->query = new_cached_query; |
templ->query = new_cached_query; |
templ->no_of_queries++; |
templ->no_of_queries++; |
Debug( LDAP_DEBUG_ANY, "TEMPLATE %d QUERIES++ %d\n", |
Debug( pcache_debug, "TEMPLATE %d QUERIES++ %d\n", |
template_index, templ->no_of_queries, 0 ); |
template_index, templ->no_of_queries, 0 ); |
|
|
Debug( LDAP_DEBUG_ANY, "Unlock AQ index = %d \n", |
Debug( pcache_debug, "Unlock AQ index = %d \n", |
template_index, 0, 0 ); |
template_index, 0, 0 ); |
ldap_pvt_thread_rdwr_wunlock(&templ->t_rwlock); |
ldap_pvt_thread_rdwr_wunlock(&templ->t_rwlock); |
|
|
Line 727 static void cache_replacement(query_mana
|
Line 702 static void cache_replacement(query_mana
|
result->bv_len = 0; |
result->bv_len = 0; |
|
|
if (!bottom) { |
if (!bottom) { |
Debug ( LDAP_DEBUG_ANY, |
Debug ( pcache_debug, |
"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 740 static void cache_replacement(query_mana
|
Line 716 static void cache_replacement(query_mana
|
*result = bottom->q_uuid; |
*result = bottom->q_uuid; |
bottom->q_uuid.bv_val = NULL; |
bottom->q_uuid.bv_val = NULL; |
|
|
Debug( LDAP_DEBUG_ANY, "Lock CR index = %d\n", temp_id, 0, 0 ); |
Debug( pcache_debug, "Lock CR index = %d\n", temp_id, 0, 0 ); |
ldap_pvt_thread_rdwr_wlock(&(qm->templates[temp_id].t_rwlock)); |
ldap_pvt_thread_rdwr_wlock(&(qm->templates[temp_id].t_rwlock)); |
remove_from_template(bottom, (qm->templates+temp_id)); |
remove_from_template(bottom, (qm->templates+temp_id)); |
Debug( LDAP_DEBUG_ANY, "TEMPLATE %d QUERIES-- %d\n", |
Debug( pcache_debug, "TEMPLATE %d QUERIES-- %d\n", |
temp_id, qm->templates[temp_id].no_of_queries, 0 ); |
temp_id, qm->templates[temp_id].no_of_queries, 0 ); |
Debug( LDAP_DEBUG_ANY, "Unlock CR index = %d\n", temp_id, 0, 0 ); |
Debug( pcache_debug, "Unlock CR index = %d\n", temp_id, 0, 0 ); |
ldap_pvt_thread_rdwr_wunlock(&(qm->templates[temp_id].t_rwlock)); |
ldap_pvt_thread_rdwr_wunlock(&(qm->templates[temp_id].t_rwlock)); |
free_query(bottom); |
free_query(bottom); |
} |
} |
Line 838 remove_query_data (
|
Line 814 remove_query_data (
|
op->o_req_ndn = qi->xdn; |
op->o_req_ndn = qi->xdn; |
|
|
if ( qi->del) { |
if ( qi->del) { |
Debug( LDAP_DEBUG_ANY, "DELETING ENTRY TEMPLATE=%s\n", |
Debug( pcache_debug, "DELETING ENTRY TEMPLATE=%s\n", |
query_uuid->bv_val, 0, 0 ); |
query_uuid->bv_val, 0, 0 ); |
|
|
op->o_tag = LDAP_REQ_DELETE; |
op->o_tag = LDAP_REQ_DELETE; |
Line 860 remove_query_data (
|
Line 836 remove_query_data (
|
mod.sml_values = vals; |
mod.sml_values = vals; |
mod.sml_nvalues = NULL; |
mod.sml_nvalues = NULL; |
mod.sml_next = NULL; |
mod.sml_next = NULL; |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"REMOVING TEMP ATTR : TEMPLATE=%s\n", |
"REMOVING TEMP ATTR : TEMPLATE=%s\n", |
query_uuid->bv_val, 0, 0 ); |
query_uuid->bv_val, 0, 0 ); |
|
|
Line 882 get_attr_set(
|
Line 858 get_attr_set(
|
); |
); |
|
|
static int |
static int |
attrscmp( |
|
AttributeName* attrs_in, |
|
AttributeName* attrs |
|
); |
|
|
|
static int |
|
is_temp_answerable( |
|
int attr_set, |
|
struct berval* tempstr, |
|
query_manager* qm, |
|
int template_id ) |
|
{ |
|
QueryTemplate *qt = qm->templates + template_id; |
|
|
|
if (attr_set != qt->attr_set_index) { |
|
int* id_array = qm->attr_sets[attr_set].ID_array; |
|
|
|
while (*id_array != -1) { |
|
if (*id_array == qt->attr_set_index) |
|
break; |
|
id_array++; |
|
} |
|
if (*id_array == -1) |
|
return 0; |
|
} |
|
return (qt->querystr.bv_len == tempstr->bv_len && |
|
strcasecmp(qt->querystr.bv_val, tempstr->bv_val) == 0); |
|
} |
|
|
|
static int |
|
filter2template( |
filter2template( |
|
Operation *op, |
Filter *f, |
Filter *f, |
struct berval *fstr, |
struct berval *fstr, |
AttributeName** filter_attrs, |
AttributeName** filter_attrs, |
int* filter_cnt ) |
int* filter_cnt, |
|
int* filter_got_oc ) |
{ |
{ |
AttributeDescription *ad; |
AttributeDescription *ad; |
|
|
Line 967 filter2template(
|
Line 915 filter2template(
|
fstr->bv_len += sizeof("(%") - 1; |
fstr->bv_len += sizeof("(%") - 1; |
|
|
for ( f = f->f_list; f != NULL; f = f->f_next ) { |
for ( f = f->f_list; f != NULL; f = f->f_next ) { |
rc = filter2template( f, fstr, filter_attrs, filter_cnt ); |
rc = filter2template( op, f, fstr, filter_attrs, filter_cnt, |
|
filter_got_oc ); |
if ( rc ) break; |
if ( rc ) break; |
} |
} |
sprintf( fstr->bv_val+fstr->bv_len, ")" ); |
sprintf( fstr->bv_val+fstr->bv_len, ")" ); |
Line 982 filter2template(
|
Line 931 filter2template(
|
return -1; |
return -1; |
} |
} |
|
|
*filter_attrs = (AttributeName *)ch_realloc(*filter_attrs, |
*filter_attrs = (AttributeName *)op->o_tmprealloc(*filter_attrs, |
(*filter_cnt + 2)*sizeof(AttributeName)); |
(*filter_cnt + 2)*sizeof(AttributeName), op->o_tmpmemctx); |
|
|
(*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; |
Line 991 filter2template(
|
Line 940 filter2template(
|
(*filter_attrs)[*filter_cnt].an_oc_exclude = 0; |
(*filter_attrs)[*filter_cnt].an_oc_exclude = 0; |
BER_BVZERO( &(*filter_attrs)[*filter_cnt+1].an_name ); |
BER_BVZERO( &(*filter_attrs)[*filter_cnt+1].an_name ); |
(*filter_cnt)++; |
(*filter_cnt)++; |
|
if ( ad == slap_schema.si_ad_objectClass ) |
|
*filter_got_oc = 1; |
return 0; |
return 0; |
} |
} |
|
|
Line 1027 cache_entries(
|
Line 978 cache_entries(
|
op_tmp.o_dn = cm->db.be_rootdn; |
op_tmp.o_dn = cm->db.be_rootdn; |
op_tmp.o_ndn = cm->db.be_rootndn; |
op_tmp.o_ndn = cm->db.be_rootndn; |
|
|
Debug( LDAP_DEBUG_ANY, "UUID for query being added = %s\n", |
Debug( pcache_debug, "UUID for query being added = %s\n", |
uuidbuf, 0, 0 ); |
uuidbuf, 0, 0 ); |
|
|
for ( e=si->head; e; e=si->head ) { |
for ( e=si->head; e; e=si->head ) { |
si->head = e->e_private; |
si->head = e->e_private; |
e->e_private = NULL; |
e->e_private = NULL; |
Debug( LDAP_DEBUG_NONE, "LOCKING REMOVE MUTEX\n", 0, 0, 0 ); |
|
ldap_pvt_thread_mutex_lock(&cm->remove_mutex); |
|
Debug( LDAP_DEBUG_NONE, "LOCKED REMOVE MUTEX\n", 0, 0, 0); |
|
while ( cm->cur_entries > (cm->max_entries) ) { |
while ( cm->cur_entries > (cm->max_entries) ) { |
qm->crfunc(qm, &crp_uuid); |
qm->crfunc(qm, &crp_uuid); |
if (crp_uuid.bv_val) { |
if (crp_uuid.bv_val) { |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"Removing query UUID %s\n", |
"Removing query UUID %s\n", |
crp_uuid.bv_val, 0, 0 ); |
crp_uuid.bv_val, 0, 0 ); |
return_val = remove_query_data(&op_tmp, rs, &crp_uuid); |
return_val = remove_query_data(&op_tmp, rs, &crp_uuid); |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"QUERY REMOVED, SIZE=%d\n", |
"QUERY REMOVED, SIZE=%d\n", |
return_val, 0, 0); |
return_val, 0, 0); |
ldap_pvt_thread_mutex_lock( |
ldap_pvt_thread_mutex_lock( |
&cm->cache_mutex ); |
&cm->cache_mutex ); |
cm->cur_entries -= return_val; |
cm->cur_entries -= return_val; |
cm->num_cached_queries--; |
cm->num_cached_queries--; |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"STORED QUERIES = %lu\n", |
"STORED QUERIES = %lu\n", |
cm->num_cached_queries, 0, 0 ); |
cm->num_cached_queries, 0, 0 ); |
ldap_pvt_thread_mutex_unlock( |
ldap_pvt_thread_mutex_unlock( |
&cm->cache_mutex ); |
&cm->cache_mutex ); |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"QUERY REMOVED, CACHE =" |
"QUERY REMOVED, CACHE =" |
"%d entries\n", |
"%d entries\n", |
cm->cur_entries, 0, 0 ); |
cm->cur_entries, 0, 0 ); |
Line 1063 cache_entries(
|
Line 1011 cache_entries(
|
} |
} |
|
|
return_val = merge_entry(&op_tmp, e, query_uuid); |
return_val = merge_entry(&op_tmp, e, query_uuid); |
ldap_pvt_thread_mutex_unlock(&cm->remove_mutex); |
|
ldap_pvt_thread_mutex_lock(&cm->cache_mutex); |
ldap_pvt_thread_mutex_lock(&cm->cache_mutex); |
cm->cur_entries += return_val; |
cm->cur_entries += return_val; |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"ENTRY ADDED/MERGED, CACHED ENTRIES=%d\n", |
"ENTRY ADDED/MERGED, CACHED ENTRIES=%d\n", |
cm->cur_entries, 0, 0 ); |
cm->cur_entries, 0, 0 ); |
return_val = 0; |
return_val = 0; |
ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); |
ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); |
} |
} |
ldap_pvt_thread_mutex_lock(&cm->cache_mutex); |
|
cm->num_cached_queries++; |
|
Debug( LDAP_DEBUG_ANY, "STORED QUERIES = %lu\n", |
|
cm->num_cached_queries, 0, 0 ); |
|
ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); |
|
|
|
return return_val; |
return return_val; |
} |
} |
|
|
static int |
static int |
proxy_cache_response( |
pcache_op_cleanup( Operation *op, SlapReply *rs ) { |
|
slap_callback *cb = op->o_callback; |
|
struct search_info *si = cb->sc_private; |
|
if ( si->query.save_attrs != NULL ) { |
|
rs->sr_attrs = si->query.save_attrs; |
|
op->ors_attrs = si->query.save_attrs; |
|
} |
|
op->o_callback = op->o_callback->sc_next; |
|
op->o_tmpfree( cb, op->o_tmpmemctx ); |
|
return SLAP_CB_CONTINUE; |
|
} |
|
|
|
static int |
|
pcache_response( |
Operation *op, |
Operation *op, |
SlapReply *rs ) |
SlapReply *rs ) |
{ |
{ |
Line 1092 proxy_cache_response(
|
Line 1047 proxy_cache_response(
|
query_manager* qm = cm->qm; |
query_manager* qm = cm->qm; |
struct berval uuid; |
struct berval uuid; |
|
|
|
if ( si->query.save_attrs != NULL ) { |
|
rs->sr_attrs = si->query.save_attrs; |
|
op->ors_attrs = si->query.save_attrs; |
|
si->query.save_attrs = NULL; |
|
} |
|
|
if ( rs->sr_type == REP_SEARCH ) { |
if ( rs->sr_type == REP_SEARCH ) { |
Entry *e; |
Entry *e; |
/* If we haven't exceeded the limit for this query, |
/* If we haven't exceeded the limit for this query, |
Line 1117 proxy_cache_response(
|
Line 1078 proxy_cache_response(
|
} |
} |
} |
} |
|
|
if (rs->sr_attrs != op->ors_attrs ) { |
|
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 ); |
|
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 ) { |
QueryTemplate* templ = (qm->templates)+si->template_id; |
qm->addfunc(qm, &si->query, si->template_id, &uuid); |
if (( si->count && cache_entries( op, rs, &uuid ) == 0 ) || |
|
( templ->negttl && !si->count && !si->over && |
|
rs->sr_err == LDAP_SUCCESS )) { |
|
qm->addfunc(qm, &si->query, si->template_id, |
|
si->count ? &uuid : NULL); |
|
|
|
ldap_pvt_thread_mutex_lock(&cm->cache_mutex); |
|
cm->num_cached_queries++; |
|
Debug( pcache_debug, "STORED QUERIES = %lu\n", |
|
cm->num_cached_queries, 0, 0 ); |
|
ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); |
|
|
/* If the consistency checker suspended itself, |
/* If the consistency checker suspended itself, |
* wake it back up |
* wake it back up |
*/ |
*/ |
Line 1139 proxy_cache_response(
|
Line 1103 proxy_cache_response(
|
} |
} |
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); |
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); |
} |
} |
|
} else { |
|
free( si->query.attrs ); |
|
filter_free( si->query.filter ); |
} |
} |
|
|
/* free self */ |
op->o_callback->sc_cleanup = pcache_op_cleanup; |
op->o_callback->sc_cleanup = slap_freeself_cb; |
|
} |
} |
return SLAP_CB_CONTINUE; |
return SLAP_CB_CONTINUE; |
} |
} |
Line 1151 static void
|
Line 1117 static void
|
add_filter_attrs( |
add_filter_attrs( |
Operation *op, |
Operation *op, |
AttributeName** new_attrs, |
AttributeName** new_attrs, |
AttributeName* attrs, |
struct attr_set *attrs, |
AttributeName* filter_attrs ) |
AttributeName* filter_attrs, |
|
int fattr_cnt, |
|
int fattr_got_oc) |
{ |
{ |
int alluser = 0; |
int alluser = 0; |
int allop = 0; |
int allop = 0; |
int i; |
int i, j; |
int count; |
int count; |
|
int addoc = 0; |
|
|
/* duplicate attrs */ |
/* duplicate attrs */ |
if (attrs == NULL) { |
count = attrs->count + fattr_cnt; |
count = 1; |
if ( !fattr_got_oc && !(attrs->flags & PC_GOT_OC)) { |
} else { |
addoc = 1; |
for (count=0; attrs[count].an_name.bv_val; count++) |
count++; |
; |
|
} |
|
*new_attrs = (AttributeName*)(op->o_tmpalloc((count+1)* |
|
sizeof(AttributeName), op->o_tmpmemctx)); |
|
if (attrs == NULL) { |
|
BER_BVSTR( &(*new_attrs)[0].an_name, "*" ); |
|
(*new_attrs)[0].an_desc = NULL; |
|
(*new_attrs)[0].an_oc = NULL; |
|
(*new_attrs)[0].an_oc_exclude = 0; |
|
BER_BVZERO( &(*new_attrs)[1].an_name ); |
|
alluser = 1; |
|
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; |
|
} |
|
BER_BVZERO( &(*new_attrs)[count].an_name ); |
|
alluser = an_find(*new_attrs, &AllUser); |
|
allop = an_find(*new_attrs, &AllOper); |
|
} |
} |
|
|
for ( i=0; filter_attrs[i].an_name.bv_val; i++ ) { |
*new_attrs = (AttributeName*)ch_malloc((count+1)* |
|
sizeof(AttributeName)); |
|
for (i=0; i<attrs->count; i++) { |
|
(*new_attrs)[i].an_name = attrs->attrs[i].an_name; |
|
(*new_attrs)[i].an_desc = attrs->attrs[i].an_desc; |
|
} |
|
BER_BVZERO( &(*new_attrs)[i].an_name ); |
|
alluser = an_find(*new_attrs, &AllUser); |
|
allop = an_find(*new_attrs, &AllOper); |
|
|
|
j = i; |
|
for ( i=0; i<fattr_cnt; i++ ) { |
if ( an_find(*new_attrs, &filter_attrs[i].an_name )) |
if ( an_find(*new_attrs, &filter_attrs[i].an_name )) |
continue; |
continue; |
if ( is_at_operational(filter_attrs[i].an_desc->ad_type) ) { |
if ( is_at_operational(filter_attrs[i].an_desc->ad_type) ) { |
Line 1194 add_filter_attrs(
|
Line 1154 add_filter_attrs(
|
continue; |
continue; |
} else if (alluser) |
} else if (alluser) |
continue; |
continue; |
*new_attrs = (AttributeName*)(op->o_tmprealloc(*new_attrs, |
(*new_attrs)[j].an_name = filter_attrs[i].an_name; |
(count+2)*sizeof(AttributeName), op->o_tmpmemctx)); |
(*new_attrs)[j].an_desc = filter_attrs[i].an_desc; |
(*new_attrs)[count].an_name = filter_attrs[i].an_name; |
(*new_attrs)[j].an_oc = NULL; |
(*new_attrs)[count].an_desc = filter_attrs[i].an_desc; |
(*new_attrs)[j].an_oc_exclude = 0; |
(*new_attrs)[count].an_oc = NULL; |
j++; |
(*new_attrs)[count].an_oc_exclude = 0; |
} |
count++; |
if ( addoc ) { |
BER_BVZERO( &(*new_attrs)[count].an_name ); |
(*new_attrs)[j].an_name = slap_schema.si_ad_objectClass->ad_cname; |
|
(*new_attrs)[j].an_desc = slap_schema.si_ad_objectClass; |
|
(*new_attrs)[j].an_oc = NULL; |
|
(*new_attrs)[j].an_oc_exclude = 0; |
|
j++; |
|
} |
|
BER_BVZERO( &(*new_attrs)[j].an_name ); |
|
} |
|
|
|
/* 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( pcache_debug, "%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 1214 proxy_cache_search(
|
Line 1215 proxy_cache_search(
|
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 count; |
|
|
|
int i = -1; |
int i = -1; |
|
|
AttributeName *filter_attrs = NULL; |
AttributeName *filter_attrs = NULL; |
Line 1224 proxy_cache_search(
|
Line 1223 proxy_cache_search(
|
|
|
int attr_set = -1; |
int attr_set = -1; |
int template_id = -1; |
int template_id = -1; |
int answerable = 0; |
CachedQuery *answerable = NULL; |
int cacheable = 0; |
int cacheable = 0; |
int fattr_cnt=0; |
int fattr_cnt=0; |
int oc_attr_absent = 1; |
int fattr_got_oc = 0; |
|
|
struct berval tempstr; |
struct berval tempstr; |
|
|
tempstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len+1, op->o_tmpmemctx ); |
tempstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len+1, op->o_tmpmemctx ); |
tempstr.bv_len = 0; |
tempstr.bv_len = 0; |
if (filter2template(op->ors_filter, &tempstr, &filter_attrs, &fattr_cnt)) { |
if ( filter2template( op, op->ors_filter, &tempstr, &filter_attrs, |
|
&fattr_cnt, &fattr_got_oc )) { |
op->o_tmpfree( tempstr.bv_val, op->o_tmpmemctx ); |
op->o_tmpfree( tempstr.bv_val, op->o_tmpmemctx ); |
return SLAP_CB_CONTINUE; |
return SLAP_CB_CONTINUE; |
} |
} |
|
|
Debug( LDAP_DEBUG_ANY, "query template of incoming query = %s\n", |
Debug( pcache_debug, "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 1252 proxy_cache_search(
|
Line 1255 proxy_cache_search(
|
|
|
/* check for query containment */ |
/* check for query containment */ |
if (attr_set > -1) { |
if (attr_set > -1) { |
for (i=0; i<cm->numtemplates; i++) { |
QueryTemplate *qt = qm->templates; |
|
for (i=0; i<cm->numtemplates; i++, qt++) { |
/* find if template i can potentially answer tempstr */ |
/* find if template i can potentially answer tempstr */ |
if (!is_temp_answerable(attr_set, &tempstr, qm, i)) |
if ( qt->attr_set_index != attr_set || |
|
qt->querystr.bv_len != tempstr.bv_len || |
|
strcasecmp( qt->querystr.bv_val, tempstr.bv_val )) |
continue; |
continue; |
if (attr_set == qm->templates[i].attr_set_index) { |
cacheable = 1; |
cacheable = 1; |
template_id = i; |
template_id = i; |
|
} |
|
Debug( LDAP_DEBUG_NONE, "Entering QC, querystr = %s\n", |
Debug( LDAP_DEBUG_NONE, "Entering QC, querystr = %s\n", |
op->ors_filterstr.bv_val, 0, 0 ); |
op->ors_filterstr.bv_val, 0, 0 ); |
answerable = (*(qm->qcfunc))(qm, &query, i); |
answerable = (*(qm->qcfunc))(op, qm, &query, i); |
|
|
if (answerable) |
if (answerable) |
break; |
break; |
Line 1279 proxy_cache_search(
|
Line 1283 proxy_cache_search(
|
BackendDB *save_bd = op->o_bd; |
BackendDB *save_bd = op->o_bd; |
slap_callback *save_cb = op->o_callback; |
slap_callback *save_cb = op->o_callback; |
|
|
Debug( LDAP_DEBUG_ANY, "QUERY ANSWERABLE\n", 0, 0, 0 ); |
Debug( pcache_debug, "QUERY ANSWERABLE\n", 0, 0, 0 ); |
free(filter_attrs); |
op->o_tmpfree( filter_attrs, op->o_tmpmemctx ); |
ldap_pvt_thread_rdwr_runlock(&qm->templates[i].t_rwlock); |
ldap_pvt_thread_rdwr_runlock(&qm->templates[i].t_rwlock); |
op->o_bd = &cm->db; |
if ( BER_BVISNULL( &answerable->q_uuid )) { |
op->o_callback = NULL; |
/* No entries cached, just an empty result set */ |
i = cm->db.bd_info->bi_op_search( op, rs ); |
i = rs->sr_err = 0; |
|
send_ldap_result( op, rs ); |
|
} else { |
|
op->o_bd = &cm->db; |
|
op->o_callback = NULL; |
|
i = cm->db.bd_info->bi_op_search( op, rs ); |
|
} |
op->o_bd = save_bd; |
op->o_bd = save_bd; |
op->o_callback = save_cb; |
op->o_callback = save_cb; |
return i; |
return i; |
} |
} |
|
|
Debug( LDAP_DEBUG_ANY, "QUERY NOT ANSWERABLE\n", 0, 0, 0 ); |
Debug( pcache_debug, "QUERY NOT ANSWERABLE\n", 0, 0, 0 ); |
|
|
ldap_pvt_thread_mutex_lock(&cm->cache_mutex); |
ldap_pvt_thread_mutex_lock(&cm->cache_mutex); |
if (cm->num_cached_queries >= cm->max_queries) { |
if (cm->num_cached_queries >= cm->max_queries) { |
Line 1298 proxy_cache_search(
|
Line 1308 proxy_cache_search(
|
} |
} |
ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); |
ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); |
|
|
|
if (op->ors_attrsonly) |
|
cacheable = 0; |
|
|
if (cacheable) { |
if (cacheable) { |
slap_callback *cb; |
slap_callback *cb; |
struct search_info *si; |
struct search_info *si; |
|
|
Debug( LDAP_DEBUG_ANY, "QUERY CACHEABLE\n", 0, 0, 0 ); |
Debug( pcache_debug, "QUERY CACHEABLE\n", 0, 0, 0 ); |
query.filter = str2filter(op->ors_filterstr.bv_val); |
query.filter = filter_dup(op->ors_filter, NULL); |
if (op->ors_attrs) { |
add_filter_attrs(op, &query.attrs, &qm->attr_sets[attr_set], |
for ( count = 0; !BER_BVISNULL( &op->ors_attrs[ count ].an_name ); count++ ) { |
filter_attrs, fattr_cnt, fattr_got_oc); |
if ( op->ors_attrs[count].an_desc == slap_schema.si_ad_objectClass ) { |
|
oc_attr_absent = 0; |
op->ors_attrs = query.attrs; |
} |
|
} |
|
query.attrs = (AttributeName *)ch_malloc( ( count + 1 + oc_attr_absent ) |
|
*sizeof(AttributeName) ); |
|
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 ); |
|
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 ) { |
|
query.attrs[ count ].an_desc = slap_schema.si_ad_objectClass; |
|
ber_dupbv( &query.attrs[count].an_name, |
|
&slap_schema.si_ad_objectClass->ad_cname ); |
|
query.attrs[ count ].an_oc = NULL; |
|
query.attrs[ count ].an_oc_exclude = 0; |
|
count++; |
|
} |
|
BER_BVZERO( &query.attrs[ count ].an_name ); |
|
} |
|
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 1360 proxy_cache_search(
|
Line 1352 proxy_cache_search(
|
} |
} |
|
|
} else { |
} else { |
Debug( LDAP_DEBUG_ANY, "QUERY NOT CACHEABLE\n", |
Debug( pcache_debug, "QUERY NOT CACHEABLE\n", |
0, 0, 0); |
0, 0, 0); |
} |
} |
|
|
free(filter_attrs); |
op->o_tmpfree( filter_attrs, op->o_tmpmemctx ); |
|
|
return SLAP_CB_CONTINUE; |
return SLAP_CB_CONTINUE; |
} |
} |
|
|
static int |
static int |
attrscmp( |
|
AttributeName* attrs_in, |
|
AttributeName* attrs) |
|
{ |
|
int i, count1, count2; |
|
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++ ) |
|
; |
|
for ( count2=0; |
|
attrs && attrs[count2].an_name.bv_val != NULL; |
|
count2++) |
|
; |
|
if ( count1 != count2 ) |
|
return 0; |
|
|
|
for ( i=0; i<count1; i++ ) { |
|
if ( !an_find(attrs, &attrs_in[i].an_name )) |
|
return 0; |
|
} |
|
return 1; |
|
} |
|
|
|
static int |
|
get_attr_set( |
get_attr_set( |
AttributeName* attrs, |
AttributeName* attrs, |
query_manager* qm, |
query_manager* qm, |
int num ) |
int num ) |
{ |
{ |
int i; |
int i; |
|
int count = 0; |
|
|
|
if ( attrs ) { |
|
for ( ; attrs[count].an_name.bv_val; count++ ); |
|
} |
|
|
for (i=0; i<num; i++) { |
for (i=0; i<num; i++) { |
if (attrscmp(attrs, qm->attr_sets[i].attrs)) |
AttributeName *a2; |
return i; |
int found = 1; |
|
|
|
if ( count > qm->attr_sets[i].count ) |
|
continue; |
|
if ( !count ) { |
|
if ( !qm->attr_sets[i].count ) |
|
break; |
|
continue; |
|
} |
|
for ( a2 = attrs; a2->an_name.bv_val; a2++ ) { |
|
if ( !an_find( qm->attr_sets[i].attrs, &a2->an_name )) { |
|
found = 0; |
|
break; |
|
} |
|
} |
|
if ( found ) |
|
break; |
} |
} |
return -1; |
if ( i == num ) |
|
i = -1; |
|
return i; |
} |
} |
|
|
static void* |
static void* |
Line 1423 consistency_check(
|
Line 1409 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 1431 consistency_check(
|
Line 1417 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 1445 consistency_check(
|
Line 1431 consistency_check(
|
query = templ->query_last; |
query = templ->query_last; |
if ( query ) pause = 0; |
if ( query ) pause = 0; |
op->o_time = slap_get_time(); |
op->o_time = slap_get_time(); |
ldap_pvt_thread_mutex_lock(&cm->remove_mutex); |
|
while (query && (query->expiry_time < op->o_time)) { |
while (query && (query->expiry_time < op->o_time)) { |
ldap_pvt_thread_mutex_lock(&qm->lru_mutex); |
Debug( pcache_debug, "Lock CR index = %d\n", |
remove_query(qm, query); |
|
ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); |
|
Debug( LDAP_DEBUG_ANY, "Lock CR index = %d\n", |
|
i, 0, 0 ); |
i, 0, 0 ); |
ldap_pvt_thread_rdwr_wlock(&templ->t_rwlock); |
ldap_pvt_thread_rdwr_wlock(&templ->t_rwlock); |
remove_from_template(query, templ); |
remove_from_template(query, templ); |
Debug( LDAP_DEBUG_ANY, "TEMPLATE %d QUERIES-- %d\n", |
Debug( pcache_debug, "TEMPLATE %d QUERIES-- %d\n", |
i, templ->no_of_queries, 0 ); |
i, templ->no_of_queries, 0 ); |
Debug( LDAP_DEBUG_ANY, "Unlock CR index = %d\n", |
Debug( pcache_debug, "Unlock CR index = %d\n", |
i, 0, 0 ); |
i, 0, 0 ); |
ldap_pvt_thread_rdwr_wunlock(&templ->t_rwlock); |
ldap_pvt_thread_rdwr_wunlock(&templ->t_rwlock); |
return_val = remove_query_data(op, &rs, &query->q_uuid); |
ldap_pvt_thread_mutex_lock(&qm->lru_mutex); |
Debug( LDAP_DEBUG_ANY, "STALE QUERY REMOVED, SIZE=%d\n", |
remove_query(qm, query); |
|
ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); |
|
if ( BER_BVISNULL( &query->q_uuid )) |
|
return_val = 0; |
|
else |
|
return_val = remove_query_data(op, &rs, &query->q_uuid); |
|
Debug( pcache_debug, "STALE QUERY REMOVED, SIZE=%d\n", |
return_val, 0, 0 ); |
return_val, 0, 0 ); |
ldap_pvt_thread_mutex_lock(&cm->cache_mutex); |
ldap_pvt_thread_mutex_lock(&cm->cache_mutex); |
cm->cur_entries -= return_val; |
cm->cur_entries -= return_val; |
cm->num_cached_queries--; |
cm->num_cached_queries--; |
Debug( LDAP_DEBUG_ANY, "STORED QUERIES = %lu\n", |
Debug( pcache_debug, "STORED QUERIES = %lu\n", |
cm->num_cached_queries, 0, 0 ); |
cm->num_cached_queries, 0, 0 ); |
ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); |
ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); |
Debug( LDAP_DEBUG_ANY, |
Debug( pcache_debug, |
"STALE QUERY REMOVED, CACHE =" |
"STALE QUERY REMOVED, CACHE =" |
"%d entries\n", |
"%d entries\n", |
cm->cur_entries, 0, 0 ); |
cm->cur_entries, 0, 0 ); |
Line 1476 consistency_check(
|
Line 1464 consistency_check(
|
query = query->prev; |
query = query->prev; |
free_query(query_prev); |
free_query(query_prev); |
} |
} |
ldap_pvt_thread_mutex_unlock(&cm->remove_mutex); |
|
} |
} |
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); |
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); |
if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask )) { |
if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask )) { |
Line 1493 consistency_check(
|
Line 1480 consistency_check(
|
|
|
#define MAX_ATTR_SETS 500 |
#define MAX_ATTR_SETS 500 |
|
|
/* |
|
* 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 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 { |
enum { |
PC_MAIN = 1, |
PC_MAIN = 1, |
PC_ATTR, |
PC_ATTR, |
PC_TEMP, |
PC_TEMP, |
PC_RESP |
PC_RESP, |
|
PC_QUERIES |
}; |
}; |
|
|
static ConfigDriver pc_cf_gen; |
static ConfigDriver pc_cf_gen; |
Line 1603 static ConfigTable pccfg[] = {
|
Line 1504 static ConfigTable pccfg[] = {
|
"( OLcfgOvAt:2.2 NAME 'olcProxyAttrset' " |
"( OLcfgOvAt:2.2 NAME 'olcProxyAttrset' " |
"DESC 'A set of attributes to cache' " |
"DESC 'A set of attributes to cache' " |
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
{ "proxytemplate", "filter> <attrset-index> <TTL", |
{ "proxytemplate", "filter> <attrset-index> <TTL> <negTTL", |
4, 4, 0, ARG_MAGIC|PC_TEMP, pc_cf_gen, |
4, 5, 0, ARG_MAGIC|PC_TEMP, pc_cf_gen, |
"( OLcfgOvAt:2.3 NAME 'olcProxyTemplate' " |
"( OLcfgOvAt:2.3 NAME 'olcProxyTemplate' " |
"DESC 'Filter template, attrset, and cache TTL' " |
"DESC 'Filter template, attrset, cache TTL, optional negative TTL' " |
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
{ "response-callback", "head|tail(default)", |
{ "response-callback", "head|tail(default)", |
2, 2, 0, ARG_MAGIC|ARG_STRING|PC_RESP, pc_cf_gen, |
2, 2, 0, ARG_MAGIC|PC_RESP, pc_cf_gen, |
"( OLcfgOvAt:2.4 NAME 'olcProxyResponseCB' " |
"( OLcfgOvAt:2.4 NAME 'olcProxyResponseCB' " |
"DESC 'Response callback position in overlay stack' " |
"DESC 'Response callback position in overlay stack' " |
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
"SYNTAX OMsDirectoryString )", NULL, NULL }, |
|
{ "proxyCacheQueries", "queries", |
|
2, 2, 0, ARG_INT|ARG_MAGIC|PC_QUERIES, pc_cf_gen, |
|
"( OLcfgOvAt:2.5 NAME 'olcProxyCacheQueries' " |
|
"DESC 'Maximum number of queries to cache' " |
|
"SYNTAX OMsInteger )", NULL, NULL }, |
|
|
{ NULL, NULL, 0, 0, 0, ARG_IGNORED } |
{ NULL, NULL, 0, 0, 0, ARG_IGNORED } |
}; |
}; |
|
|
Line 1622 static ConfigOCs pcocs[] = {
|
Line 1529 static ConfigOCs pcocs[] = {
|
"DESC 'ProxyCache configuration' " |
"DESC 'ProxyCache configuration' " |
"SUP olcOverlayConfig " |
"SUP olcOverlayConfig " |
"MUST ( olcProxyCache $ olcProxyAttrset $ olcProxyTemplate ) " |
"MUST ( olcProxyCache $ olcProxyAttrset $ olcProxyTemplate ) " |
"MAY olcProxyResponseCB )", Cft_Overlay, pccfg, NULL, pc_cfadd }, |
"MAY ( olcProxyResponseCB $ olcProxyCacheQueries ) )", Cft_Overlay, pccfg, NULL, pc_cfadd }, |
{ "( OLcfgOvOc:2.2 " |
{ "( OLcfgOvOc:2.2 " |
"NAME 'olcPcacheDatabase' " |
"NAME 'olcPcacheDatabase' " |
"DESC 'Cache database configuration' " |
"DESC 'Cache database configuration' " |
Line 1671 pc_cfadd( Operation *op, SlapReply *rs,
|
Line 1578 pc_cfadd( Operation *op, SlapReply *rs,
|
static int |
static int |
pc_cf_gen( ConfigArgs *c ) |
pc_cf_gen( ConfigArgs *c ) |
{ |
{ |
slap_overinst *on = (slap_overinst *)c->bi; |
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; |
int i, num, rc = 0; |
int i, num, rc = 0; |
char *ptr; |
char *ptr; |
|
unsigned long t; |
|
|
if ( c->op == SLAP_CONFIG_EMIT ) { |
if ( c->op == SLAP_CONFIG_EMIT ) { |
struct berval bv; |
struct berval bv; |
switch( c->type ) { |
switch( c->type ) { |
case PC_MAIN: |
case PC_MAIN: |
bv.bv_len = sprintf( c->msg, "%s %d %d %d %d", |
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->db.bd_info->bi_type, cm->max_entries, cm->numattrsets, |
cm->num_entries_limit, cm->cc_period ); |
cm->num_entries_limit, cm->cc_period ); |
bv.bv_val = c->msg; |
bv.bv_val = c->msg; |
Line 1695 pc_cf_gen( ConfigArgs *c )
|
Line 1603 pc_cf_gen( ConfigArgs *c )
|
for (i=0; i<cm->numattrsets; i++) { |
for (i=0; i<cm->numattrsets; i++) { |
if ( !qm->attr_sets[i].count ) continue; |
if ( !qm->attr_sets[i].count ) continue; |
|
|
bv.bv_len = sprintf( c->msg, "%d", i ); |
bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%d", i ); |
|
|
/* count the attr length */ |
/* count the attr length */ |
for ( attr_name = qm->attr_sets[i].attrs; |
for ( attr_name = qm->attr_sets[i].attrs; |
Line 1716 pc_cf_gen( ConfigArgs *c )
|
Line 1624 pc_cf_gen( ConfigArgs *c )
|
break; |
break; |
case PC_TEMP: |
case PC_TEMP: |
for (i=0; i<cm->numtemplates; i++) { |
for (i=0; i<cm->numtemplates; i++) { |
bv.bv_len = sprintf( c->msg, " %d %d", |
if ( qm->templates[i].negttl ) { |
qm->templates[i].attr_set_index, |
bv.bv_len = snprintf( c->msg, sizeof( c->msg ), |
qm->templates[i].ttl ); |
" %d %ld %ld", |
|
qm->templates[i].attr_set_index, |
|
qm->templates[i].ttl, |
|
qm->templates[i].negttl ); |
|
} else { |
|
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_len += qm->templates[i].querystr.bv_len + 2; |
bv.bv_val = ch_malloc( bv.bv_len+1 ); |
bv.bv_val = ch_malloc( bv.bv_len+1 ); |
ptr = bv.bv_val; |
ptr = bv.bv_val; |
Line 1733 pc_cf_gen( ConfigArgs *c )
|
Line 1649 pc_cf_gen( ConfigArgs *c )
|
break; |
break; |
case PC_RESP: |
case PC_RESP: |
if ( cm->response_cb == PCACHE_RESPONSE_CB_HEAD ) { |
if ( cm->response_cb == PCACHE_RESPONSE_CB_HEAD ) { |
bv.bv_val = "head"; |
BER_BVSTR( &bv, "head" ); |
bv.bv_len = STRLENOF("head"); |
|
} else { |
} else { |
bv.bv_val = "tail"; |
BER_BVSTR( &bv, "tail" ); |
bv.bv_len = STRLENOF("tail"); |
|
} |
} |
value_add_one( &c->rvalue_vals, &bv ); |
value_add_one( &c->rvalue_vals, &bv ); |
break; |
break; |
|
case PC_QUERIES: |
|
c->value_int = cm->max_queries; |
|
break; |
} |
} |
return rc; |
return rc; |
} else if ( c->op == LDAP_MOD_DELETE ) { |
} else if ( c->op == LDAP_MOD_DELETE ) { |
Line 1756 pc_cf_gen( ConfigArgs *c )
|
Line 1673 pc_cf_gen( ConfigArgs *c )
|
|
|
switch( c->type ) { |
switch( c->type ) { |
case PC_MAIN: |
case PC_MAIN: |
cm->numattrsets = atoi( c->argv[3] ); |
if ( cm->numattrsets > 0 ) { |
if ( cm->numattrsets > MAX_ATTR_SETS ) { |
snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive already provided" ); |
sprintf( c->msg, "numattrsets must be <= %d", MAX_ATTR_SETS ); |
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
return( 1 ); |
} |
} |
cm->db.bd_info = backend_info( c->argv[1] ); |
|
if ( !cm->db.bd_info ) { |
if ( lutil_atoi( &cm->numattrsets, c->argv[3] ) != 0 ) { |
sprintf( c->msg, "unknown backend type" ); |
snprintf( c->msg, sizeof( c->msg ), "unable to parse num attrsets=\"%s\" (arg #3)", |
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); |
c->argv[3] ); |
|
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
return( 1 ); |
return( 1 ); |
} |
} |
if ( cm->db.bd_info->bi_db_init( &cm->db ) ) { |
if ( cm->numattrsets <= 0 ) { |
sprintf( c->msg, "backend %s init failed", c->argv[1] ); |
snprintf( c->msg, sizeof( c->msg ), "numattrsets (arg #3) must be positive" ); |
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); |
Debug( LDAP_DEBUG_CONFIG, "%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_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
return( 1 ); |
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_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
|
cm->max_entries = atoi( c->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_CONFIG, "%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_CONFIG, "%s: %s\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
|
cm->num_entries_limit = atoi( c->argv[4] ); |
if ( lutil_atoi( &cm->num_entries_limit, c->argv[4] ) != 0 ) { |
cm->cc_period = atoi( c->argv[5] ); |
snprintf( c->msg, sizeof( c->msg ), "unable to parse entry limit=\"%s\" (arg #4)", |
Debug( LDAP_DEBUG_TRACE, |
c->argv[4] ); |
"Total # of attribute sets to be cached = %d\n", |
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
cm->numattrsets, 0, 0 ); |
return( 1 ); |
qm->attr_sets = ( struct attr_set * )ch_malloc( cm->numattrsets * |
} |
sizeof( struct attr_set )); |
if ( cm->num_entries_limit <= 0 ) { |
for ( i = 0; i < cm->numattrsets; i++ ) { |
snprintf( c->msg, sizeof( c->msg ), "entry limit (arg #4) must be positive" ); |
qm->attr_sets[i].attrs = NULL; |
Debug( LDAP_DEBUG_CONFIG, "%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_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
|
|
if ( lutil_parse_time( c->argv[5], &t ) != 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "unable to parse period=\"%s\" (arg #5)", |
|
c->argv[5] ); |
|
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
} |
} |
|
cm->cc_period = (time_t)t; |
|
Debug( pcache_debug, |
|
"Total # of attribute sets to be cached = %d.\n", |
|
cm->numattrsets, 0, 0 ); |
|
qm->attr_sets = ( struct attr_set * )ch_calloc( cm->numattrsets, |
|
sizeof( struct attr_set ) ); |
break; |
break; |
case PC_ATTR: |
case PC_ATTR: |
num = atoi( c->argv[1] ); |
if ( cm->numattrsets == 0 ) { |
if (num >= cm->numattrsets) { |
snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive not provided yet" ); |
sprintf( c->msg, "attrset index out of bounds" ); |
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); |
return( 1 ); |
|
} |
|
if ( lutil_atoi( &num, c->argv[1] ) != 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "unable to parse attrset #=\"%s\"", |
|
c->argv[1] ); |
|
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
|
|
if ( num < 0 || num >= cm->numattrsets ) { |
|
snprintf( c->msg, sizeof( c->msg ), "attrset index %d out of bounds (must be %s%d)", |
|
num, cm->numattrsets > 1 ? "0->" : "", cm->numattrsets - 1 ); |
|
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
return 1; |
return 1; |
} |
} |
if ( c->argv[2] && strcmp( c->argv[2], "*" ) ) { |
qm->attr_sets[num].flags |= PC_CONFIGURED; |
|
if ( c->argc > 2 && strcmp( c->argv[2], "*" ) ) { |
qm->attr_sets[num].count = c->argc - 2; |
qm->attr_sets[num].count = c->argc - 2; |
qm->attr_sets[num].attrs = (AttributeName*)ch_malloc( |
qm->attr_sets[num].attrs = (AttributeName*)ch_malloc( |
(c->argc-1) * sizeof( AttributeName )); |
(c->argc-1) * sizeof( AttributeName )); |
attr_name = qm->attr_sets[num].attrs; |
attr_name = qm->attr_sets[num].attrs; |
for ( i = 2; i < c->argc; i++ ) { |
for ( i = 2; i < c->argc; i++ ) { |
ber_str2bv( c->argv[i], 0, 1, &attr_name->an_name); |
|
attr_name->an_desc = NULL; |
attr_name->an_desc = NULL; |
if ( slap_bv2ad( &attr_name->an_name, |
if ( slap_str2ad( c->argv[i], |
&attr_name->an_desc, &text )) { |
&attr_name->an_desc, &text ) ) |
|
{ |
strcpy( c->msg, text ); |
strcpy( c->msg, text ); |
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); |
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
ch_free( qm->attr_sets[num].attrs ); |
ch_free( qm->attr_sets[num].attrs ); |
qm->attr_sets[num].attrs = NULL; |
qm->attr_sets[num].attrs = NULL; |
qm->attr_sets[num].count = 0; |
qm->attr_sets[num].count = 0; |
return 1; |
return 1; |
} |
} |
|
attr_name->an_name = attr_name->an_desc->ad_cname; |
attr_name->an_oc = NULL; |
attr_name->an_oc = NULL; |
attr_name->an_oc_exclude = 0; |
attr_name->an_oc_exclude = 0; |
|
if ( attr_name->an_desc == slap_schema.si_ad_objectClass ) |
|
qm->attr_sets[num].flags |= PC_GOT_OC; |
attr_name++; |
attr_name++; |
BER_BVZERO( &attr_name->an_name ); |
BER_BVZERO( &attr_name->an_name ); |
} |
} |
} |
} |
break; |
break; |
case PC_TEMP: |
case PC_TEMP: |
if (( i = atoi( c->argv[2] )) >= cm->numattrsets ) { |
if ( cm->numattrsets == 0 ) { |
sprintf( c->msg, "template index invalid" ); |
snprintf( c->msg, sizeof( c->msg ), "\"proxycache\" directive not provided yet" ); |
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); |
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
if ( lutil_atoi( &i, c->argv[2] ) != 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "unable to parse template #=\"%s\"", |
|
c->argv[2] ); |
|
Debug( LDAP_DEBUG_CONFIG, "%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_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
return 1; |
return 1; |
} |
} |
num = cm->numtemplates; |
num = cm->numtemplates; |
if ( num == 0 ) |
|
find_supersets( qm->attr_sets, cm->numattrsets ); |
|
qm->templates = ( QueryTemplate* )ch_realloc( qm->templates, |
qm->templates = ( QueryTemplate* )ch_realloc( qm->templates, |
( num + 2 ) * sizeof( QueryTemplate )); |
( num + 2 ) * sizeof( QueryTemplate )); |
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( c->argv[3] ); |
if ( lutil_parse_time( c->argv[3], &t ) != 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "unable to parse template ttl=\"%s\"", |
|
c->argv[3] ); |
|
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
temp->ttl = (time_t)t; |
|
if ( c->argc == 5 ) { |
|
if ( lutil_parse_time( c->argv[4], &t ) != 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), |
|
"unable to parse template negttl=\"%s\"", |
|
c->argv[4] ); |
|
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
temp->negttl = (time_t)t; |
|
} else { |
|
temp->negttl = 0; |
|
} |
|
|
temp->no_of_queries = 0; |
temp->no_of_queries = 0; |
|
|
ber_str2bv( c->argv[1], 0, 1, &temp->querystr ); |
ber_str2bv( c->argv[1], 0, 1, &temp->querystr ); |
Debug( LDAP_DEBUG_TRACE, "Template:\n", 0, 0, 0 ); |
Debug( pcache_debug, "Template:\n", 0, 0, 0 ); |
Debug( LDAP_DEBUG_TRACE, " query template: %s\n", |
Debug( pcache_debug, " 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_TRACE, " attributes: \n", 0, 0, 0 ); |
qm->attr_sets[i].flags |= PC_REFERENCED; |
|
Debug( pcache_debug, " 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_TRACE, "\t%s\n", |
Debug( pcache_debug, "\t%s\n", |
attrarray[i].an_name.bv_val, 0, 0 ); |
attrarray[i].an_name.bv_val, 0, 0 ); |
} |
} |
temp++; |
temp++; |
Line 1861 pc_cf_gen( ConfigArgs *c )
|
Line 1862 pc_cf_gen( ConfigArgs *c )
|
cm->response_cb = PCACHE_RESPONSE_CB_TAIL; |
cm->response_cb = PCACHE_RESPONSE_CB_TAIL; |
|
|
} else { |
} else { |
sprintf( c->msg, "unknown specifier" ); |
snprintf( c->msg, sizeof( c->msg ), "unknown specifier" ); |
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); |
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
return 1; |
return 1; |
} |
} |
break; |
break; |
|
case PC_QUERIES: |
|
if ( c->value_int <= 0 ) { |
|
snprintf( c->msg, sizeof( c->msg ), "max queries must be positive" ); |
|
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 ); |
|
return( 1 ); |
|
} |
|
cm->max_queries = c->value_int; |
|
break; |
} |
} |
return rc; |
return rc; |
} |
} |
|
|
static int |
static int |
proxy_cache_config( |
pcache_db_config( |
BackendDB *be, |
BackendDB *be, |
const char *fname, |
const char *fname, |
int lineno, |
int lineno, |
Line 1890 proxy_cache_config(
|
Line 1899 proxy_cache_config(
|
} |
} |
|
|
static int |
static int |
proxy_cache_init( |
pcache_db_init( |
BackendDB *be |
BackendDB *be |
) |
) |
{ |
{ |
Line 1930 proxy_cache_init(
|
Line 1939 proxy_cache_init(
|
ldap_pvt_thread_mutex_init(&qm->lru_mutex); |
ldap_pvt_thread_mutex_init(&qm->lru_mutex); |
|
|
ldap_pvt_thread_mutex_init(&cm->cache_mutex); |
ldap_pvt_thread_mutex_init(&cm->cache_mutex); |
ldap_pvt_thread_mutex_init(&cm->remove_mutex); |
|
return 0; |
return 0; |
} |
} |
|
|
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, 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_CONFIG, "pcache: attr set #%d not configured but referenced.\n", i, 0, 0 ); |
|
rf++; |
|
|
|
} else { |
|
Debug( LDAP_DEBUG_CONFIG, "pcache: warning, attr set #%d not configured.\n", i, 0, 0 ); |
|
} |
|
ncf++; |
|
|
|
} else if ( !( qm->attr_sets[i].flags & PC_REFERENCED ) ) { |
|
Debug( LDAP_DEBUG_CONFIG, "pcache: attr set #%d configured but not referenced.\n", i, 0, 0 ); |
|
nrf++; |
|
} |
|
} |
|
|
|
if ( ncf || rf || nrf ) { |
|
Debug( LDAP_DEBUG_CONFIG, "pcache: warning, %d attr sets configured but not referenced.\n", nrf, 0, 0 ); |
|
Debug( LDAP_DEBUG_CONFIG, "pcache: warning, %d attr sets not configured.\n", ncf, 0, 0 ); |
|
Debug( LDAP_DEBUG_CONFIG, "pcache: %d attr sets not configured but referenced.\n", rf, 0, 0 ); |
|
|
|
if ( rf > 0 ) { |
|
return 1; |
|
} |
|
} |
|
|
/* need to inherit something from the original database... */ |
/* need to inherit something from the original database... */ |
cm->db.be_def_limit = be->be_def_limit; |
cm->db.be_def_limit = be->be_def_limit; |
Line 1963 proxy_cache_open(
|
Line 2000 proxy_cache_open(
|
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 ) ) |
{ |
{ |
Debug( LDAP_DEBUG_ANY, "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", |
Line 1977 proxy_cache_open(
|
Line 2014 proxy_cache_open(
|
} |
} |
|
|
static int |
static int |
proxy_cache_close( |
pcache_db_close( |
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 i, j, rc = 0; |
int i, rc = 0; |
|
|
/* cleanup stuff inherited from the original database... */ |
/* cleanup stuff inherited from the original database... */ |
cm->db.be_limits = NULL; |
cm->db.be_limits = NULL; |
Line 2006 proxy_cache_close(
|
Line 2043 proxy_cache_close(
|
qm->templates = NULL; |
qm->templates = NULL; |
|
|
for ( i=0; i<cm->numattrsets; i++ ) { |
for ( i=0; i<cm->numattrsets; i++ ) { |
free( qm->attr_sets[i].ID_array ); |
|
for ( j=0; j<qm->attr_sets[i].count; j++ ) { |
|
free( qm->attr_sets[i].attrs[j].an_name.bv_val ); |
|
} |
|
free( qm->attr_sets[i].attrs ); |
free( qm->attr_sets[i].attrs ); |
} |
} |
free( qm->attr_sets ); |
free( qm->attr_sets ); |
Line 2019 proxy_cache_close(
|
Line 2052 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 ); |
free( qm ); |
free( qm ); |
free( cm ); |
free( cm ); |
return rc; |
|
|
return 0; |
} |
} |
|
|
static slap_overinst proxy_cache; |
static slap_overinst pcache; |
|
|
int pcache_init() |
int pcache_initialize() |
{ |
{ |
LDAPAttributeType *at; |
LDAPAttributeType *at; |
int code; |
int code; |
const char *err; |
const char *err; |
|
struct berval debugbv = BER_BVC("pcache"); |
|
|
|
if (( code = slap_loglevel_get( &debugbv, &pcache_debug ))) |
|
return code; |
|
|
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 ) { |
Debug( LDAP_DEBUG_ANY, |
Debug( LDAP_DEBUG_ANY, |
"pcache_init: ldap_str2attributetype failed %s %s\n", |
"pcache_initialize: ldap_str2attributetype failed %s %s\n", |
ldap_scherr2str(code), err, 0 ); |
ldap_scherr2str(code), err, 0 ); |
return code; |
return code; |
} |
} |
Line 2062 int pcache_init()
|
Line 2107 int pcache_init()
|
ldap_memfree( at ); |
ldap_memfree( at ); |
if ( code ) { |
if ( code ) { |
Debug( LDAP_DEBUG_ANY, |
Debug( LDAP_DEBUG_ANY, |
"pcache_init: at_add failed %s %s\n", |
"pcache_initialize: at_add failed %s %s\n", |
scherr2str(code), err, 0 ); |
scherr2str(code), err, 0 ); |
return code; |
return code; |
} |
} |
|
|
proxy_cache.on_bi.bi_type = "pcache"; |
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; |
|
|
proxy_cache.on_bi.bi_cf_ocs = pcocs; |
pcache.on_bi.bi_cf_ocs = pcocs; |
|
|
code = config_register_schema( pccfg, pcocs ); |
code = config_register_schema( pccfg, pcocs ); |
if ( code ) return code; |
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 |
|
|