-/* Copyright (c) 2003 by International Business Machines, Inc.
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * International Business Machines, Inc. (hereinafter called IBM) grants
- * permission under its copyrights to use, copy, modify, and distribute this
- * Software with or without fee, provided that the above copyright notice and
- * all paragraphs of this notice appear in all copies, and that the name of IBM
- * not be used in connection with the marketing of any product incorporating
- * the Software or modifications thereof, without specific, written prior
- * permission.
+ * Copyright 1999-2003 The OpenLDAP Foundation.
+ * Portions Copyright 2003 IBM Corporation.
+ * All rights reserved.
*
- * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
- * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
- * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by the Apurva Kumar for inclusion
+ * in OpenLDAP Software.
*/
#include "portable.h"
#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;
Backend* glue_be;
};
+
int
get_entry_size(
Entry* e,
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;
+ char textbuf[SLAP_TEXT_BUFLEN];
+ size_t textlen = sizeof(textbuf);
- /* 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, textbuf, textlen );
+ 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 ) {
+ syncrepl_add_glue( &op_tmp, e );
+ 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)
{
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;
+}