Home | History | Annotate | Line # | Download | only in back-mdb
attr.c revision 1.1.1.3.6.1
      1  1.1.1.3.6.1    martin /*	$NetBSD: attr.c,v 1.1.1.3.6.1 2019/08/10 06:17:18 martin Exp $	*/
      2          1.1      tron 
      3          1.1      tron /* attr.c - backend routines for dealing with attributes */
      4          1.1      tron /* $OpenLDAP$ */
      5          1.1      tron /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6          1.1      tron  *
      7  1.1.1.3.6.1    martin  * Copyright 2000-2019 The OpenLDAP Foundation.
      8          1.1      tron  * All rights reserved.
      9          1.1      tron  *
     10          1.1      tron  * Redistribution and use in source and binary forms, with or without
     11          1.1      tron  * modification, are permitted only as authorized by the OpenLDAP
     12          1.1      tron  * Public License.
     13          1.1      tron  *
     14          1.1      tron  * A copy of this license is available in the file LICENSE in the
     15          1.1      tron  * top-level directory of the distribution or, alternatively, at
     16          1.1      tron  * <http://www.OpenLDAP.org/license.html>.
     17          1.1      tron  */
     18          1.1      tron 
     19      1.1.1.2  christos #include <sys/cdefs.h>
     20  1.1.1.3.6.1    martin __RCSID("$NetBSD: attr.c,v 1.1.1.3.6.1 2019/08/10 06:17:18 martin Exp $");
     21      1.1.1.2  christos 
     22          1.1      tron #include "portable.h"
     23          1.1      tron 
     24          1.1      tron #include <stdio.h>
     25          1.1      tron 
     26          1.1      tron #include <ac/socket.h>
     27          1.1      tron #include <ac/string.h>
     28          1.1      tron 
     29          1.1      tron #include "slap.h"
     30          1.1      tron #include "back-mdb.h"
     31          1.1      tron #include "config.h"
     32          1.1      tron #include "lutil.h"
     33          1.1      tron 
     34          1.1      tron /* Find the ad, return -1 if not found,
     35          1.1      tron  * set point for insertion if ins is non-NULL
     36          1.1      tron  */
     37          1.1      tron int
     38          1.1      tron mdb_attr_slot( struct mdb_info *mdb, AttributeDescription *ad, int *ins )
     39          1.1      tron {
     40          1.1      tron 	unsigned base = 0, cursor = 0;
     41          1.1      tron 	unsigned n = mdb->mi_nattrs;
     42          1.1      tron 	int val = 0;
     43          1.1      tron 
     44          1.1      tron 	while ( 0 < n ) {
     45          1.1      tron 		unsigned pivot = n >> 1;
     46          1.1      tron 		cursor = base + pivot;
     47          1.1      tron 
     48          1.1      tron 		val = SLAP_PTRCMP( ad, mdb->mi_attrs[cursor]->ai_desc );
     49          1.1      tron 		if ( val < 0 ) {
     50          1.1      tron 			n = pivot;
     51          1.1      tron 		} else if ( val > 0 ) {
     52          1.1      tron 			base = cursor + 1;
     53          1.1      tron 			n -= pivot + 1;
     54          1.1      tron 		} else {
     55          1.1      tron 			return cursor;
     56          1.1      tron 		}
     57          1.1      tron 	}
     58          1.1      tron 	if ( ins ) {
     59          1.1      tron 		if ( val > 0 )
     60          1.1      tron 			++cursor;
     61          1.1      tron 		*ins = cursor;
     62          1.1      tron 	}
     63          1.1      tron 	return -1;
     64          1.1      tron }
     65          1.1      tron 
     66          1.1      tron static int
     67          1.1      tron ainfo_insert( struct mdb_info *mdb, AttrInfo *a )
     68          1.1      tron {
     69          1.1      tron 	int x;
     70          1.1      tron 	int i = mdb_attr_slot( mdb, a->ai_desc, &x );
     71          1.1      tron 
     72          1.1      tron 	/* Is it a dup? */
     73          1.1      tron 	if ( i >= 0 )
     74          1.1      tron 		return -1;
     75          1.1      tron 
     76          1.1      tron 	mdb->mi_attrs = ch_realloc( mdb->mi_attrs, ( mdb->mi_nattrs+1 ) *
     77          1.1      tron 		sizeof( AttrInfo * ));
     78          1.1      tron 	if ( x < mdb->mi_nattrs )
     79          1.1      tron 		AC_MEMCPY( &mdb->mi_attrs[x+1], &mdb->mi_attrs[x],
     80          1.1      tron 			( mdb->mi_nattrs - x ) * sizeof( AttrInfo *));
     81          1.1      tron 	mdb->mi_attrs[x] = a;
     82          1.1      tron 	mdb->mi_nattrs++;
     83          1.1      tron 	return 0;
     84          1.1      tron }
     85          1.1      tron 
     86          1.1      tron AttrInfo *
     87          1.1      tron mdb_attr_mask(
     88          1.1      tron 	struct mdb_info	*mdb,
     89          1.1      tron 	AttributeDescription *desc )
     90          1.1      tron {
     91          1.1      tron 	int i = mdb_attr_slot( mdb, desc, NULL );
     92          1.1      tron 	return i < 0 ? NULL : mdb->mi_attrs[i];
     93          1.1      tron }
     94          1.1      tron 
     95          1.1      tron /* Open all un-opened index DB handles */
     96          1.1      tron int
     97          1.1      tron mdb_attr_dbs_open(
     98          1.1      tron 	BackendDB *be, MDB_txn *tx0, ConfigReply *cr )
     99          1.1      tron {
    100          1.1      tron 	struct mdb_info *mdb = (struct mdb_info *) be->be_private;
    101          1.1      tron 	MDB_txn *txn;
    102          1.1      tron 	MDB_dbi *dbis = NULL;
    103          1.1      tron 	int i, flags;
    104          1.1      tron 	int rc;
    105          1.1      tron 
    106          1.1      tron 	txn = tx0;
    107          1.1      tron 	if ( txn == NULL ) {
    108          1.1      tron 		rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
    109          1.1      tron 		if ( rc ) {
    110          1.1      tron 			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
    111          1.1      tron 				"txn_begin failed: %s (%d).",
    112          1.1      tron 				be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
    113          1.1      tron 			Debug( LDAP_DEBUG_ANY,
    114          1.1      tron 				LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
    115          1.1      tron 				cr->msg, 0, 0 );
    116          1.1      tron 			return rc;
    117          1.1      tron 		}
    118          1.1      tron 		dbis = ch_calloc( 1, mdb->mi_nattrs * sizeof(MDB_dbi) );
    119          1.1      tron 	} else {
    120          1.1      tron 		rc = 0;
    121          1.1      tron 	}
    122          1.1      tron 
    123          1.1      tron 	flags = MDB_DUPSORT|MDB_DUPFIXED|MDB_INTEGERDUP;
    124          1.1      tron 	if ( !(slapMode & SLAP_TOOL_READONLY) )
    125          1.1      tron 		flags |= MDB_CREATE;
    126          1.1      tron 
    127          1.1      tron 	for ( i=0; i<mdb->mi_nattrs; i++ ) {
    128          1.1      tron 		if ( mdb->mi_attrs[i]->ai_dbi )	/* already open */
    129          1.1      tron 			continue;
    130          1.1      tron 		rc = mdb_dbi_open( txn, mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
    131          1.1      tron 			flags, &mdb->mi_attrs[i]->ai_dbi );
    132          1.1      tron 		if ( rc ) {
    133          1.1      tron 			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
    134          1.1      tron 				"mdb_dbi_open(%s) failed: %s (%d).",
    135          1.1      tron 				be->be_suffix[0].bv_val,
    136          1.1      tron 				mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
    137          1.1      tron 				mdb_strerror(rc), rc );
    138          1.1      tron 			Debug( LDAP_DEBUG_ANY,
    139          1.1      tron 				LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
    140          1.1      tron 				cr->msg, 0, 0 );
    141          1.1      tron 			break;
    142          1.1      tron 		}
    143          1.1      tron 		/* Remember newly opened DBI handles */
    144          1.1      tron 		if ( dbis )
    145          1.1      tron 			dbis[i] = mdb->mi_attrs[i]->ai_dbi;
    146          1.1      tron 	}
    147          1.1      tron 
    148          1.1      tron 	/* Only commit if this is our txn */
    149          1.1      tron 	if ( tx0 == NULL ) {
    150          1.1      tron 		if ( !rc ) {
    151          1.1      tron 			rc = mdb_txn_commit( txn );
    152          1.1      tron 			if ( rc ) {
    153          1.1      tron 				snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
    154          1.1      tron 					"txn_commit failed: %s (%d).",
    155          1.1      tron 					be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
    156          1.1      tron 				Debug( LDAP_DEBUG_ANY,
    157          1.1      tron 					LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
    158          1.1      tron 					cr->msg, 0, 0 );
    159          1.1      tron 			}
    160          1.1      tron 		} else {
    161          1.1      tron 			mdb_txn_abort( txn );
    162          1.1      tron 		}
    163          1.1      tron 		/* Something failed, forget anything we just opened */
    164          1.1      tron 		if ( rc ) {
    165          1.1      tron 			for ( i=0; i<mdb->mi_nattrs; i++ ) {
    166          1.1      tron 				if ( dbis[i] ) {
    167          1.1      tron 					mdb->mi_attrs[i]->ai_dbi = 0;
    168          1.1      tron 					mdb->mi_attrs[i]->ai_indexmask |= MDB_INDEX_DELETING;
    169          1.1      tron 				}
    170          1.1      tron 			}
    171          1.1      tron 			mdb_attr_flush( mdb );
    172          1.1      tron 		}
    173          1.1      tron 		ch_free( dbis );
    174          1.1      tron 	}
    175          1.1      tron 
    176          1.1      tron 	return rc;
    177          1.1      tron }
    178          1.1      tron 
    179          1.1      tron void
    180          1.1      tron mdb_attr_dbs_close(
    181          1.1      tron 	struct mdb_info *mdb
    182          1.1      tron )
    183          1.1      tron {
    184          1.1      tron 	int i;
    185          1.1      tron 	for ( i=0; i<mdb->mi_nattrs; i++ )
    186          1.1      tron 		if ( mdb->mi_attrs[i]->ai_dbi ) {
    187          1.1      tron 			mdb_dbi_close( mdb->mi_dbenv, mdb->mi_attrs[i]->ai_dbi );
    188          1.1      tron 			mdb->mi_attrs[i]->ai_dbi = 0;
    189          1.1      tron 		}
    190          1.1      tron }
    191          1.1      tron 
    192          1.1      tron int
    193          1.1      tron mdb_attr_index_config(
    194          1.1      tron 	struct mdb_info	*mdb,
    195          1.1      tron 	const char		*fname,
    196          1.1      tron 	int			lineno,
    197          1.1      tron 	int			argc,
    198          1.1      tron 	char		**argv,
    199          1.1      tron 	struct		config_reply_s *c_reply)
    200          1.1      tron {
    201          1.1      tron 	int rc = 0;
    202          1.1      tron 	int	i;
    203          1.1      tron 	slap_mask_t mask;
    204          1.1      tron 	char **attrs;
    205          1.1      tron 	char **indexes = NULL;
    206          1.1      tron 
    207          1.1      tron 	attrs = ldap_str2charray( argv[0], "," );
    208          1.1      tron 
    209          1.1      tron 	if( attrs == NULL ) {
    210          1.1      tron 		fprintf( stderr, "%s: line %d: "
    211          1.1      tron 			"no attributes specified: %s\n",
    212          1.1      tron 			fname, lineno, argv[0] );
    213          1.1      tron 		return LDAP_PARAM_ERROR;
    214          1.1      tron 	}
    215          1.1      tron 
    216          1.1      tron 	if ( argc > 1 ) {
    217          1.1      tron 		indexes = ldap_str2charray( argv[1], "," );
    218          1.1      tron 
    219          1.1      tron 		if( indexes == NULL ) {
    220          1.1      tron 			fprintf( stderr, "%s: line %d: "
    221          1.1      tron 				"no indexes specified: %s\n",
    222          1.1      tron 				fname, lineno, argv[1] );
    223          1.1      tron 			rc = LDAP_PARAM_ERROR;
    224          1.1      tron 			goto done;
    225          1.1      tron 		}
    226          1.1      tron 	}
    227          1.1      tron 
    228          1.1      tron 	if( indexes == NULL ) {
    229          1.1      tron 		mask = mdb->mi_defaultmask;
    230          1.1      tron 
    231          1.1      tron 	} else {
    232          1.1      tron 		mask = 0;
    233          1.1      tron 
    234          1.1      tron 		for ( i = 0; indexes[i] != NULL; i++ ) {
    235          1.1      tron 			slap_mask_t index;
    236          1.1      tron 			rc = slap_str2index( indexes[i], &index );
    237          1.1      tron 
    238          1.1      tron 			if( rc != LDAP_SUCCESS ) {
    239          1.1      tron 				if ( c_reply )
    240          1.1      tron 				{
    241          1.1      tron 					snprintf(c_reply->msg, sizeof(c_reply->msg),
    242          1.1      tron 						"index type \"%s\" undefined", indexes[i] );
    243          1.1      tron 
    244          1.1      tron 					fprintf( stderr, "%s: line %d: %s\n",
    245          1.1      tron 						fname, lineno, c_reply->msg );
    246          1.1      tron 				}
    247          1.1      tron 				rc = LDAP_PARAM_ERROR;
    248          1.1      tron 				goto done;
    249          1.1      tron 			}
    250          1.1      tron 
    251          1.1      tron 			mask |= index;
    252          1.1      tron 		}
    253          1.1      tron 	}
    254          1.1      tron 
    255          1.1      tron 	if( !mask ) {
    256          1.1      tron 		if ( c_reply )
    257          1.1      tron 		{
    258          1.1      tron 			snprintf(c_reply->msg, sizeof(c_reply->msg),
    259          1.1      tron 				"no indexes selected" );
    260          1.1      tron 			fprintf( stderr, "%s: line %d: %s\n",
    261          1.1      tron 				fname, lineno, c_reply->msg );
    262          1.1      tron 		}
    263          1.1      tron 		rc = LDAP_PARAM_ERROR;
    264          1.1      tron 		goto done;
    265          1.1      tron 	}
    266          1.1      tron 
    267          1.1      tron 	for ( i = 0; attrs[i] != NULL; i++ ) {
    268          1.1      tron 		AttrInfo	*a;
    269          1.1      tron 		AttributeDescription *ad;
    270          1.1      tron 		const char *text;
    271          1.1      tron #ifdef LDAP_COMP_MATCH
    272          1.1      tron 		ComponentReference* cr = NULL;
    273          1.1      tron 		AttrInfo *a_cr = NULL;
    274          1.1      tron #endif
    275          1.1      tron 
    276          1.1      tron 		if( strcasecmp( attrs[i], "default" ) == 0 ) {
    277          1.1      tron 			mdb->mi_defaultmask |= mask;
    278          1.1      tron 			continue;
    279          1.1      tron 		}
    280          1.1      tron 
    281          1.1      tron #ifdef LDAP_COMP_MATCH
    282          1.1      tron 		if ( is_component_reference( attrs[i] ) ) {
    283          1.1      tron 			rc = extract_component_reference( attrs[i], &cr );
    284          1.1      tron 			if ( rc != LDAP_SUCCESS ) {
    285          1.1      tron 				if ( c_reply )
    286          1.1      tron 				{
    287          1.1      tron 					snprintf(c_reply->msg, sizeof(c_reply->msg),
    288          1.1      tron 						"index component reference\"%s\" undefined",
    289          1.1      tron 						attrs[i] );
    290          1.1      tron 					fprintf( stderr, "%s: line %d: %s\n",
    291          1.1      tron 						fname, lineno, c_reply->msg );
    292          1.1      tron 				}
    293          1.1      tron 				goto done;
    294          1.1      tron 			}
    295          1.1      tron 			cr->cr_indexmask = mask;
    296          1.1      tron 			/*
    297          1.1      tron 			 * After extracting a component reference
    298          1.1      tron 			 * only the name of a attribute will be remaining
    299          1.1      tron 			 */
    300          1.1      tron 		} else {
    301          1.1      tron 			cr = NULL;
    302          1.1      tron 		}
    303          1.1      tron #endif
    304          1.1      tron 		ad = NULL;
    305          1.1      tron 		rc = slap_str2ad( attrs[i], &ad, &text );
    306          1.1      tron 
    307          1.1      tron 		if( rc != LDAP_SUCCESS ) {
    308          1.1      tron 			if ( c_reply )
    309          1.1      tron 			{
    310          1.1      tron 				snprintf(c_reply->msg, sizeof(c_reply->msg),
    311          1.1      tron 					"index attribute \"%s\" undefined",
    312          1.1      tron 					attrs[i] );
    313          1.1      tron 
    314          1.1      tron 				fprintf( stderr, "%s: line %d: %s\n",
    315          1.1      tron 					fname, lineno, c_reply->msg );
    316          1.1      tron 			}
    317          1.1      tron 			goto done;
    318          1.1      tron 		}
    319          1.1      tron 
    320          1.1      tron 		if( ad == slap_schema.si_ad_entryDN || slap_ad_is_binary( ad ) ) {
    321          1.1      tron 			if (c_reply) {
    322          1.1      tron 				snprintf(c_reply->msg, sizeof(c_reply->msg),
    323          1.1      tron 					"index of attribute \"%s\" disallowed", attrs[i] );
    324          1.1      tron 				fprintf( stderr, "%s: line %d: %s\n",
    325          1.1      tron 					fname, lineno, c_reply->msg );
    326          1.1      tron 			}
    327          1.1      tron 			rc = LDAP_UNWILLING_TO_PERFORM;
    328          1.1      tron 			goto done;
    329          1.1      tron 		}
    330          1.1      tron 
    331          1.1      tron 		if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
    332          1.1      tron 			ad->ad_type->sat_approx
    333          1.1      tron 				&& ad->ad_type->sat_approx->smr_indexer
    334          1.1      tron 				&& ad->ad_type->sat_approx->smr_filter ) )
    335          1.1      tron 		{
    336          1.1      tron 			if (c_reply) {
    337          1.1      tron 				snprintf(c_reply->msg, sizeof(c_reply->msg),
    338          1.1      tron 					"approx index of attribute \"%s\" disallowed", attrs[i] );
    339          1.1      tron 				fprintf( stderr, "%s: line %d: %s\n",
    340          1.1      tron 					fname, lineno, c_reply->msg );
    341          1.1      tron 			}
    342          1.1      tron 			rc = LDAP_INAPPROPRIATE_MATCHING;
    343          1.1      tron 			goto done;
    344          1.1      tron 		}
    345          1.1      tron 
    346          1.1      tron 		if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
    347          1.1      tron 			ad->ad_type->sat_equality
    348          1.1      tron 				&& ad->ad_type->sat_equality->smr_indexer
    349          1.1      tron 				&& ad->ad_type->sat_equality->smr_filter ) )
    350          1.1      tron 		{
    351          1.1      tron 			if (c_reply) {
    352          1.1      tron 				snprintf(c_reply->msg, sizeof(c_reply->msg),
    353          1.1      tron 					"equality index of attribute \"%s\" disallowed", attrs[i] );
    354          1.1      tron 				fprintf( stderr, "%s: line %d: %s\n",
    355          1.1      tron 					fname, lineno, c_reply->msg );
    356          1.1      tron 			}
    357          1.1      tron 			rc = LDAP_INAPPROPRIATE_MATCHING;
    358          1.1      tron 			goto done;
    359          1.1      tron 		}
    360          1.1      tron 
    361          1.1      tron 		if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
    362          1.1      tron 			ad->ad_type->sat_substr
    363          1.1      tron 				&& ad->ad_type->sat_substr->smr_indexer
    364          1.1      tron 				&& ad->ad_type->sat_substr->smr_filter ) )
    365          1.1      tron 		{
    366          1.1      tron 			if (c_reply) {
    367          1.1      tron 				snprintf(c_reply->msg, sizeof(c_reply->msg),
    368          1.1      tron 					"substr index of attribute \"%s\" disallowed", attrs[i] );
    369          1.1      tron 				fprintf( stderr, "%s: line %d: %s\n",
    370          1.1      tron 					fname, lineno, c_reply->msg );
    371          1.1      tron 			}
    372          1.1      tron 			rc = LDAP_INAPPROPRIATE_MATCHING;
    373          1.1      tron 			goto done;
    374          1.1      tron 		}
    375          1.1      tron 
    376          1.1      tron 		Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
    377          1.1      tron 			ad->ad_cname.bv_val, mask, 0 );
    378          1.1      tron 
    379          1.1      tron 		a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
    380          1.1      tron 
    381          1.1      tron #ifdef LDAP_COMP_MATCH
    382          1.1      tron 		a->ai_cr = NULL;
    383          1.1      tron #endif
    384          1.1      tron 		a->ai_cursor = NULL;
    385          1.1      tron 		a->ai_flist = NULL;
    386          1.1      tron 		a->ai_clist = NULL;
    387          1.1      tron 		a->ai_root = NULL;
    388          1.1      tron 		a->ai_desc = ad;
    389          1.1      tron 		a->ai_dbi = 0;
    390          1.1      tron 
    391          1.1      tron 		if ( mdb->mi_flags & MDB_IS_OPEN ) {
    392          1.1      tron 			a->ai_indexmask = 0;
    393          1.1      tron 			a->ai_newmask = mask;
    394          1.1      tron 		} else {
    395          1.1      tron 			a->ai_indexmask = mask;
    396          1.1      tron 			a->ai_newmask = 0;
    397          1.1      tron 		}
    398          1.1      tron 
    399          1.1      tron #ifdef LDAP_COMP_MATCH
    400          1.1      tron 		if ( cr ) {
    401          1.1      tron 			a_cr = mdb_attr_mask( mdb, ad );
    402          1.1      tron 			if ( a_cr ) {
    403          1.1      tron 				/*
    404          1.1      tron 				 * AttrInfo is already in AVL
    405          1.1      tron 				 * just add the extracted component reference
    406          1.1      tron 				 * in the AttrInfo
    407          1.1      tron 				 */
    408          1.1      tron 				rc = insert_component_reference( cr, &a_cr->ai_cr );
    409          1.1      tron 				if ( rc != LDAP_SUCCESS) {
    410          1.1      tron 					fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
    411          1.1      tron 					rc = LDAP_PARAM_ERROR;
    412          1.1      tron 					goto done;
    413          1.1      tron 				}
    414          1.1      tron 				continue;
    415          1.1      tron 			} else {
    416          1.1      tron 				rc = insert_component_reference( cr, &a->ai_cr );
    417          1.1      tron 				if ( rc != LDAP_SUCCESS) {
    418          1.1      tron 					fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
    419          1.1      tron 					rc = LDAP_PARAM_ERROR;
    420          1.1      tron 					goto done;
    421          1.1      tron 				}
    422          1.1      tron 			}
    423          1.1      tron 		}
    424          1.1      tron #endif
    425          1.1      tron 		rc = ainfo_insert( mdb, a );
    426          1.1      tron 		if( rc ) {
    427          1.1      tron 			if ( mdb->mi_flags & MDB_IS_OPEN ) {
    428          1.1      tron 				AttrInfo *b = mdb_attr_mask( mdb, ad );
    429          1.1      tron 				/* If there is already an index defined for this attribute
    430          1.1      tron 				 * it must be replaced. Otherwise we end up with multiple
    431          1.1      tron 				 * olcIndex values for the same attribute */
    432          1.1      tron 				if ( b->ai_indexmask & MDB_INDEX_DELETING ) {
    433          1.1      tron 					/* If we were editing this attr, reset it */
    434          1.1      tron 					b->ai_indexmask &= ~MDB_INDEX_DELETING;
    435          1.1      tron 					/* If this is leftover from a previous add, commit it */
    436          1.1      tron 					if ( b->ai_newmask )
    437          1.1      tron 						b->ai_indexmask = b->ai_newmask;
    438          1.1      tron 					b->ai_newmask = a->ai_newmask;
    439          1.1      tron 					ch_free( a );
    440          1.1      tron 					rc = 0;
    441          1.1      tron 					continue;
    442          1.1      tron 				}
    443          1.1      tron 			}
    444          1.1      tron 			if (c_reply) {
    445          1.1      tron 				snprintf(c_reply->msg, sizeof(c_reply->msg),
    446          1.1      tron 					"duplicate index definition for attr \"%s\"",
    447          1.1      tron 					attrs[i] );
    448          1.1      tron 				fprintf( stderr, "%s: line %d: %s\n",
    449          1.1      tron 					fname, lineno, c_reply->msg );
    450          1.1      tron 			}
    451          1.1      tron 
    452          1.1      tron 			rc = LDAP_PARAM_ERROR;
    453          1.1      tron 			goto done;
    454          1.1      tron 		}
    455          1.1      tron 	}
    456          1.1      tron 
    457          1.1      tron done:
    458          1.1      tron 	ldap_charray_free( attrs );
    459          1.1      tron 	if ( indexes != NULL ) ldap_charray_free( indexes );
    460          1.1      tron 
    461          1.1      tron 	return rc;
    462          1.1      tron }
    463          1.1      tron 
    464          1.1      tron static int
    465          1.1      tron mdb_attr_index_unparser( void *v1, void *v2 )
    466          1.1      tron {
    467          1.1      tron 	AttrInfo *ai = v1;
    468          1.1      tron 	BerVarray *bva = v2;
    469          1.1      tron 	struct berval bv;
    470          1.1      tron 	char *ptr;
    471          1.1      tron 
    472          1.1      tron 	slap_index2bvlen( ai->ai_indexmask, &bv );
    473          1.1      tron 	if ( bv.bv_len ) {
    474          1.1      tron 		bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
    475          1.1      tron 		ptr = ch_malloc( bv.bv_len+1 );
    476          1.1      tron 		bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
    477          1.1      tron 		*bv.bv_val++ = ' ';
    478          1.1      tron 		slap_index2bv( ai->ai_indexmask, &bv );
    479          1.1      tron 		bv.bv_val = ptr;
    480          1.1      tron 		ber_bvarray_add( bva, &bv );
    481          1.1      tron 	}
    482          1.1      tron 	return 0;
    483          1.1      tron }
    484          1.1      tron 
    485          1.1      tron static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
    486          1.1      tron static AttrInfo aidef = { &addef };
    487          1.1      tron 
    488          1.1      tron void
    489          1.1      tron mdb_attr_index_unparse( struct mdb_info *mdb, BerVarray *bva )
    490          1.1      tron {
    491          1.1      tron 	int i;
    492          1.1      tron 
    493          1.1      tron 	if ( mdb->mi_defaultmask ) {
    494          1.1      tron 		aidef.ai_indexmask = mdb->mi_defaultmask;
    495          1.1      tron 		mdb_attr_index_unparser( &aidef, bva );
    496          1.1      tron 	}
    497          1.1      tron 	for ( i=0; i<mdb->mi_nattrs; i++ )
    498          1.1      tron 		mdb_attr_index_unparser( mdb->mi_attrs[i], bva );
    499          1.1      tron }
    500          1.1      tron 
    501          1.1      tron void
    502          1.1      tron mdb_attr_info_free( AttrInfo *ai )
    503          1.1      tron {
    504          1.1      tron #ifdef LDAP_COMP_MATCH
    505          1.1      tron 	free( ai->ai_cr );
    506          1.1      tron #endif
    507          1.1      tron 	free( ai );
    508          1.1      tron }
    509          1.1      tron 
    510          1.1      tron void
    511          1.1      tron mdb_attr_index_destroy( struct mdb_info *mdb )
    512          1.1      tron {
    513          1.1      tron 	int i;
    514          1.1      tron 
    515          1.1      tron 	for ( i=0; i<mdb->mi_nattrs; i++ )
    516          1.1      tron 		mdb_attr_info_free( mdb->mi_attrs[i] );
    517          1.1      tron 
    518          1.1      tron 	free( mdb->mi_attrs );
    519          1.1      tron }
    520          1.1      tron 
    521          1.1      tron void mdb_attr_index_free( struct mdb_info *mdb, AttributeDescription *ad )
    522          1.1      tron {
    523          1.1      tron 	int i;
    524          1.1      tron 
    525          1.1      tron 	i = mdb_attr_slot( mdb, ad, NULL );
    526          1.1      tron 	if ( i >= 0 ) {
    527          1.1      tron 		mdb_attr_info_free( mdb->mi_attrs[i] );
    528          1.1      tron 		mdb->mi_nattrs--;
    529          1.1      tron 		for (; i<mdb->mi_nattrs; i++)
    530          1.1      tron 			mdb->mi_attrs[i] = mdb->mi_attrs[i+1];
    531          1.1      tron 	}
    532          1.1      tron }
    533          1.1      tron 
    534          1.1      tron void mdb_attr_flush( struct mdb_info *mdb )
    535          1.1      tron {
    536          1.1      tron 	int i;
    537          1.1      tron 
    538          1.1      tron 	for ( i=0; i<mdb->mi_nattrs; i++ ) {
    539          1.1      tron 		if ( mdb->mi_attrs[i]->ai_indexmask & MDB_INDEX_DELETING ) {
    540          1.1      tron 			int j;
    541          1.1      tron 			mdb_attr_info_free( mdb->mi_attrs[i] );
    542          1.1      tron 			mdb->mi_nattrs--;
    543          1.1      tron 			for (j=i; j<mdb->mi_nattrs; j++)
    544          1.1      tron 				mdb->mi_attrs[j] = mdb->mi_attrs[j+1];
    545          1.1      tron 			i--;
    546          1.1      tron 		}
    547          1.1      tron 	}
    548          1.1      tron }
    549          1.1      tron 
    550          1.1      tron int mdb_ad_read( struct mdb_info *mdb, MDB_txn *txn )
    551          1.1      tron {
    552          1.1      tron 	int i, rc;
    553          1.1      tron 	MDB_cursor *mc;
    554          1.1      tron 	MDB_val key, data;
    555          1.1      tron 	struct berval bdata;
    556          1.1      tron 	const char *text;
    557          1.1      tron 	AttributeDescription *ad;
    558          1.1      tron 
    559          1.1      tron 	rc = mdb_cursor_open( txn, mdb->mi_ad2id, &mc );
    560          1.1      tron 	if ( rc ) {
    561          1.1      tron 		Debug( LDAP_DEBUG_ANY,
    562          1.1      tron 			"mdb_ad_read: cursor_open failed %s(%d)\n",
    563          1.1      tron 			mdb_strerror(rc), rc, 0);
    564          1.1      tron 		return rc;
    565          1.1      tron 	}
    566          1.1      tron 
    567          1.1      tron 	/* our array is 1-based, an index of 0 means no data */
    568          1.1      tron 	i = mdb->mi_numads+1;
    569          1.1      tron 	key.mv_size = sizeof(int);
    570          1.1      tron 	key.mv_data = &i;
    571          1.1      tron 
    572          1.1      tron 	rc = mdb_cursor_get( mc, &key, &data, MDB_SET );
    573          1.1      tron 
    574          1.1      tron 	while ( rc == MDB_SUCCESS ) {
    575          1.1      tron 		bdata.bv_len = data.mv_size;
    576          1.1      tron 		bdata.bv_val = data.mv_data;
    577          1.1      tron 		ad = NULL;
    578          1.1      tron 		rc = slap_bv2ad( &bdata, &ad, &text );
    579          1.1      tron 		if ( rc ) {
    580          1.1      tron 			rc = slap_bv2undef_ad( &bdata, &mdb->mi_ads[i], &text, 0 );
    581          1.1      tron 		} else {
    582          1.1      tron 			if ( ad->ad_index >= MDB_MAXADS ) {
    583          1.1      tron 				Debug( LDAP_DEBUG_ANY,
    584          1.1      tron 					"mdb_adb_read: too many AttributeDescriptions in use\n",
    585          1.1      tron 					0, 0, 0 );
    586          1.1      tron 				return LDAP_OTHER;
    587          1.1      tron 			}
    588          1.1      tron 			mdb->mi_adxs[ad->ad_index] = i;
    589          1.1      tron 			mdb->mi_ads[i] = ad;
    590          1.1      tron 		}
    591          1.1      tron 		i++;
    592          1.1      tron 		rc = mdb_cursor_get( mc, &key, &data, MDB_NEXT );
    593          1.1      tron 	}
    594          1.1      tron 	mdb->mi_numads = i-1;
    595          1.1      tron 
    596          1.1      tron done:
    597          1.1      tron 	if ( rc == MDB_NOTFOUND )
    598          1.1      tron 		rc = 0;
    599          1.1      tron 
    600          1.1      tron 	mdb_cursor_close( mc );
    601          1.1      tron 
    602          1.1      tron 	return rc;
    603          1.1      tron }
    604          1.1      tron 
    605          1.1      tron int mdb_ad_get( struct mdb_info *mdb, MDB_txn *txn, AttributeDescription *ad )
    606          1.1      tron {
    607          1.1      tron 	int i, rc;
    608          1.1      tron 	MDB_val key, val;
    609          1.1      tron 
    610          1.1      tron 	rc = mdb_ad_read( mdb, txn );
    611          1.1      tron 	if (rc)
    612          1.1      tron 		return rc;
    613          1.1      tron 
    614          1.1      tron 	if ( mdb->mi_adxs[ad->ad_index] )
    615          1.1      tron 		return 0;
    616          1.1      tron 
    617          1.1      tron 	i = mdb->mi_numads+1;
    618          1.1      tron 	key.mv_size = sizeof(int);
    619          1.1      tron 	key.mv_data = &i;
    620          1.1      tron 	val.mv_size = ad->ad_cname.bv_len;
    621          1.1      tron 	val.mv_data = ad->ad_cname.bv_val;
    622          1.1      tron 
    623          1.1      tron 	rc = mdb_put( txn, mdb->mi_ad2id, &key, &val, 0 );
    624          1.1      tron 	if ( rc == MDB_SUCCESS ) {
    625          1.1      tron 		mdb->mi_adxs[ad->ad_index] = i;
    626          1.1      tron 		mdb->mi_ads[i] = ad;
    627      1.1.1.2  christos 		mdb->mi_numads = i;
    628          1.1      tron 	} else {
    629          1.1      tron 		Debug( LDAP_DEBUG_ANY,
    630          1.1      tron 			"mdb_ad_get: mdb_put failed %s(%d)\n",
    631          1.1      tron 			mdb_strerror(rc), rc, 0);
    632          1.1      tron 	}
    633          1.1      tron 
    634          1.1      tron 	return rc;
    635          1.1      tron }
    636