attr.c revision 1.1 1 1.1 christos /* $NetBSD: attr.c,v 1.1 2021/08/14 16:05:24 christos Exp $ */
2 1.1 christos
3 1.1 christos /* OpenLDAP WiredTiger backend */
4 1.1 christos /* $OpenLDAP$ */
5 1.1 christos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1 christos *
7 1.1 christos * Copyright 2002-2021 The OpenLDAP Foundation.
8 1.1 christos * All rights reserved.
9 1.1 christos *
10 1.1 christos * Redistribution and use in source and binary forms, with or without
11 1.1 christos * modification, are permitted only as authorized by the OpenLDAP
12 1.1 christos * Public License.
13 1.1 christos *
14 1.1 christos * A copy of this license is available in the file LICENSE in the
15 1.1 christos * top-level directory of the distribution or, alternatively, at
16 1.1 christos * <http://www.OpenLDAP.org/license.html>.
17 1.1 christos */
18 1.1 christos /* ACKNOWLEDGEMENTS:
19 1.1 christos * This work was developed by HAMANO Tsukasa <hamano (at) osstech.co.jp>
20 1.1 christos * based on back-bdb for inclusion in OpenLDAP Software.
21 1.1 christos * WiredTiger is a product of MongoDB Inc.
22 1.1 christos */
23 1.1 christos
24 1.1 christos #include "back-wt.h"
25 1.1 christos #include "slap-config.h"
26 1.1 christos
27 1.1 christos /* Find the ad, return -1 if not found,
28 1.1 christos * set point for insertion if ins is non-NULL
29 1.1 christos */
30 1.1 christos int
31 1.1 christos wt_attr_slot( struct wt_info *wi, AttributeDescription *ad, int *ins )
32 1.1 christos {
33 1.1 christos unsigned base = 0, cursor = 0;
34 1.1 christos unsigned n = wi->wi_nattrs;
35 1.1 christos int val = 0;
36 1.1 christos
37 1.1 christos while ( 0 < n ) {
38 1.1 christos unsigned pivot = n >> 1;
39 1.1 christos cursor = base + pivot;
40 1.1 christos
41 1.1 christos val = SLAP_PTRCMP( ad, wi->wi_attrs[cursor]->ai_desc );
42 1.1 christos if ( val < 0 ) {
43 1.1 christos n = pivot;
44 1.1 christos } else if ( val > 0 ) {
45 1.1 christos base = cursor + 1;
46 1.1 christos n -= pivot + 1;
47 1.1 christos } else {
48 1.1 christos return cursor;
49 1.1 christos }
50 1.1 christos }
51 1.1 christos if ( ins ) {
52 1.1 christos if ( val > 0 )
53 1.1 christos ++cursor;
54 1.1 christos *ins = cursor;
55 1.1 christos }
56 1.1 christos return -1;
57 1.1 christos }
58 1.1 christos
59 1.1 christos static int
60 1.1 christos ainfo_insert( struct wt_info *wi, AttrInfo *a )
61 1.1 christos {
62 1.1 christos int x;
63 1.1 christos int i = wt_attr_slot( wi, a->ai_desc, &x );
64 1.1 christos
65 1.1 christos /* Is it a dup? */
66 1.1 christos if ( i >= 0 )
67 1.1 christos return -1;
68 1.1 christos
69 1.1 christos wi->wi_attrs = ch_realloc( wi->wi_attrs, ( wi->wi_nattrs+1 ) *
70 1.1 christos sizeof( AttrInfo * ));
71 1.1 christos if ( x < wi->wi_nattrs )
72 1.1 christos AC_MEMCPY( &wi->wi_attrs[x+1], &wi->wi_attrs[x],
73 1.1 christos ( wi->wi_nattrs - x ) * sizeof( AttrInfo *));
74 1.1 christos wi->wi_attrs[x] = a;
75 1.1 christos wi->wi_nattrs++;
76 1.1 christos return 0;
77 1.1 christos }
78 1.1 christos
79 1.1 christos AttrInfo *
80 1.1 christos wt_attr_mask(
81 1.1 christos struct wt_info *wi,
82 1.1 christos AttributeDescription *desc )
83 1.1 christos {
84 1.1 christos int i = wt_attr_slot( wi, desc, NULL );
85 1.1 christos return i < 0 ? NULL : wi->wi_attrs[i];
86 1.1 christos }
87 1.1 christos
88 1.1 christos int
89 1.1 christos wt_attr_index_config(
90 1.1 christos struct wt_info *wi,
91 1.1 christos const char *fname,
92 1.1 christos int lineno,
93 1.1 christos int argc,
94 1.1 christos char **argv,
95 1.1 christos struct config_reply_s *c_reply)
96 1.1 christos {
97 1.1 christos int rc = 0;
98 1.1 christos int i;
99 1.1 christos slap_mask_t mask;
100 1.1 christos char **attrs;
101 1.1 christos char **indexes = NULL;
102 1.1 christos
103 1.1 christos attrs = ldap_str2charray( argv[0], "," );
104 1.1 christos
105 1.1 christos if( attrs == NULL ) {
106 1.1 christos fprintf( stderr, "%s: line %d: "
107 1.1 christos "no attributes specified: %s\n",
108 1.1 christos fname, lineno, argv[0] );
109 1.1 christos return LDAP_PARAM_ERROR;
110 1.1 christos }
111 1.1 christos
112 1.1 christos if ( argc > 1 ) {
113 1.1 christos indexes = ldap_str2charray( argv[1], "," );
114 1.1 christos
115 1.1 christos if( indexes == NULL ) {
116 1.1 christos fprintf( stderr, "%s: line %d: "
117 1.1 christos "no indexes specified: %s\n",
118 1.1 christos fname, lineno, argv[1] );
119 1.1 christos rc = LDAP_PARAM_ERROR;
120 1.1 christos goto done;
121 1.1 christos }
122 1.1 christos }
123 1.1 christos
124 1.1 christos if( indexes == NULL ) {
125 1.1 christos mask = wi->wi_defaultmask;
126 1.1 christos
127 1.1 christos } else {
128 1.1 christos mask = 0;
129 1.1 christos
130 1.1 christos for ( i = 0; indexes[i] != NULL; i++ ) {
131 1.1 christos slap_mask_t index;
132 1.1 christos
133 1.1 christos rc = slap_str2index( indexes[i], &index );
134 1.1 christos
135 1.1 christos if( rc != LDAP_SUCCESS ) {
136 1.1 christos if ( c_reply )
137 1.1 christos {
138 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
139 1.1 christos "index type \"%s\" undefined", indexes[i] );
140 1.1 christos
141 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
142 1.1 christos fname, lineno, c_reply->msg );
143 1.1 christos }
144 1.1 christos rc = LDAP_PARAM_ERROR;
145 1.1 christos goto done;
146 1.1 christos }
147 1.1 christos
148 1.1 christos mask |= index;
149 1.1 christos }
150 1.1 christos }
151 1.1 christos
152 1.1 christos if( !mask ) {
153 1.1 christos if ( c_reply )
154 1.1 christos {
155 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
156 1.1 christos "no indexes selected" );
157 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
158 1.1 christos fname, lineno, c_reply->msg );
159 1.1 christos }
160 1.1 christos rc = LDAP_PARAM_ERROR;
161 1.1 christos goto done;
162 1.1 christos }
163 1.1 christos
164 1.1 christos for ( i = 0; attrs[i] != NULL; i++ ) {
165 1.1 christos AttrInfo *a;
166 1.1 christos AttributeDescription *ad;
167 1.1 christos const char *text;
168 1.1 christos #ifdef LDAP_COMP_MATCH
169 1.1 christos ComponentReference* cr = NULL;
170 1.1 christos AttrInfo *a_cr = NULL;
171 1.1 christos #endif
172 1.1 christos
173 1.1 christos if( strcasecmp( attrs[i], "default" ) == 0 ) {
174 1.1 christos wi->wi_defaultmask |= mask;
175 1.1 christos continue;
176 1.1 christos }
177 1.1 christos
178 1.1 christos #ifdef LDAP_COMP_MATCH
179 1.1 christos if ( is_component_reference( attrs[i] ) ) {
180 1.1 christos rc = extract_component_reference( attrs[i], &cr );
181 1.1 christos if ( rc != LDAP_SUCCESS ) {
182 1.1 christos if ( c_reply )
183 1.1 christos {
184 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
185 1.1 christos "index component reference\"%s\" undefined",
186 1.1 christos attrs[i] );
187 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
188 1.1 christos fname, lineno, c_reply->msg );
189 1.1 christos }
190 1.1 christos goto done;
191 1.1 christos }
192 1.1 christos cr->cr_indexmask = mask;
193 1.1 christos /*
194 1.1 christos * After extracting a component reference
195 1.1 christos * only the name of a attribute will be remaining
196 1.1 christos */
197 1.1 christos } else {
198 1.1 christos cr = NULL;
199 1.1 christos }
200 1.1 christos #endif
201 1.1 christos ad = NULL;
202 1.1 christos rc = slap_str2ad( attrs[i], &ad, &text );
203 1.1 christos
204 1.1 christos if( rc != LDAP_SUCCESS ) {
205 1.1 christos if ( c_reply )
206 1.1 christos {
207 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
208 1.1 christos "index attribute \"%s\" undefined",
209 1.1 christos attrs[i] );
210 1.1 christos
211 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
212 1.1 christos fname, lineno, c_reply->msg );
213 1.1 christos }
214 1.1 christos fail:
215 1.1 christos #ifdef LDAP_COMP_MATCH
216 1.1 christos ch_free( cr );
217 1.1 christos #endif
218 1.1 christos goto done;
219 1.1 christos }
220 1.1 christos
221 1.1 christos if( ad == slap_schema.si_ad_entryDN || slap_ad_is_binary( ad ) ) {
222 1.1 christos if (c_reply) {
223 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
224 1.1 christos "index of attribute \"%s\" disallowed", attrs[i] );
225 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
226 1.1 christos fname, lineno, c_reply->msg );
227 1.1 christos }
228 1.1 christos rc = LDAP_UNWILLING_TO_PERFORM;
229 1.1 christos goto fail;
230 1.1 christos }
231 1.1 christos
232 1.1 christos if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
233 1.1 christos ad->ad_type->sat_approx
234 1.1 christos && ad->ad_type->sat_approx->smr_indexer
235 1.1 christos && ad->ad_type->sat_approx->smr_filter ) )
236 1.1 christos {
237 1.1 christos if (c_reply) {
238 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
239 1.1 christos "approx index of attribute \"%s\" disallowed", attrs[i] );
240 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
241 1.1 christos fname, lineno, c_reply->msg );
242 1.1 christos }
243 1.1 christos rc = LDAP_INAPPROPRIATE_MATCHING;
244 1.1 christos goto fail;
245 1.1 christos }
246 1.1 christos
247 1.1 christos if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
248 1.1 christos ad->ad_type->sat_equality
249 1.1 christos && ad->ad_type->sat_equality->smr_indexer
250 1.1 christos && ad->ad_type->sat_equality->smr_filter ) )
251 1.1 christos {
252 1.1 christos if (c_reply) {
253 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
254 1.1 christos "equality index of attribute \"%s\" disallowed", attrs[i] );
255 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
256 1.1 christos fname, lineno, c_reply->msg );
257 1.1 christos }
258 1.1 christos rc = LDAP_INAPPROPRIATE_MATCHING;
259 1.1 christos goto fail;
260 1.1 christos }
261 1.1 christos
262 1.1 christos if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
263 1.1 christos ad->ad_type->sat_substr
264 1.1 christos && ad->ad_type->sat_substr->smr_indexer
265 1.1 christos && ad->ad_type->sat_substr->smr_filter ) )
266 1.1 christos {
267 1.1 christos if (c_reply) {
268 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
269 1.1 christos "substr index of attribute \"%s\" disallowed", attrs[i] );
270 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
271 1.1 christos fname, lineno, c_reply->msg );
272 1.1 christos }
273 1.1 christos rc = LDAP_INAPPROPRIATE_MATCHING;
274 1.1 christos goto fail;
275 1.1 christos }
276 1.1 christos
277 1.1 christos Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
278 1.1 christos ad->ad_cname.bv_val, mask );
279 1.1 christos
280 1.1 christos a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
281 1.1 christos
282 1.1 christos #ifdef LDAP_COMP_MATCH
283 1.1 christos a->ai_cr = NULL;
284 1.1 christos #endif
285 1.1 christos a->ai_desc = ad;
286 1.1 christos
287 1.1 christos if ( wi->wi_flags & WT_IS_OPEN ) {
288 1.1 christos a->ai_indexmask = 0;
289 1.1 christos a->ai_newmask = mask;
290 1.1 christos } else {
291 1.1 christos a->ai_indexmask = mask;
292 1.1 christos a->ai_newmask = 0;
293 1.1 christos }
294 1.1 christos
295 1.1 christos #ifdef LDAP_COMP_MATCH
296 1.1 christos if ( cr ) {
297 1.1 christos a_cr = wt_attr_mask( wi, ad );
298 1.1 christos if ( a_cr ) {
299 1.1 christos /*
300 1.1 christos * AttrInfo is already in AVL
301 1.1 christos * just add the extracted component reference
302 1.1 christos * in the AttrInfo
303 1.1 christos */
304 1.1 christos ch_free( a );
305 1.1 christos rc = insert_component_reference( cr, &a_cr->ai_cr );
306 1.1 christos if ( rc != LDAP_SUCCESS) {
307 1.1 christos fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
308 1.1 christos rc = LDAP_PARAM_ERROR;
309 1.1 christos goto fail;
310 1.1 christos }
311 1.1 christos continue;
312 1.1 christos } else {
313 1.1 christos rc = insert_component_reference( cr, &a->ai_cr );
314 1.1 christos if ( rc != LDAP_SUCCESS) {
315 1.1 christos fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
316 1.1 christos rc = LDAP_PARAM_ERROR;
317 1.1 christos ch_free( a );
318 1.1 christos goto fail;
319 1.1 christos }
320 1.1 christos }
321 1.1 christos }
322 1.1 christos #endif
323 1.1 christos rc = ainfo_insert( wi, a );
324 1.1 christos if( rc ) {
325 1.1 christos if ( wi->wi_flags & WT_IS_OPEN ) {
326 1.1 christos AttrInfo *b = wt_attr_mask( wi, ad );
327 1.1 christos /* If there is already an index defined for this attribute
328 1.1 christos * it must be replaced. Otherwise we end up with multiple
329 1.1 christos * olcIndex values for the same attribute */
330 1.1 christos if ( b->ai_indexmask & WT_INDEX_DELETING ) {
331 1.1 christos /* If we were editing this attr, reset it */
332 1.1 christos b->ai_indexmask &= ~WT_INDEX_DELETING;
333 1.1 christos /* If this is leftover from a previous add, commit it */
334 1.1 christos if ( b->ai_newmask )
335 1.1 christos b->ai_indexmask = b->ai_newmask;
336 1.1 christos b->ai_newmask = a->ai_newmask;
337 1.1 christos ch_free( a );
338 1.1 christos rc = 0;
339 1.1 christos continue;
340 1.1 christos }
341 1.1 christos }
342 1.1 christos if (c_reply) {
343 1.1 christos snprintf(c_reply->msg, sizeof(c_reply->msg),
344 1.1 christos "duplicate index definition for attr \"%s\"",
345 1.1 christos attrs[i] );
346 1.1 christos fprintf( stderr, "%s: line %d: %s\n",
347 1.1 christos fname, lineno, c_reply->msg );
348 1.1 christos }
349 1.1 christos
350 1.1 christos rc = LDAP_PARAM_ERROR;
351 1.1 christos goto done;
352 1.1 christos }
353 1.1 christos }
354 1.1 christos
355 1.1 christos done:
356 1.1 christos ldap_charray_free( attrs );
357 1.1 christos if ( indexes != NULL ) ldap_charray_free( indexes );
358 1.1 christos
359 1.1 christos return rc;
360 1.1 christos }
361 1.1 christos
362 1.1 christos void
363 1.1 christos wt_attr_info_free( AttrInfo *ai )
364 1.1 christos {
365 1.1 christos #ifdef LDAP_COMP_MATCH
366 1.1 christos free( ai->ai_cr );
367 1.1 christos #endif
368 1.1 christos free( ai );
369 1.1 christos }
370 1.1 christos
371 1.1 christos void
372 1.1 christos wt_attr_index_destroy( struct wt_info *wi )
373 1.1 christos {
374 1.1 christos int i;
375 1.1 christos
376 1.1 christos for ( i=0; i<wi->wi_nattrs; i++ )
377 1.1 christos wt_attr_info_free( wi->wi_attrs[i] );
378 1.1 christos
379 1.1 christos free( wi->wi_attrs );
380 1.1 christos }
381 1.1 christos
382 1.1 christos
383 1.1 christos
384 1.1 christos /*
385 1.1 christos * Local variables:
386 1.1 christos * indent-tabs-mode: t
387 1.1 christos * tab-width: 4
388 1.1 christos * c-basic-offset: 4
389 1.1 christos * End:
390 1.1 christos */
391