attr.c revision 1.1.1.5 1 1.1.1.3 christos /* $NetBSD: attr.c,v 1.1.1.5 2020/08/11 13:12:16 christos 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.5 christos * Copyright 2000-2020 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 christos __RCSID("$NetBSD: attr.c,v 1.1.1.5 2020/08/11 13:12:16 christos 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 1.1.1.5 christos
637 1.1.1.5 christos void mdb_ad_unwind( struct mdb_info *mdb, int prev_ads )
638 1.1.1.5 christos {
639 1.1.1.5 christos int i;
640 1.1.1.5 christos
641 1.1.1.5 christos for (i=mdb->mi_numads; i>prev_ads; i--) {
642 1.1.1.5 christos mdb->mi_adxs[mdb->mi_ads[i]->ad_index] = 0;
643 1.1.1.5 christos mdb->mi_ads[i] = NULL;
644 1.1.1.5 christos }
645 1.1.1.5 christos mdb->mi_numads = i;
646 1.1.1.5 christos }
647