Commit d1131664 authored by Jong Hyuk Choi's avatar Jong Hyuk Choi
Browse files

Proxy cache patch (by Jong, Apurva, & Kurt)

1. Glueing patch for proxy cache
2. test script update to avoid schema checking voilations (attributes set)
3. configuration patch for proxy cache
parent 264f690c
......@@ -2882,6 +2882,7 @@ BUILD_LDAP=no
BUILD_LDBM=no
BUILD_META=no
BUILD_MONITOR=no
BUILD_CACHE=no
BUILD_NULL=no
BUILD_PASSWD=no
BUILD_PERL=no
......@@ -23271,6 +23272,10 @@ EOF
BUILD_SLAPD=yes
BUILD_META=yes
BUILD_REWRITE=yes
if test $ol_enable_ldbm = yes -o \
$ol_enable_bdb = yes ; then
BUILD_CACHE=yes
fi
if test "$ol_with_meta_module" != static ; then
cat >> confdefs.h <<\EOF
#define SLAPD_META_DYNAMIC 1
......@@ -23740,6 +23745,7 @@ s%@BUILD_LDAP@%$BUILD_LDAP%g
s%@BUILD_LDBM@%$BUILD_LDBM%g
s%@BUILD_META@%$BUILD_META%g
s%@BUILD_MONITOR@%$BUILD_MONITOR%g
s%@BUILD_CACHE@%$BUILD_CACHE%g
s%@BUILD_NULL@%$BUILD_NULL%g
s%@BUILD_PASSWD@%$BUILD_PASSWD%g
s%@BUILD_PERL@%$BUILD_PERL%g
......
......@@ -541,6 +541,7 @@ BUILD_LDAP=no
BUILD_LDBM=no
BUILD_META=no
BUILD_MONITOR=no
BUILD_CACHE=no
BUILD_NULL=no
BUILD_PASSWD=no
BUILD_PERL=no
......@@ -2663,6 +2664,10 @@ if test "$ol_enable_meta" != no ; then
BUILD_SLAPD=yes
BUILD_META=yes
BUILD_REWRITE=yes
if test $ol_enable_ldbm = yes -o \
$ol_enable_bdb = yes ; then
BUILD_CACHE=yes
fi
if test "$ol_with_meta_module" != static ; then
AC_DEFINE(SLAPD_META_DYNAMIC,1,
[define to support dynamic LDAP Metadirectory backend])
......@@ -2832,6 +2837,7 @@ AC_SUBST(BUILD_SLAPD)
AC_SUBST(BUILD_LDBM)
AC_SUBST(BUILD_META)
AC_SUBST(BUILD_MONITOR)
AC_SUBST(BUILD_CACHE)
AC_SUBST(BUILD_NULL)
AC_SUBST(BUILD_PASSWD)
AC_SUBST(BUILD_PERL)
......
......@@ -38,30 +38,12 @@
static struct berval bv_queryid_any = BER_BVC( "(queryid=*)" );
static int
merge_func (
Operation *op,
SlapReply *rs
);
static void
add_func (
Operation *op,
SlapReply *rs
);
static Attribute*
add_attribute(AttributeDescription *ad,
Entry* e,
BerVarray value_array
);
static int
get_size_func (
Operation *op,
SlapReply *rs
);
static int
null_response (
Operation *op,
......@@ -116,25 +98,6 @@ get_entry_size(
return size;
}
/* quick hack: call the right callback */
static int
add_merge_func( Operation *op, SlapReply *rs )
{
switch ( rs->sr_type ) {
case REP_SEARCH:
merge_func( op, rs );
break;
case REP_RESULT:
add_func( op, rs );
break;
default:
assert( 0 );
}
return 0;
}
int
merge_entry(
Operation *op,
......@@ -143,277 +106,101 @@ merge_entry(
struct exception* result )
{
struct entry_info info;
struct berval normdn;
struct berval prettydn;
int rc;
Modifications* modlist = NULL;
const char* text = NULL;
BerVarray value_array;
Attribute *uuid_attr, *attr;
Entry *e;
SlapReply sreply = {REP_RESULT};
Operation op_tmp = *op;
slap_callback cb = { add_merge_func, NULL };
slap_callback cb;
Filter* filter = str2filter( bv_queryid_any.bv_val );
sreply.sr_entry = NULL;
sreply.sr_nentries = 0;
dnPrettyNormal(0, &rs->sr_entry->e_name, &prettydn, &normdn,
op->o_tmpmemctx);
free(rs->sr_entry->e_name.bv_val);
rs->sr_entry->e_name = prettydn;
if (rs->sr_entry->e_nname.bv_val) free(rs->sr_entry->e_nname.bv_val);
rs->sr_entry->e_nname = normdn;
info.entry = rs->sr_entry;
info.uuid = query_uuid;
info.size_init = 0;
info.size_final = 0;
info.added = 0;
info.glue_be = op->o_bd;
info.err = SUCCESS;
cb.sc_private = &info;
op_tmp.o_tag = LDAP_REQ_SEARCH;
op_tmp.o_protocol = LDAP_VERSION3;
op_tmp.o_callback = &cb;
op_tmp.o_caching_on = 1;
op_tmp.o_time = slap_get_time();
op_tmp.o_do_not_cache = 1;
op_tmp.o_req_dn = rs->sr_entry->e_name;
op_tmp.o_req_ndn = rs->sr_entry->e_nname;
op_tmp.ors_scope = LDAP_SCOPE_BASE;
op_tmp.ors_deref = LDAP_DEREF_NEVER;
op_tmp.ors_slimit = 1;
op_tmp.ors_tlimit = 0;
op_tmp.ors_filter = filter;
op_tmp.ors_filterstr = bv_queryid_any;
op_tmp.ors_attrs = NULL;
op_tmp.ors_attrsonly = 0;
op->o_bd->be_search( &op_tmp, &sreply );
result->type = info.err;
if ( result->type == SUCCESS )
result->rc = info.added;
else
result->rc = 0;
return ( info.size_final - info.size_init );
}
static int
merge_func (
Operation *op,
SlapReply *rs
)
{
Backend *be;
char *new_attr_name;
Attribute *a_new, *a;
int i = 0;
int rc = 0;
int count;
struct timeval time; /* time */
long timediff; /* time */
struct entry_info *info = op->o_callback->sc_private;
Filter *filter = str2filter( bv_queryid_any.bv_val );
Entry *entry = info->entry;
struct berval *uuid = info->uuid;
Modifications *modhead = NULL;
Modifications *mod;
Modifications **modtail = &modhead;
AttributeDescription *a_new_desc;
const char *text = NULL;
Operation op_tmp = *op;
SlapReply sreply = {REP_RESULT};
SlapReply sreply1 = {REP_RESULT};
info->err = SUCCESS;
be = select_backend(&entry->e_nname, 0, 0);
info->size_init = get_entry_size(rs->sr_entry, 0, 0);
a_new = entry->e_attrs;
while (a_new != NULL) {
a_new_desc = a_new->a_desc;
mod = (Modifications *) malloc( sizeof(Modifications) );
mod->sml_op = LDAP_MOD_REPLACE;
ber_dupbv(&mod->sml_type, &a_new_desc->ad_cname);
for ( count = 0; a_new->a_vals[count].bv_val; count++ )
;
mod->sml_bvalues = (struct berval*) malloc(
(count+1) * sizeof( struct berval) );
mod->sml_nvalues = (struct berval*) malloc(
(count+1) * sizeof( struct berval) );
for ( i = 0; i < count; i++ ) {
ber_dupbv(mod->sml_bvalues+i, a_new->a_vals+i);
if ( a_new->a_desc->ad_type->sat_equality &&
a_new->a_desc->ad_type->sat_equality->smr_normalize ) {
rc = a_new->a_desc->ad_type->sat_equality->smr_normalize(
0,
a_new->a_desc->ad_type->sat_syntax,
a_new->a_desc->ad_type->sat_equality,
a_new->a_vals+i, mod->sml_nvalues+i, NULL );
if (rc) {
info->err = MERGE_ERR;
return 0;
}
}
else {
ber_dupbv( mod->sml_nvalues+i, a_new->a_vals+i );
}
}
mod->sml_bvalues[count].bv_val = 0;
mod->sml_bvalues[count].bv_len = 0;
mod->sml_nvalues[count].bv_val = 0;
mod->sml_nvalues[count].bv_len = 0;
mod->sml_desc = NULL;
slap_bv2ad(&mod->sml_type, &mod->sml_desc, &text);
mod->sml_next =NULL;
*modtail = mod;
modtail = &mod->sml_next;
a_new = a_new->a_next;
}
/* add query UUID to queryid attribute */
mod = (Modifications *) ch_malloc( sizeof(Modifications) );
mod->sml_op = LDAP_MOD_ADD;
mod->sml_desc = slap_schema.si_ad_queryid;
ber_dupbv(&mod->sml_type, &mod->sml_desc->ad_cname);
mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
ber_dupbv( mod->sml_bvalues, uuid );
mod->sml_bvalues[1].bv_val = NULL;
mod->sml_bvalues[1].bv_len = 0;
mod->sml_nvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
ber_dupbv( mod->sml_nvalues, uuid );
mod->sml_nvalues[1].bv_val = NULL;
mod->sml_nvalues[1].bv_len = 0;
*modtail = mod;
mod->sml_next = NULL;
/* Apply changes */
op_tmp.o_req_dn = entry->e_name;
op_tmp.o_req_ndn = entry->e_nname;
op_tmp.orm_modlist = modhead;
op_tmp.o_callback->sc_response = null_response;
/* FIXME: &op_tmp ??? */
if (be->be_modify(&op_tmp, &sreply ) != 0 ) {
/* FIXME: cleanup ? */
info->err = MERGE_ERR;
goto cleanup;
}
/* compute the size of the entry */
op_tmp.o_callback->sc_response = get_size_func;
op_tmp.ors_scope = LDAP_SCOPE_BASE;
op_tmp.ors_deref = LDAP_DEREF_NEVER;
op_tmp.ors_slimit = 1;
op_tmp.ors_tlimit = 0;
op_tmp.ors_filter = filter;
op_tmp.ors_filterstr = bv_queryid_any;
op_tmp.ors_attrs = NULL;
op_tmp.ors_attrsonly = 0;
sreply1.sr_entry = NULL;
sreply1.sr_nentries = 0;
if (be->be_search( &op_tmp, &sreply1 ) != 0) {
info->err = GET_SIZE_ERR;
}
cleanup:;
if ( modhead != NULL) {
slap_mods_free( modhead );
}
return 0;
}
static void
add_func (
Operation *op,
SlapReply *rs
)
{
struct entry_info *info = op->o_callback->sc_private;
Entry *entry = info->entry;
struct berval *uuid = info->uuid;
Backend *be;
BerVarray value_array;
Entry *e;
Attribute *a, *attr;
int i,j;
SlapReply sreply = {REP_RESULT};
struct timeval time; /* time */
long timediff; /* time */
Operation op_tmp = *op;
/*
* new entry, construct an entry with
* the projected attributes
*/
if (rs->sr_nentries) {
return;
}
op_tmp.o_callback->sc_response = null_response;
be = select_backend(&entry->e_nname, 0, 0);
e = (Entry*)malloc(sizeof(Entry));
ber_dupbv(&e->e_name,&entry->e_name);
ber_dupbv(&e->e_nname,&entry->e_nname);
e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
dnPrettyNormal(0, &rs->sr_entry->e_name, &e->e_name, &e->e_nname, op->o_tmpmemctx);
e->e_private = 0;
e->e_attrs = 0;
e->e_bv.bv_val = 0;
e->e_private = NULL;
e->e_attrs = NULL;
e->e_bv.bv_val = NULL;
/* add queryid attribute */
value_array = (struct berval *)malloc(2 * sizeof( struct berval) );
ber_dupbv(value_array, uuid);
ber_dupbv(value_array, query_uuid);
value_array[1].bv_val = NULL;
value_array[1].bv_len = 0;
a = add_attribute(slap_schema.si_ad_queryid,
e, value_array);
uuid_attr = add_attribute(slap_schema.si_ad_queryid, e, value_array);
/* append the attribute list from the fetched entry */
a->a_next = entry->e_attrs;
entry->e_attrs = NULL;
uuid_attr->a_next = rs->sr_entry->e_attrs;
rs->sr_entry->e_attrs = NULL;
for ( attr = e->e_attrs; attr; attr = attr->a_next ) {
if ( normalize_values( attr ) ) {
info->err = MERGE_ERR;
return;
info.err = MERGE_ERR;
result->rc = info.err;
return 0;
}
}
info->size_final = get_entry_size( e, 0, NULL );
info.entry = e;
info.uuid = query_uuid;
info.size_init = get_entry_size( rs->sr_entry, 0, 0 );
info.size_final = 0;
info.added = 0;
info.glue_be = op->o_bd;
info.err = SUCCESS;
cb.sc_private = &info;
cb.sc_response = null_response;
op_tmp.o_tag = LDAP_REQ_ADD;
op_tmp.o_protocol = LDAP_VERSION3;
op_tmp.o_callback = &cb;
op_tmp.o_caching_on = 0;
op_tmp.o_time = slap_get_time();
op_tmp.o_do_not_cache = 1;
op_tmp.o_bd = be;
op_tmp.ora_e = e;
if ( be->be_add( &op_tmp, &sreply ) == 0 ) {
info->added = 1;
be_entry_release_w( &op_tmp, e );
op_tmp.o_req_dn = e->e_name;
op_tmp.o_req_ndn = e->e_nname;
rc = op->o_bd->be_add( &op_tmp, &sreply );
if ( rc != LDAP_SUCCESS ) {
if ( rc == LDAP_ALREADY_EXISTS ) {
slap_entry2mods( e, &modlist, &text );
op_tmp.o_tag = LDAP_REQ_MODIFY;
op_tmp.orm_modlist = modlist;
op_tmp.o_req_dn = e->e_name;
op_tmp.o_req_ndn = e->e_nname;
rc = op->o_bd->be_modify( &op_tmp, &sreply );
result->rc = info.added;
} else if ( rc == LDAP_REFERRAL ||
rc == LDAP_NO_SUCH_OBJECT ) {
slap_entry2mods( e, &modlist, &text );
syncrepl_add_glue( NULL, NULL, &op_tmp, e, modlist, 0, NULL, NULL );
result->rc = info.added;
} else {
result->rc = 0;
}
if ( modlist != NULL ) slap_mods_free( modlist );
} else {
info->err = MERGE_ERR;
info.size_init = 0;
result->rc = info.added;
be_entry_release_w( &op_tmp, e );
}
if ( result->rc )
info.size_final = get_entry_size( e, info.size_init, result );
else
info.size_final = info.size_init;
return ( info.size_final - info.size_init );
}
static Attribute*
add_attribute(AttributeDescription *ad,
......@@ -444,25 +231,6 @@ add_attribute(AttributeDescription *ad,
return new_attr;
}
static int
get_size_func (
Operation *op,
SlapReply *rs
)
{
struct entry_info *info = op->o_callback->sc_private;
struct exception result;
if ( rs->sr_type == REP_SEARCH ) {
result.type = info->err;
info->size_final = get_entry_size(rs->sr_entry,
info->size_init, &result);
}
return 0;
}
static int
null_response (
Operation *op,
......
......@@ -80,7 +80,7 @@ remove_query_data (
op_tmp.o_callback = &cb;
op_tmp.o_time = slap_get_time();
op_tmp.o_do_not_cache = 1;
op_tmp.o_caching_on = 1;
op_tmp.o_caching_on = 0;
op_tmp.o_req_dn = op->o_bd->be_suffix[0];
op_tmp.o_req_ndn = op->o_bd->be_nsuffix[0];
......
......@@ -274,8 +274,8 @@ meta_back_cache_search(
int num_entries = 0;
int curr_limit;
int fattr_cnt=0;
int oc_attr_absent = 1;
struct exception result[1];
Filter* filter = str2filter(op->ors_filterstr.bv_val);
......@@ -284,10 +284,12 @@ meta_back_cache_search(
cb.sc_private = op->o_bd;
if (op->ors_attrs) {
for ( count=0; op->ors_attrs[ count ].an_name.bv_val; count++ )
;
attrs = (AttributeName*)malloc( ( count + 1 ) *
sizeof(AttributeName));
for ( count=0; op->ors_attrs[ count ].an_name.bv_val; count++ ) {
if ( op->ors_attrs[count].an_desc == slap_schema.si_ad_objectClass )
oc_attr_absent = 0;
}
attrs = (AttributeName*)malloc( ( count + 1 + oc_attr_absent )
*sizeof(AttributeName));
for ( count=0; op->ors_attrs[ count ].an_name.bv_val; count++ ) {
ber_dupbv(&attrs[ count ].an_name,
&op->ors_attrs[ count ].an_name);
......@@ -297,7 +299,6 @@ meta_back_cache_search(
attrs[ count ].an_name.bv_len = 0;
}
result->type = SUCCESS;
result->rc = 0;
ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
......@@ -364,6 +365,15 @@ meta_back_cache_search(
}
}
if ( attrs && oc_attr_absent ) {
for ( count = 0; attrs[count].an_name.bv_val; count++) ;
attrs[ count ].an_name.bv_val = "objectClass";
attrs[ count ].an_name.bv_len = strlen( "objectClass" );
attrs[ count ].an_desc = slap_schema.si_ad_objectClass;
attrs[ count + 1 ].an_name.bv_val = NULL;
attrs[ count + 1 ].an_name.bv_len = 0;
}
if (answerable) {
Operation op_tmp;
......@@ -394,7 +404,7 @@ meta_back_cache_search(
op_tmp.o_req_dn = cachebase;
op_tmp.o_req_ndn = ncachebase;
op_tmp.o_caching_on = 1;
op_tmp.o_caching_on = 0;
op_tmp.o_callback = &cb;
li->glue_be->be_search(&op_tmp, rs);
......@@ -614,7 +624,7 @@ meta_back_cache_search(
*/
msgid[ i ] = ldap_search( lsc->ld, mbase, realscope,
mapped_filter, mapped_attrs,
op->ors_attrsonly );
op->ors_attrsonly );
if ( msgid[ i ] == -1 ) {
result->type = CONN_ERR;
......@@ -660,8 +670,7 @@ meta_back_cache_search(
Debug( LDAP_DEBUG_ANY, "QUERY CACHEABLE\n", 0, 0, 0 );
#endif /* !NEW_LOGGING */
op_tmp.o_bd = li->glue_be;
uuid = cache_entries(&op_tmp, rs, entry_array,
cm, result);
uuid = cache_entries(&op_tmp, rs, entry_array, cm, result);
#ifdef NEW_LOGGING
LDAP_LOG( BACK_META, DETAIL1,
"Added query %s UUID %s ENTRIES %d\n",
......@@ -681,6 +690,19 @@ meta_back_cache_search(
goto Catch;
filter = 0;
attrs = 0;
/* FIXME : launch do_syncrepl() threads around here
*
* entryUUID and entryCSN need also to be requested by :
*/
/*
msgid[ i ] = ldap_search( lsc->ld, mbase, realscope,
mapped_filter, mapped_attrs, op->ors_attrsonly );
*/
/* Also, mbase, realscope, mapped_filter, mapped_attrs need
* be managed as arrays. Each element needs to be retained by this point.
*/
} else {
#ifdef NEW_LOGGING
LDAP_LOG( BACK_META, DETAIL1,
......@@ -824,11 +846,15 @@ meta_create_entry (
struct berval a, mapped;
Entry* ent;
BerElement ber = *e->lm_ber;
Attribute *attr, **attrp;
struct berval dummy = { 0, NULL };
struct berval *bv, bdn;
Attribute *attr, *soc_attr, **attrp;
struct berval dummy = { 0, NULL };
struct berval *bv, bdn;
const char *text;
char* ename = NULL;
char* ename = NULL;
struct berval sc;
char* textbuf;
size_t textlen;
if ( ber_scanf( &ber, "{m{", &bdn ) == LBER_ERROR ) {
result->type = CREATE_ENTRY_ERR;
return NULL;
......@@ -930,9 +956,13 @@ meta_create_entry (
if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
|| attr->a_vals == NULL ) {