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