]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/attr.c
document option '-F'
[openldap] / servers / slapd / back-bdb / attr.c
1 /* attr.c - backend routines for dealing with attributes */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2000-2005 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20
21 #include <ac/socket.h>
22 #include <ac/string.h>
23
24 #include "slap.h"
25 #include "back-bdb.h"
26 #include "lutil.h"
27
28 /* for the cache of attribute information (which are indexed, etc.) */
29 typedef struct bdb_attrinfo {
30         AttributeDescription *ai_desc; /* attribute description cn;lang-en */
31         slap_mask_t ai_indexmask;       /* how the attr is indexed      */
32 #ifdef LDAP_COMP_MATCH
33         ComponentReference* ai_cr; /*component indexing*/
34 #endif
35 } AttrInfo;
36
37 static int
38 ainfo_type_cmp(
39         const void *v_desc,
40         const void *v_a
41 )
42 {
43         const AttributeDescription *desc = v_desc;
44         const AttrInfo  *a = v_a;
45         return SLAP_PTRCMP(desc, a->ai_desc);
46 }
47
48 static int
49 ainfo_cmp(
50         const void      *v_a,
51         const void      *v_b
52 )
53 {
54         const AttrInfo *a = v_a, *b = v_b;
55         return SLAP_PTRCMP(a->ai_desc, b->ai_desc);
56 }
57
58 #ifdef LDAP_COMP_MATCH
59 void
60 bdb_attr_comp_ref(
61         struct bdb_info *bdb,
62         AttributeDescription *desc,
63         ComponentReference** cr )
64 {
65         AttrInfo        *a;
66
67         a = (AttrInfo *) avl_find( bdb->bi_attrs, desc, ainfo_type_cmp );
68         
69         *cr = a != NULL ? a->ai_cr : 0 ;
70 }
71 void
72 bdb_attr_mask_cr(
73         struct bdb_info *bdb,
74         AttributeDescription *desc,
75         slap_mask_t *indexmask,
76         ComponentReference** cr )
77 {
78         AttrInfo        *a;
79
80         a = (AttrInfo *) avl_find( bdb->bi_attrs, desc, ainfo_type_cmp );
81         if ( a ) {
82                 *indexmask = a->ai_indexmask;
83                 *cr = a->ai_cr;
84         } else {
85                 *indexmask = 0;
86                 *cr = NULL;
87         }
88 }
89 #endif
90
91 void
92 bdb_attr_mask(
93         struct bdb_info *bdb,
94         AttributeDescription *desc,
95         slap_mask_t *indexmask )
96 {
97         AttrInfo        *a;
98
99         a = (AttrInfo *) avl_find( bdb->bi_attrs, desc, ainfo_type_cmp );
100         
101         *indexmask = a != NULL ? a->ai_indexmask : 0;
102 }
103
104 int
105 bdb_attr_index_config(
106         struct bdb_info *bdb,
107         const char              *fname,
108         int                     lineno,
109         int                     argc,
110         char            **argv )
111 {
112         int rc;
113         int     i;
114         slap_mask_t mask;
115         char **attrs;
116         char **indexes = NULL;
117
118         attrs = ldap_str2charray( argv[0], "," );
119
120         if( attrs == NULL ) {
121                 fprintf( stderr, "%s: line %d: "
122                         "no attributes specified: %s\n",
123                         fname, lineno, argv[0] );
124                 return LDAP_PARAM_ERROR;
125         }
126
127         if ( argc > 1 ) {
128                 indexes = ldap_str2charray( argv[1], "," );
129
130                 if( indexes == NULL ) {
131                         fprintf( stderr, "%s: line %d: "
132                                 "no indexes specified: %s\n",
133                                 fname, lineno, argv[1] );
134                         return LDAP_PARAM_ERROR;
135                 }
136         }
137
138         if( indexes == NULL ) {
139                 mask = bdb->bi_defaultmask;
140
141         } else {
142                 mask = 0;
143
144                 for ( i = 0; indexes[i] != NULL; i++ ) {
145                         slap_mask_t index;
146                         rc = slap_str2index( indexes[i], &index );
147
148                         if( rc != LDAP_SUCCESS ) {
149                                 fprintf( stderr, "%s: line %d: "
150                                         "index type \"%s\" undefined\n",
151                                         fname, lineno, indexes[i] );
152                                 return LDAP_PARAM_ERROR;
153                         }
154
155                         mask |= index;
156                 }
157         }
158
159         if( !mask ) {
160                 fprintf( stderr, "%s: line %d: "
161                         "no indexes selected\n",
162                         fname, lineno );
163                 return LDAP_PARAM_ERROR;
164         }
165
166         for ( i = 0; attrs[i] != NULL; i++ ) {
167                 AttrInfo        *a;
168                 AttributeDescription *ad;
169                 const char *text;
170 #ifdef LDAP_COMP_MATCH
171                 ComponentReference* cr = NULL;
172                 AttrInfo *a_cr = NULL;
173 #endif
174
175                 if( strcasecmp( attrs[i], "default" ) == 0 ) {
176                         bdb->bi_defaultmask |= mask;
177                         continue;
178                 }
179
180 #ifdef LDAP_COMP_MATCH
181                 if ( is_component_reference( attrs[i] ) ) {
182                         rc = extract_component_reference( attrs[i], &cr );
183                         if ( rc != LDAP_SUCCESS ) {
184                                 fprintf( stderr, "%s: line %d: "
185                                         "index component reference\"%s\" undefined\n",
186                                         fname, lineno, attrs[i] );
187                                 return rc;
188                         }
189                         cr->cr_indexmask = mask;
190                         /*
191                          * After extracting a component reference
192                          * only the name of a attribute will be remaining
193                          */
194                 } else {
195                         cr = NULL;
196                 }
197 #endif
198                 a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
199
200 #ifdef LDAP_COMP_MATCH
201                 a->ai_cr = NULL;
202 #endif
203                 ad = NULL;
204                 rc = slap_str2ad( attrs[i], &ad, &text );
205
206                 if( rc != LDAP_SUCCESS ) {
207                         fprintf( stderr, "%s: line %d: "
208                                 "index attribute \"%s\" undefined\n",
209                                 fname, lineno, attrs[i] );
210                         return rc;
211                 }
212
213                 if( slap_ad_is_binary( ad ) ) {
214                         fprintf( stderr, "%s: line %d: "
215                                 "index of attribute \"%s\" disallowed\n",
216                                 fname, lineno, attrs[i] );
217                         return LDAP_UNWILLING_TO_PERFORM;
218                 }
219
220                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
221                         ad->ad_type->sat_approx
222                                 && ad->ad_type->sat_approx->smr_indexer
223                                 && ad->ad_type->sat_approx->smr_filter ) )
224                 {
225                         fprintf( stderr, "%s: line %d: "
226                                 "approx index of attribute \"%s\" disallowed\n",
227                                 fname, lineno, attrs[i] );
228                         return LDAP_INAPPROPRIATE_MATCHING;
229                 }
230
231                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
232                         ad->ad_type->sat_equality
233                                 && ad->ad_type->sat_equality->smr_indexer
234                                 && ad->ad_type->sat_equality->smr_filter ) )
235                 {
236                         fprintf( stderr, "%s: line %d: "
237                                 "equality index of attribute \"%s\" disallowed\n",
238                                 fname, lineno, attrs[i] );
239                         return LDAP_INAPPROPRIATE_MATCHING;
240                 }
241
242                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
243                         ad->ad_type->sat_substr
244                                 && ad->ad_type->sat_substr->smr_indexer
245                                 && ad->ad_type->sat_substr->smr_filter ) )
246                 {
247                         fprintf( stderr, "%s: line %d: "
248                                 "substr index of attribute \"%s\" disallowed\n",
249                                 fname, lineno, attrs[i] );
250                         return LDAP_INAPPROPRIATE_MATCHING;
251                 }
252
253                 Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
254                         ad->ad_cname.bv_val, mask, 0 ); 
255
256                 a->ai_desc = ad;
257                 a->ai_indexmask = mask;
258 #ifdef LDAP_COMP_MATCH
259                 if ( cr ) {
260                         a_cr = avl_find( bdb->bi_attrs, ad, ainfo_type_cmp );
261                         if ( a_cr ) {
262                                 /*
263                                  * AttrInfo is already in AVL
264                                  * just add the extracted component reference
265                                  * in the AttrInfo
266                                  */
267                                 rc = insert_component_reference( cr, &a_cr->ai_cr );
268                                 if ( rc != LDAP_SUCCESS) {
269                                         fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
270                                         return LDAP_PARAM_ERROR;
271                                 }
272                                 continue;
273                         } else {
274                                 rc = insert_component_reference( cr, &a->ai_cr );
275                                 if ( rc != LDAP_SUCCESS) {
276                                         fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
277                                         return LDAP_PARAM_ERROR;
278                                 }
279                         }
280                 }
281 #endif
282                 rc = avl_insert( &bdb->bi_attrs, (caddr_t) a,
283                                  ainfo_cmp, avl_dup_error );
284
285                 if( rc ) {
286                         fprintf( stderr, "%s: line %d: duplicate index definition "
287                                 "for attr \"%s\" (ignored)\n",
288                                 fname, lineno, attrs[i] );
289
290                         return LDAP_PARAM_ERROR;
291                 }
292         }
293
294         ldap_charray_free( attrs );
295         if ( indexes != NULL ) ldap_charray_free( indexes );
296
297         return LDAP_SUCCESS;
298 }
299
300 static int
301 bdb_attr_index_unparser( void *v1, void *v2 )
302 {
303         AttrInfo *ai = v1;
304         BerVarray *bva = v2;
305         struct berval bv;
306         char *ptr;
307
308         slap_index2bvlen( ai->ai_indexmask, &bv );
309         if ( bv.bv_len ) {
310                 bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
311                 ptr = ch_malloc( bv.bv_len+1 );
312                 bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
313                 *bv.bv_val++ = ' ';
314                 slap_index2bv( ai->ai_indexmask, &bv );
315                 bv.bv_val = ptr;
316                 ber_bvarray_add( bva, &bv );
317         }
318 }
319
320 static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
321 static AttrInfo aidef = { &addef };
322
323 void
324 bdb_attr_index_unparse( struct bdb_info *bdb, BerVarray *bva )
325 {
326         if ( bdb->bi_defaultmask ) {
327                 aidef.ai_indexmask = bdb->bi_defaultmask;
328                 bdb_attr_index_unparser( &aidef, bva );
329         }
330         avl_apply( bdb->bi_attrs, bdb_attr_index_unparser, bva, -1, AVL_INORDER );
331 }
332
333 void
334 bdb_attr_index_destroy( Avlnode *tree )
335 {
336         avl_free( tree, free );
337 }
338