]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-meta/cache-merge.c
Fix dnPrettyNormalize mem usage
[openldap] / servers / slapd / back-meta / cache-merge.c
index 8c453e11d629563d95d409121004b01c70b658d0..e6472730ef206b2bec886d8d6015a98e3291852f 100644 (file)
 #include "../../../libraries/libldap/ldap-int.h"
 #include <sys/time.h>
 
-#ifdef LDAP_CACHING
-static int
-merge_func (
-       Backend *be,
-       Connection      *conn,
-       Operation       *op,
-       Entry   *stored_entry,
-       AttributeName   *attrs,
-       int             attrsonly,
-       LDAPControl **ctrls
-); 
-
-void
-add_func (
-       Connection      *conn,
-       Operation       *op,
-       ber_int_t       err,
-       const char      *matched,
-       const char      *text,
-       BerVarray       refs,
-       LDAPControl     **ctrls,
-       int             nentries
-); 
+static struct berval bv_queryid_any = BER_BVC( "(queryid=*)" );
 
 static Attribute* 
-add_attribute(const char* attr_name, 
+add_attribute(AttributeDescription *ad,
        Entry* e,
        BerVarray value_array
 ); 
 
 static int
-get_size_func (
-       Backend         *be,
-       Connection      *conn,
+null_response (
        Operation       *op,
-       Entry           *entry,
-       AttributeName   *attrs,
-       int             attrsonly,
-       LDAPControl     **ctrls
+       SlapReply       *rs
 ); 
 
-
-/* Two empty callback functions to avoid sending results */
-void callback_null_response(
-       Connection      *conn,
-       Operation       *o,
-       ber_tag_t       tag,
-       ber_int_t       msgid,
-       ber_int_t       err,
-       const char      *matched,
-       const char      *text,
-       BerVarray       ref,
-       const char      *resoid,
-       struct berval   *resdata,
-       struct berval   *sasldata,
-       LDAPControl     **c     )
-{
-}
-
-void callback_null_sresult(
-       Connection      *conn,
-       Operation       *o,
-       ber_int_t       err,
-       const char      *matched,
-       const char      *text,
-       BerVarray       refs,
-       LDAPControl     **c,
-       int nentries    )
-{
-}
+static int 
+normalize_values( Attribute* attr );   
 
 struct entry_info {
        int                     size_init; 
@@ -116,6 +62,7 @@ struct entry_info {
        Backend*                glue_be; 
 }; 
 
+
 int 
 get_entry_size(
        Entry* e, 
@@ -149,216 +96,116 @@ get_entry_size(
        return size;
 }
 
-
 int
-merge_entry (
-       Backend*                be,
-       Connection*             conn, 
-       Entry*                  e, 
+merge_entry(
+       Operation               *op,
+       SlapReply               *rs,
        struct berval*          query_uuid, 
-       struct exception*       result  )
+       struct exception*       result )
 {
-       struct entry_info info; 
-       struct berval normdn; 
-       struct berval prettydn; 
-
-       Operation op = {0};
-       slap_callback cb = {callback_null_response, 
-               add_func, merge_func, NULL}; 
-
-       Filter* filter = str2filter("(queryid=*)");           
-
-       dnPrettyNormal(0, &(e->e_name), &prettydn, &normdn); 
-
-       free(e->e_name.bv_val); 
-       e->e_name = prettydn; 
-       e->e_nname = normdn; 
-
-       info.entry = e; 
-       info.uuid = query_uuid; 
-       info.size_init = 0; 
-       info.size_final = 0; 
-       info.added = 0; 
-       info.glue_be = be; 
-       info.err = SUCCESS; 
-       cb.sc_private = &info;
-
-       op.o_tag = LDAP_REQ_SEARCH;
-       op.o_protocol = LDAP_VERSION3;
-       op.o_ndn = conn->c_ndn;
-       op.o_callback = &cb;
-       op.o_caching_on = 1;
-       op.o_time = slap_get_time();
-       op.o_do_not_cache = 1;
-
-       be->be_search( be, conn, &op, NULL, &(e->e_nname),
-               LDAP_SCOPE_BASE, LDAP_DEREF_NEVER, 1, 0,
-               filter, NULL, NULL, 0 );
-       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 (
-       Backend         *be_glue,
-       Connection      *conn,
-       Operation       *op,
-       Entry           *e,
-       AttributeName   *attrs,
-       int             attrsonly,
-       LDAPControl     **ctrls
-)
-{ 
-       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 */ 
-       slap_callback   *tmp = op->o_callback;  
-       struct entry_info*      info = tmp->sc_private; 
-       Filter* filter = str2filter("(queryid=*)");           
-       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; 
-
-       info->err = SUCCESS; 
-
-       be = select_backend(&entry->e_nname, 0, 0); 
-     
-       info->size_init = get_entry_size(e, 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) );
-
-               for (i=0; i < count; i++) {
-                       ber_dupbv(mod->sml_bvalues+i, a_new->a_vals+i); 
-               }
-
-               mod->sml_bvalues[count].bv_val = 0; 
-               mod->sml_bvalues[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; 
-       } 
+       struct entry_info info;
+       int             rc;
+       Modifications* modlist = NULL;
+       const char*     text = NULL;
+       BerVarray               value_array; 
+       Attribute               *uuid_attr, *attr;
+       Entry                   *e;
 
-       /* 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;
-       *modtail = mod;
-       mod->sml_next = NULL; 
-
-       if (be->be_modify(be, conn, op, &(entry->e_name),
-                               &(entry->e_nname), modhead) != 0 ) {
-               info->err = MERGE_ERR;
-               return 0; 
-       }
-       op->o_callback->sc_sendentry = get_size_func; 
-       op->o_callback->sc_sresult = NULL; 
-    
-       if (be->be_search( be, conn, op, NULL, &(entry->e_nname),
-                       LDAP_SCOPE_BASE, LDAP_DEREF_NEVER, 1, 0,
-                       filter, NULL, NULL, 0 ) != 0) {
-               info->err = GET_SIZE_ERR;
-       }
-       return 0; 
-}
+       SlapReply sreply = {REP_RESULT};
 
-void
-add_func (
-       Connection      *conn,
-       Operation       *op,
-       ber_int_t       err,
-       const char      *matched,
-       const char      *text,
-       BerVarray       refs,
-       LDAPControl **ctrls,
-       int             nentries
-)
-{
-       slap_callback   *tmp = op->o_callback;  
-       struct entry_info   *info = tmp->sc_private; 
-       Entry* entry = info->entry; 
-       struct berval* uuid = info->uuid; 
-       Backend* be; 
-       BerVarray               value_array; 
-       Entry           *e; 
-       Attribute               *a; 
+       Operation op_tmp = *op;
+       slap_callback cb;
 
-       struct timeval      time;       /* time */ 
-       long            timediff; /* time */ 
+       sreply.sr_entry = NULL; 
+       sreply.sr_nentries = 0; 
 
-       /* 
-        * new entry, construct an entry with 
-        * the projected attributes 
-        */
-       if (nentries) 
-               return; 
-       
-       be = select_backend(&entry->e_nname, 0, 0); 
-       e = (Entry*)malloc(sizeof(Entry)); 
+       e = ( Entry * ) ch_calloc( 1, sizeof( Entry )); 
 
-       ber_dupbv(&e->e_name,&entry->e_name); 
-       ber_dupbv(&e->e_nname,&entry->e_nname); 
+       dnPrettyNormal(0, &rs->sr_entry->e_name, &op_tmp.o_req_dn, &op_tmp.o_req_ndn, op->o_tmpmemctx);
+       ber_dupbv( &e->e_name, &op_tmp.o_req_dn );
+       ber_dupbv( &e->e_nname, &op_tmp.o_req_ndn );
+       sl_free( op_tmp.o_req_ndn.bv_val, op->o_tmpmemctx );
+       sl_free( op_tmp.o_req_dn.bv_val, op->o_tmpmemctx );
+       op_tmp.o_req_dn = e->e_name;
+       op_tmp.o_req_ndn = e->e_nname;
 
-       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("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; 
+                       result->rc = info.err;
+                       return 0;
+               }
+       }
 
-       info->size_final = get_entry_size(e, 0, NULL); 
-       if ( be->be_add( be, conn, op, e ) == 0 ) {
-               info->added = 1; 
-               be_entry_release_w( be, conn, op, e );
+       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_time = slap_get_time();
+       op_tmp.o_do_not_cache = 1;
+
+       op_tmp.ora_e = e;
+       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(const char* attr_name, 
+add_attribute(AttributeDescription *ad,
        Entry* e, 
        BerVarray value_array) 
 {
@@ -381,28 +228,64 @@ add_attribute(const char* attr_name,
        new_attr->a_next = NULL; 
        new_attr->a_desc = NULL;
        new_attr->a_vals = value_array; 
-       slap_str2ad(attr_name, &(new_attr->a_desc), &text);   
+       new_attr->a_desc = ad;
 
        return new_attr; 
 }
 
 static int
-get_size_func (
-       Backend         *be,
-       Connection      *conn,
+null_response (
        Operation       *op,
-       Entry           *entry,
-       AttributeName   *attrs,
-       int             attrsonly,
-       LDAPControl     **ctrls
-)
+       SlapReply       *rs )
+{
+       return 0;
+}
+
+static int 
+normalize_values( Attribute* attr ) 
 {
-       slap_callback           *tmp = op->o_callback;  
-       struct entry_info       *info = tmp->sc_private; 
-       struct exception        result; 
-
-       result.type = info->err;  
-       info->size_final = get_entry_size(entry, info->size_init, &result); 
-       return 0; 
-}  
-#endif /* LDAP_CACHING */
+       int nvals, rc, i; 
+       if (attr->a_vals == NULL) {
+               attr->a_nvals = NULL; 
+               return 0; 
+       } 
+
+       for ( nvals = 0; attr->a_vals[nvals].bv_val; nvals++ ) 
+               ; 
+
+       attr->a_nvals = (struct berval*)ch_malloc((nvals+1)*sizeof(struct berval));
+
+       if ( attr->a_desc->ad_type->sat_equality &&
+                               attr->a_desc->ad_type->sat_equality->smr_normalize )
+       {
+               for ( i = 0; i < nvals; i++ ) {
+                       rc = attr->a_desc->ad_type->sat_equality->smr_normalize(
+                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                               attr->a_desc->ad_type->sat_syntax,
+                               attr->a_desc->ad_type->sat_equality,
+                               &attr->a_vals[i], &attr->a_nvals[i], NULL );
+                       if ( rc ) {
+#ifdef NEW_LOGGING
+                               LDAP_LOG( OPERATION, DETAIL1,
+                                       "Error in normalizing attribute %s value %d (%d)\n",
+                                       attr->a_desc->ad_cname.bv_val, i, rc );
+#else
+                               Debug( LDAP_DEBUG_ANY,
+                                       "Error in normalizing attribute %s value %d (%d)\n",
+                                       attr->a_desc->ad_cname.bv_val, i, rc );
+#endif
+                               return rc;
+                       }
+               }
+       } else {
+               for ( i = 0; i < nvals; i++ ) {
+                       ber_dupbv( &attr->a_nvals[i], &attr->a_vals[i] ); 
+               }
+       }
+                       
+       attr->a_nvals[i].bv_val = NULL;
+       attr->a_nvals[i].bv_len = 0;
+
+       return LDAP_SUCCESS;
+}