125450Speter/*	$NetBSD$	*/
250476Speter
325450Speter/* index.c - routines for dealing with attribute indexes */
425450Speter/* OpenLDAP: pkg/ldap/servers/slapd/back-bdb/index.c,v 1.61.2.9 2010/04/13 20:23:25 kurt Exp */
525450Speter/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
625450Speter *
725450Speter * Copyright 2000-2010 The OpenLDAP Foundation.
825450Speter * All rights reserved.
925450Speter *
1025450Speter * Redistribution and use in source and binary forms, with or without
1125450Speter * modification, are permitted only as authorized by the OpenLDAP
1225450Speter * Public License.
1325450Speter *
1425450Speter * A copy of this license is available in the file LICENSE in the
1525450Speter * top-level directory of the distribution or, alternatively, at
1625450Speter * <http://www.OpenLDAP.org/license.html>.
1725450Speter */
1825450Speter
1925450Speter#include "portable.h"
2025450Speter
2125450Speter#include <stdio.h>
2225450Speter
2325450Speter#include <ac/string.h>
2425450Speter#include <ac/socket.h>
2525450Speter
2625450Speter#include "slap.h"
2725450Speter#include "back-bdb.h"
2825450Speter#include "lutil_hash.h"
2925450Speter
3025450Speterstatic char presence_keyval[] = {0,0};
3125450Speterstatic struct berval presence_key = BER_BVC(presence_keyval);
3225450Speter
3325450SpeterAttrInfo *bdb_index_mask(
3425450Speter	Backend *be,
3525450Speter	AttributeDescription *desc,
3625450Speter	struct berval *atname )
3725450Speter{
3825450Speter	AttributeType *at;
3925450Speter	AttrInfo *ai = bdb_attr_mask( be->be_private, desc );
4025450Speter
4125450Speter	if( ai ) {
4225450Speter		*atname = desc->ad_cname;
4325450Speter		return ai;
4425450Speter	}
4525450Speter
4625450Speter	/* If there is a tagging option, did we ever index the base
4725450Speter	 * type? If so, check for mask, otherwise it's not there.
4825450Speter	 */
4925450Speter	if( slap_ad_is_tagged( desc ) && desc != desc->ad_type->sat_ad ) {
5025450Speter		/* has tagging option */
5125450Speter		ai = bdb_attr_mask( be->be_private, desc->ad_type->sat_ad );
5225450Speter
5325450Speter		if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOTAGS ) ) {
5425450Speter			*atname = desc->ad_type->sat_cname;
5525450Speter			return ai;
5625450Speter		}
5725450Speter	}
5825450Speter
5925450Speter	/* see if supertype defined mask for its subtypes */
6025450Speter	for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
6125450Speter		/* If no AD, we've never indexed this type */
6225450Speter		if ( !at->sat_ad ) continue;
6325450Speter
6425450Speter		ai = bdb_attr_mask( be->be_private, at->sat_ad );
6525450Speter
6625450Speter		if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOSUBTYPES ) ) {
6725450Speter			*atname = at->sat_cname;
6825450Speter			return ai;
6925450Speter		}
7025450Speter	}
7125450Speter
7225450Speter	return 0;
7325450Speter}
7425450Speter
7525450Speter/* This function is only called when evaluating search filters.
7625450Speter */
7725450Speterint bdb_index_param(
7825450Speter	Backend *be,
7925450Speter	AttributeDescription *desc,
8025450Speter	int ftype,
8125450Speter	DB **dbp,
8225450Speter	slap_mask_t *maskp,
8325450Speter	struct berval *prefixp )
8425450Speter{
8525450Speter	AttrInfo *ai;
8625450Speter	int rc;
8725450Speter	slap_mask_t mask, type = 0;
8825450Speter	DB *db;
8925450Speter
9025450Speter	ai = bdb_index_mask( be, desc, prefixp );
9125450Speter
9295005Simp	if ( !ai ) {
9395005Simp#ifdef BDB_MONITOR_IDX
94114164Ssam		switch ( ftype ) {
9595005Simp		case LDAP_FILTER_PRESENT:
9695005Simp			type = SLAP_INDEX_PRESENT;
9795005Simp			break;
9895005Simp		case LDAP_FILTER_APPROX:
9925450Speter			type = SLAP_INDEX_APPROX;
10095005Simp			break;
10195005Simp		case LDAP_FILTER_EQUALITY:
10295005Simp			type = SLAP_INDEX_EQUALITY;
10395005Simp			break;
10477385Sphk		case LDAP_FILTER_SUBSTRINGS:
105138593Ssam			type = SLAP_INDEX_SUBSTR;
106139494Ssam			break;
10725450Speter		default:
10825450Speter			return LDAP_INAPPROPRIATE_MATCHING;
10925450Speter		}
11025450Speter		bdb_monitor_idx_add( be->be_private, desc, type );
11125450Speter#endif /* BDB_MONITOR_IDX */
11225450Speter
11325450Speter		return LDAP_INAPPROPRIATE_MATCHING;
11425450Speter	}
11525450Speter	mask = ai->ai_indexmask;
11625450Speter
11725450Speter	rc = bdb_db_cache( be, prefixp, &db );
11825450Speter
11925450Speter	if( rc != LDAP_SUCCESS ) {
12025450Speter		return rc;
12125450Speter	}
12225450Speter
12325450Speter	switch( ftype ) {
12425450Speter	case LDAP_FILTER_PRESENT:
12525450Speter		type = SLAP_INDEX_PRESENT;
12625450Speter		if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
12725450Speter			*prefixp = presence_key;
12825450Speter			goto done;
12925450Speter		}
13025450Speter		break;
13125450Speter
13225450Speter	case LDAP_FILTER_APPROX:
13325450Speter		type = SLAP_INDEX_APPROX;
13425450Speter		if ( desc->ad_type->sat_approx ) {
13577385Sphk			if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
13625450Speter				goto done;
13725450Speter			}
13825450Speter			break;
13977385Sphk		}
14025450Speter
14125450Speter		/* Use EQUALITY rule and index for approximate match */
14225450Speter		/* fall thru */
14377385Sphk
14477385Sphk	case LDAP_FILTER_EQUALITY:
14525450Speter		type = SLAP_INDEX_EQUALITY;
14677385Sphk		if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
14725450Speter			goto done;
14825450Speter		}
14925450Speter		break;
15025450Speter
15125450Speter	case LDAP_FILTER_SUBSTRINGS:
15225450Speter		type = SLAP_INDEX_SUBSTR;
15325450Speter		if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
15425450Speter			goto done;
15525450Speter		}
15625450Speter		break;
15725450Speter
15825450Speter	default:
15925450Speter		return LDAP_OTHER;
16025450Speter	}
16125450Speter
162114232Sharti#ifdef BDB_MONITOR_IDX
163114232Sharti	bdb_monitor_idx_add( be->be_private, desc, type );
164114232Sharti#endif /* BDB_MONITOR_IDX */
165114232Sharti
166114232Sharti	return LDAP_INAPPROPRIATE_MATCHING;
167114232Sharti
168114232Shartidone:
169114232Sharti	*dbp = db;
17077217Sphk	*maskp = mask;
17177217Sphk	return LDAP_SUCCESS;
17277217Sphk}
17377217Sphk
17477217Sphkstatic int indexer(
17577217Sphk	Operation *op,
17677217Sphk	DB_TXN *txn,
17725450Speter	AttributeDescription *ad,
17885853Syar	struct berval *atname,
17925450Speter	BerVarray vals,
18025450Speter	ID id,
18177385Sphk	int opid,
18277385Sphk	slap_mask_t mask )
18325450Speter{
18477385Sphk	int rc, i;
18577385Sphk	DB *db;
18677385Sphk	struct berval *keys;
18725450Speter
18825450Speter	assert( mask != 0 );
18925450Speter
19025450Speter	rc = bdb_db_cache( op->o_bd, atname, &db );
19125450Speter
19225450Speter	if ( rc != LDAP_SUCCESS ) {
193138593Ssam		Debug( LDAP_DEBUG_ANY,
19495005Simp			"bdb_index_read: Could not open DB %s\n",
19525450Speter			atname->bv_val, 0, 0 );
19625450Speter		return LDAP_OTHER;
19725450Speter	}
19825450Speter
19925450Speter	if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
20025450Speter		rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid );
20125450Speter		if( rc ) {
20225450Speter			goto done;
20325450Speter		}
20425450Speter	}
20525450Speter
20625450Speter	if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
20725450Speter		rc = ad->ad_type->sat_equality->smr_indexer(
20825450Speter			LDAP_FILTER_EQUALITY,
20925450Speter			mask,
21025450Speter			ad->ad_type->sat_syntax,
21125450Speter			ad->ad_type->sat_equality,
21225450Speter			atname, vals, &keys, op->o_tmpmemctx );
21325450Speter
21425450Speter		if( rc == LDAP_SUCCESS && keys != NULL ) {
21525450Speter			for( i=0; keys[i].bv_val != NULL; i++ ) {
21625450Speter				rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
21725450Speter				if( rc ) {
21825450Speter					ber_bvarray_free_x( keys, op->o_tmpmemctx );
21925450Speter					goto done;
22025450Speter				}
22125450Speter			}
22225450Speter			ber_bvarray_free_x( keys, op->o_tmpmemctx );
22325450Speter		}
22425450Speter		rc = LDAP_SUCCESS;
22525450Speter	}
22625450Speter
22725450Speter	if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
22825450Speter		rc = ad->ad_type->sat_approx->smr_indexer(
22925450Speter			LDAP_FILTER_APPROX,
23025450Speter			mask,
23125450Speter			ad->ad_type->sat_syntax,
232114164Ssam			ad->ad_type->sat_approx,
23325450Speter			atname, vals, &keys, op->o_tmpmemctx );
23425450Speter
235138593Ssam		if( rc == LDAP_SUCCESS && keys != NULL ) {
23695005Simp			for( i=0; keys[i].bv_val != NULL; i++ ) {
23725450Speter				rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
23825450Speter				if( rc ) {
23925450Speter					ber_bvarray_free_x( keys, op->o_tmpmemctx );
24025450Speter					goto done;
24125450Speter				}
242138593Ssam			}
24395005Simp			ber_bvarray_free_x( keys, op->o_tmpmemctx );
24425450Speter		}
24525450Speter
24625450Speter		rc = LDAP_SUCCESS;
24725450Speter	}
24825450Speter
24925450Speter	if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
25095005Simp		rc = ad->ad_type->sat_substr->smr_indexer(
25125450Speter			LDAP_FILTER_SUBSTRINGS,
25225450Speter			mask,
25325450Speter			ad->ad_type->sat_syntax,
25425450Speter			ad->ad_type->sat_substr,
25525450Speter			atname, vals, &keys, op->o_tmpmemctx );
25625450Speter
25725450Speter		if( rc == LDAP_SUCCESS && keys != NULL ) {
25825450Speter			for( i=0; keys[i].bv_val != NULL; i++ ) {
25925450Speter				rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
26025450Speter				if( rc ) {
26125450Speter					ber_bvarray_free_x( keys, op->o_tmpmemctx );
26225450Speter					goto done;
26325450Speter				}
26425450Speter			}
26525450Speter			ber_bvarray_free_x( keys, op->o_tmpmemctx );
26625450Speter		}
26725450Speter
26825450Speter		rc = LDAP_SUCCESS;
26925450Speter	}
27025450Speter
27125450Speterdone:
27225450Speter	switch( rc ) {
27325450Speter	/* The callers all know how to deal with these results */
27425450Speter	case 0:
27525450Speter	case DB_LOCK_DEADLOCK:
27625450Speter	case DB_LOCK_NOTGRANTED:
27725450Speter		break;
27825450Speter	/* Anything else is bad news */
27925450Speter	default:
28025450Speter		rc = LDAP_OTHER;
28125450Speter	}
28225450Speter	return rc;
28325450Speter}
28425450Speter
28525450Speterstatic int index_at_values(
28625450Speter	Operation *op,
28725450Speter	DB_TXN *txn,
28825450Speter	AttributeDescription *ad,
28925450Speter	AttributeType *type,
290114164Ssam	struct berval *tags,
29125450Speter	BerVarray vals,
29225450Speter	ID id,
293114164Ssam	int opid )
294138593Ssam{
295114164Ssam	int rc;
296114164Ssam	slap_mask_t mask = 0;
297114164Ssam	int ixop = opid;
298114164Ssam	AttrInfo *ai = NULL;
299114164Ssam
300114164Ssam	if ( opid == BDB_INDEX_UPDATE_OP )
301114164Ssam		ixop = SLAP_INDEX_ADD_OP;
302114164Ssam
303114164Ssam	if( type->sat_sup ) {
304114164Ssam		/* recurse */
305114164Ssam		rc = index_at_values( op, txn, NULL,
306114164Ssam			type->sat_sup, tags,
307114164Ssam			vals, id, opid );
308114164Ssam
309114164Ssam		if( rc ) return rc;
310114164Ssam	}
311114164Ssam
312114164Ssam	/* If this type has no AD, we've never used it before */
313114164Ssam	if( type->sat_ad ) {
314114164Ssam		ai = bdb_attr_mask( op->o_bd->be_private, type->sat_ad );
315114164Ssam		if ( ai ) {
316114164Ssam#ifdef LDAP_COMP_MATCH
317114164Ssam			/* component indexing */
318114164Ssam			if ( ai->ai_cr ) {
319114164Ssam				ComponentReference *cr;
320114164Ssam				for( cr = ai->ai_cr ; cr ; cr = cr->cr_next ) {
321114164Ssam					rc = indexer( op, txn, cr->cr_ad, &type->sat_cname,
322114164Ssam						cr->cr_nvals, id, ixop,
323114164Ssam						cr->cr_indexmask );
324114164Ssam				}
325114164Ssam			}
326114164Ssam#endif
327114164Ssam			ad = type->sat_ad;
328124560Ssam			/* If we're updating the index, just set the new bits that aren't
329114164Ssam			 * already in the old mask.
330114164Ssam			 */
331114164Ssam			if ( opid == BDB_INDEX_UPDATE_OP )
332114164Ssam				mask = ai->ai_newmask & ~ai->ai_indexmask;
333114164Ssam			else
33425450Speter			/* For regular updates, if there is a newmask use it. Otherwise
33525450Speter			 * just use the old mask.
33625450Speter			 */
33725450Speter				mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
33825450Speter			if( mask ) {
33925450Speter				rc = indexer( op, txn, ad, &type->sat_cname,
34025450Speter					vals, id, ixop, mask );
34125450Speter
34225450Speter				if( rc ) return rc;
34325450Speter			}
34425450Speter		}
34525450Speter	}
34625450Speter
34725450Speter	if( tags->bv_len ) {
34825450Speter		AttributeDescription *desc;
34925450Speter
35025450Speter		desc = ad_find_tags( type, tags );
35125450Speter		if( desc ) {
35225450Speter			ai = bdb_attr_mask( op->o_bd->be_private, desc );
35325450Speter
35425450Speter			if( ai ) {
35525450Speter				if ( opid == BDB_INDEX_UPDATE_OP )
35625450Speter					mask = ai->ai_newmask & ~ai->ai_indexmask;
35725450Speter				else
35825450Speter					mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
35925450Speter				if ( mask ) {
36025450Speter					rc = indexer( op, txn, desc, &desc->ad_cname,
36125450Speter						vals, id, ixop, mask );
36225450Speter
36325450Speter					if( rc ) {
36425450Speter						return rc;
36525450Speter					}
36625450Speter				}
36725450Speter			}
36877217Sphk		}
36977217Sphk	}
37077217Sphk
37177217Sphk	return LDAP_SUCCESS;
37277217Sphk}
37377217Sphk
37477217Sphkint bdb_index_values(
37577217Sphk	Operation *op,
37677217Sphk	DB_TXN *txn,
377114164Ssam	AttributeDescription *desc,
378114164Ssam	BerVarray vals,
379114164Ssam	ID id,
380116820Ssam	int opid )
381116820Ssam{
382116820Ssam	int rc;
383114232Sharti
384114232Sharti	/* Never index ID 0 */
385114232Sharti	if ( id == 0 )
386114232Sharti		return 0;
387114232Sharti
388114232Sharti	rc = index_at_values( op, txn, desc,
389114232Sharti		desc->ad_type, &desc->ad_tags,
390114232Sharti		vals, id, opid );
391114232Sharti
39225450Speter	return rc;
39325450Speter}
39425450Speter
39525450Speter/* Get the list of which indices apply to this attr */
39625450Speterint
39725450Speterbdb_index_recset(
39825450Speter	struct bdb_info *bdb,
39925450Speter	Attribute *a,
40025450Speter	AttributeType *type,
40125450Speter	struct berval *tags,
40225450Speter	IndexRec *ir )
40325450Speter{
40425450Speter	int rc, slot;
40525450Speter	AttrList *al;
40625450Speter
40725450Speter	if( type->sat_sup ) {
40825450Speter		/* recurse */
40925450Speter		rc = bdb_index_recset( bdb, a, type->sat_sup, tags, ir );
410114164Ssam		if( rc ) return rc;
411114164Ssam	}
412114164Ssam	/* If this type has no AD, we've never used it before */
413116820Ssam	if( type->sat_ad ) {
41425450Speter		slot = bdb_attr_slot( bdb, type->sat_ad, NULL );
41525450Speter		if ( slot >= 0 ) {
41625450Speter			ir[slot].ai = bdb->bi_attrs[slot];
41725450Speter			al = ch_malloc( sizeof( AttrList ));
41825450Speter			al->attr = a;
41925450Speter			al->next = ir[slot].attrs;
42025450Speter			ir[slot].attrs = al;
42125450Speter		}
42225450Speter	}
42325450Speter	if( tags->bv_len ) {
42425450Speter		AttributeDescription *desc;
42525450Speter
42625450Speter		desc = ad_find_tags( type, tags );
42725450Speter		if( desc ) {
42877217Sphk			slot = bdb_attr_slot( bdb, desc, NULL );
42925450Speter			if ( slot >= 0 ) {
43025450Speter				ir[slot].ai = bdb->bi_attrs[slot];
431114164Ssam				al = ch_malloc( sizeof( AttrList ));
432114164Ssam				al->attr = a;
433114164Ssam				al->next = ir[slot].attrs;
43425450Speter				ir[slot].attrs = al;
43525450Speter			}
43625450Speter		}
43725450Speter	}
43825450Speter	return LDAP_SUCCESS;
43925450Speter}
44025450Speter
44125450Speter/* Apply the indices for the recset */
44225450Speterint bdb_index_recrun(
44325450Speter	Operation *op,
44425450Speter	struct bdb_info *bdb,
44577217Sphk	IndexRec *ir0,
44625450Speter	ID id,
44725450Speter	int base )
448114164Ssam{
449114164Ssam	IndexRec *ir;
450114164Ssam	AttrList *al;
45125450Speter	int i, rc = 0;
45225450Speter
45325450Speter	/* Never index ID 0 */
45425450Speter	if ( id == 0 )
45525450Speter		return 0;
45625450Speter
45725450Speter	for (i=base; i<bdb->bi_nattrs; i+=slap_tool_thread_max) {
45825450Speter		ir = ir0 + i;
45925450Speter		if ( !ir->ai ) continue;
46025450Speter		while (( al = ir->attrs )) {
46125450Speter			ir->attrs = al->next;
46277217Sphk			rc = indexer( op, NULL, ir->ai->ai_desc,
46325450Speter				&ir->ai->ai_desc->ad_type->sat_cname,
46425450Speter				al->attr->a_nvals, id, SLAP_INDEX_ADD_OP,
465114164Ssam				ir->ai->ai_indexmask );
466114164Ssam			free( al );
467114164Ssam			if ( rc ) break;
46825450Speter		}
46977217Sphk	}
47077217Sphk	return rc;
47177217Sphk}
47277217Sphk
47377217Sphkint
47477217Sphkbdb_index_entry(
47577217Sphk	Operation *op,
47677217Sphk	DB_TXN *txn,
47777217Sphk	int opid,
47877217Sphk	Entry	*e )
47977217Sphk{
48077217Sphk	int rc;
48177217Sphk	Attribute *ap = e->e_attrs;
482114164Ssam#if 0 /* ifdef LDAP_COMP_MATCH */
483114164Ssam	ComponentReference *cr_list = NULL;
484116820Ssam	ComponentReference *cr = NULL, *dupped_cr = NULL;
485114164Ssam	void* decoded_comp;
486114164Ssam	ComponentSyntaxInfo* csi_attr;
48777217Sphk	Syntax* syn;
488114232Sharti	AttributeType* at;
489114232Sharti	int i, num_attr;
490114232Sharti	void* mem_op;
491114232Sharti	struct berval value = {0};
492114232Sharti#endif
493114232Sharti
494114232Sharti	/* Never index ID 0 */
495114232Sharti	if ( e->e_id == 0 )
496114232Sharti		return 0;
497114232Sharti
498114232Sharti	Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
499114232Sharti		opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
500114232Sharti		(long) e->e_id, e->e_dn );
501114232Sharti
502114232Sharti	/* add each attribute to the indexes */
503114232Sharti	for ( ; ap != NULL; ap = ap->a_next ) {
504114232Sharti#if 0 /* ifdef LDAP_COMP_MATCH */
50525450Speter		AttrInfo *ai;
50625450Speter		/* see if attribute has components to be indexed */
50725450Speter		ai = bdb_attr_mask( op->o_bd->be_private, ap->a_desc->ad_type->sat_ad );
50895005Simp		if ( !ai ) continue;
50925450Speter		cr_list = ai->ai_cr;
51025450Speter		if ( attr_converter && cr_list ) {
51125450Speter			syn = ap->a_desc->ad_type->sat_syntax;
51225450Speter			ap->a_comp_data = op->o_tmpalloc( sizeof( ComponentData ), op->o_tmpmemctx );
51325450Speter                	/* Memory chunk(nibble) pre-allocation for decoders */
51425450Speter                	mem_op = nibble_mem_allocator ( 1024*16, 1024*4 );
51525450Speter			ap->a_comp_data->cd_mem_op = mem_op;
51625450Speter			for( cr = cr_list ; cr ; cr = cr->cr_next ) {
51725450Speter				/* count how many values in an attribute */
51825450Speter				for( num_attr=0; ap->a_vals[num_attr].bv_val != NULL; num_attr++ );
51925450Speter				num_attr++;
52025450Speter				cr->cr_nvals = (BerVarray)op->o_tmpalloc( sizeof( struct berval )*num_attr, op->o_tmpmemctx );
52125450Speter				for( i=0; ap->a_vals[i].bv_val != NULL; i++ ) {
52225450Speter					/* decoding attribute value */
52325450Speter					decoded_comp = attr_converter ( ap, syn, &ap->a_vals[i] );
52425450Speter					if ( !decoded_comp )
52525450Speter						return LDAP_DECODING_ERROR;
52625450Speter					/* extracting the referenced component */
52725450Speter					dupped_cr = dup_comp_ref( op, cr );
528114164Ssam					csi_attr = ((ComponentSyntaxInfo*)decoded_comp)->csi_comp_desc->cd_extract_i( mem_op, dupped_cr, decoded_comp );
52925450Speter					if ( !csi_attr )
53025450Speter						return LDAP_DECODING_ERROR;
53125450Speter					cr->cr_asn_type_id = csi_attr->csi_comp_desc->cd_type_id;
532114164Ssam					cr->cr_ad = (AttributeDescription*)get_component_description ( cr->cr_asn_type_id );
533114164Ssam					if ( !cr->cr_ad )
534114164Ssam						return LDAP_INVALID_SYNTAX;
535114164Ssam					at = cr->cr_ad->ad_type;
536114164Ssam					/* encoding the value of component in GSER */
537114164Ssam					rc = component_encoder( mem_op, csi_attr, &value );
538114164Ssam					if ( rc != LDAP_SUCCESS )
539114164Ssam						return LDAP_ENCODING_ERROR;
540114164Ssam					/* Normalize the encoded component values */
541114164Ssam					if ( at->sat_equality && at->sat_equality->smr_normalize ) {
542114164Ssam						rc = at->sat_equality->smr_normalize (
543114164Ssam							SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
544114164Ssam							at->sat_syntax, at->sat_equality,
545114164Ssam							&value, &cr->cr_nvals[i], op->o_tmpmemctx );
546114164Ssam					} else {
547114164Ssam						cr->cr_nvals[i] = value;
548114164Ssam					}
549114164Ssam				}
550114164Ssam				/* The end of BerVarray */
551114164Ssam				cr->cr_nvals[num_attr-1].bv_val = NULL;
552114164Ssam				cr->cr_nvals[num_attr-1].bv_len = 0;
553114164Ssam			}
554114164Ssam			op->o_tmpfree( ap->a_comp_data, op->o_tmpmemctx );
55595005Simp			nibble_mem_free ( mem_op );
55625450Speter			ap->a_comp_data = NULL;
55725450Speter		}
55825450Speter#endif
55925450Speter		rc = bdb_index_values( op, txn, ap->a_desc,
56025450Speter			ap->a_nvals, e->e_id, opid );
56125450Speter
56225450Speter		if( rc != LDAP_SUCCESS ) {
56325450Speter			Debug( LDAP_DEBUG_TRACE,
56425450Speter				"<= index_entry_%s( %ld, \"%s\" ) failure\n",
56525450Speter				opid == SLAP_INDEX_ADD_OP ? "add" : "del",
56625450Speter				(long) e->e_id, e->e_dn );
56725450Speter			return rc;
56825450Speter		}
56925450Speter	}
57025450Speter
57125450Speter	Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
57225450Speter		opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
57325450Speter		(long) e->e_id, e->e_dn );
57425450Speter
57525450Speter	return LDAP_SUCCESS;
57625450Speter}
57725450Speter