]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
924f16ee5764160ab38b320d5cd67e196e658edd
[openldap] / servers / slapd / back-ldbm / index.c
1 /* index.c - routines for dealing with attribute indexes */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/string.h>
13 #include <ac/socket.h>
14
15 #include "slap.h"
16 #include "back-ldbm.h"
17
18 static slap_mask_t index_mask(
19         Backend *be,
20         AttributeDescription *desc,
21         char **dbname,
22         struct berval *atname )
23 {
24         AttributeType *at;
25         slap_mask_t mask = 0;
26
27         attr_mask( be->be_private, desc, &mask );
28
29         if( mask ) {
30                 *atname = desc->ad_cname;
31                 *dbname = desc->ad_cname.bv_val;
32                 return mask;
33         }
34
35         /* If there is a language tag, did we ever index the base
36          * type? If so, check for mask, otherwise it's not there.
37          */
38         if( slap_ad_is_lang( desc ) && desc != desc->ad_type->sat_ad ) {
39                 /* has language tag */
40                 attr_mask( be->be_private, desc->ad_type->sat_ad, &mask );
41
42                 if( !( mask & SLAP_INDEX_NOLANG ) ) {
43                         *atname = desc->ad_type->sat_cname;
44                         *dbname = desc->ad_type->sat_cname.bv_val;
45                         return mask;
46                 }
47         }
48
49         /* see if supertype defined mask for its subtypes */
50         for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
51                 /* If no AD, we've never indexed this type */
52                 if (!at->sat_ad)
53                         continue;
54                 
55                 attr_mask( be->be_private, at->sat_ad, &mask );
56
57                 if( mask & SLAP_INDEX_AUTO_SUBTYPES ) {
58                         *atname = desc->ad_type->sat_cname;
59                         *dbname = at->sat_cname.bv_val;
60                         return mask;
61                 }
62                 if( !( mask & SLAP_INDEX_NOSUBTYPES ) ) {
63                         *atname = at->sat_cname;
64                         *dbname = at->sat_cname.bv_val;
65                         return mask;
66                 }
67
68                 if( mask ) break;
69         }
70
71         return 0;
72 }
73
74 int index_is_indexed(
75         Backend *be,
76         AttributeDescription *desc )
77 {
78         int rc;
79         slap_mask_t mask;
80         char *dbname;
81         struct berval prefix;
82
83         mask = index_mask( be, desc, &dbname, &prefix );
84
85         if( mask == 0 ) {
86                 return LDAP_INAPPROPRIATE_MATCHING;
87         }
88
89         return LDAP_SUCCESS;
90 }
91
92 int index_param(
93         Backend *be,
94         AttributeDescription *desc,
95         int ftype,
96         char **dbnamep,
97         slap_mask_t *maskp,
98         struct berval *prefixp )
99 {
100         slap_mask_t mask;
101         char *dbname;
102
103         mask = index_mask( be, desc, &dbname, prefixp );
104
105         if( mask == 0 ) {
106                 return LDAP_INAPPROPRIATE_MATCHING;
107         }
108
109         switch( ftype ) {
110         case LDAP_FILTER_PRESENT:
111                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
112                         goto done;
113                 }
114                 break;
115
116         case LDAP_FILTER_APPROX:
117                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
118                         goto done;
119                 }
120                 /* fall thru */
121
122         case LDAP_FILTER_EQUALITY:
123                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
124                         goto done;
125                 }
126                 break;
127
128         case LDAP_FILTER_SUBSTRINGS:
129                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
130                         goto done;
131                 }
132                 break;
133
134         default:
135                 return LDAP_OTHER;
136         }
137
138         return LDAP_INAPPROPRIATE_MATCHING;
139
140 done:
141         *dbnamep = dbname;
142         *maskp = mask;
143         return LDAP_SUCCESS;
144 }
145
146 static int indexer(
147         Backend *be,
148         char *dbname,
149         struct berval *atname,
150         BVarray vals,
151         ID id,
152         int op,
153         slap_mask_t mask )
154 {
155         int rc, i;
156         const char *text;
157     DBCache     *db;
158         AttributeDescription *ad = NULL;
159         struct berval *keys;
160
161         assert( mask );
162
163         rc = slap_bv2ad( atname, &ad, &text );
164
165         if( rc != LDAP_SUCCESS ) return rc;
166
167         db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
168         
169         if ( db == NULL ) {
170 #ifdef NEW_LOGGING
171                 LDAP_LOG(( "index", LDAP_LEVEL_ERR,
172                            "index_read: Could not open db %s%s\n",
173                            dbname, LDBM_SUFFIX ));
174 #else
175                 Debug( LDAP_DEBUG_ANY,
176                     "<= index_read NULL (could not open %s%s)\n",
177                         dbname, LDBM_SUFFIX, 0 );
178 #endif
179
180                 return LDAP_OTHER;
181         }
182
183         if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
184                 key_change( be, db, atname, id, op );
185         }
186
187         if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
188                 rc = ad->ad_type->sat_equality->smr_indexer(
189                         LDAP_FILTER_EQUALITY,
190                         mask,
191                         ad->ad_type->sat_syntax,
192                         ad->ad_type->sat_equality,
193                         atname, vals, &keys );
194
195                 if( rc == LDAP_SUCCESS && keys != NULL ) {
196                         for( i=0; keys[i].bv_val != NULL; i++ ) {
197                                 key_change( be, db, &keys[i], id, op );
198                         }
199                         bvarray_free( keys );
200                 }
201         }
202
203         if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
204                 rc = ad->ad_type->sat_approx->smr_indexer(
205                         LDAP_FILTER_APPROX,
206                         mask,
207                         ad->ad_type->sat_syntax,
208                         ad->ad_type->sat_approx,
209                         atname, vals, &keys );
210
211                 if( rc == LDAP_SUCCESS && keys != NULL ) {
212                         for( i=0; keys[i].bv_val != NULL; i++ ) {
213                                 key_change( be, db, &keys[i], id, op );
214                         }
215                         bvarray_free( keys );
216                 }
217         }
218
219         if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
220                 rc = ad->ad_type->sat_substr->smr_indexer(
221                         LDAP_FILTER_SUBSTRINGS,
222                         mask,
223                         ad->ad_type->sat_syntax,
224                         ad->ad_type->sat_substr,
225                         atname, vals, &keys );
226
227                 if( rc == LDAP_SUCCESS && keys != NULL ) {
228                         for( i=0; keys[i].bv_val != NULL; i++ ) {
229                                 key_change( be, db, &keys[i], id, op );
230                         }
231                         bvarray_free( keys );
232                 }
233         }
234
235         ldbm_cache_close( be, db );
236         return LDAP_SUCCESS;
237 }
238
239 static int index_at_values(
240         Backend *be,
241         AttributeType *type,
242         struct berval *lang,
243         BVarray vals,
244         ID id,
245         int op,
246         char ** dbnamep,
247         slap_mask_t *maskp )
248 {
249         slap_mask_t mask = 0;
250         slap_mask_t tmpmask = 0;
251
252         if( type->sat_sup ) {
253                 /* recurse */
254                 (void) index_at_values( be,
255                         type->sat_sup, lang,
256                         vals, id, op,
257                         dbnamep, &tmpmask );
258         }
259
260         /* If this type has no AD, we've never used it before */
261         if( type->sat_ad ) {
262                 attr_mask( be->be_private, type->sat_ad, &mask );
263         }
264
265         if( mask ) {
266                 *dbnamep = type->sat_cname.bv_val;
267         } else if ( tmpmask & SLAP_INDEX_AUTO_SUBTYPES ) {
268                 mask = tmpmask;
269         }
270
271         if( mask ) {
272                 indexer( be, *dbnamep,
273                         &type->sat_cname,
274                         vals, id, op,
275                         mask );
276         }
277
278         if( lang->bv_len ) {
279                 char *dbname = NULL;
280                 struct berval lname;
281                 AttributeDescription *desc;
282
283                 tmpmask = 0;
284                 lname.bv_val = NULL;
285
286                 desc = ad_find_lang(type, lang);
287                 if( desc ) {
288                         attr_mask( be->be_private, desc, &tmpmask );
289                 }
290
291                 if( tmpmask ) {
292                         dbname = desc->ad_cname.bv_val;
293                         lname = desc->ad_cname;
294                         mask = tmpmask;
295                 }
296
297                 if( dbname != NULL ) {
298                         indexer( be, dbname, &lname,
299                                 vals, id, op,
300                                 mask );
301                         if( !tmpmask ) {
302                                 ch_free( lname.bv_val );
303                         }
304                 }
305         }
306
307         return LDAP_SUCCESS;
308 }
309
310 int index_values(
311         Backend *be,
312         AttributeDescription *desc,
313         BVarray vals,
314         ID id,
315         int op )
316 {
317         char *dbname = NULL;
318         slap_mask_t mask;
319
320         (void) index_at_values( be,
321                 desc->ad_type, &desc->ad_lang,
322                 vals, id, op,
323                 &dbname, &mask );
324
325         return LDAP_SUCCESS;
326 }
327
328 int
329 index_entry(
330     Backend     *be,
331         int op,
332     Entry *e,
333         Attribute *ap )
334 {
335 #ifdef NEW_LOGGING
336         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
337                    "index_entry: %s (%s)%ld\n",
338                    op == SLAP_INDEX_ADD_OP ? "add" : "del",
339                    e->e_dn, e->e_id ));
340 #else
341         Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
342                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
343                 e->e_id, e->e_dn );
344 #endif
345
346         /* add each attribute to the indexes */
347         for ( ; ap != NULL; ap = ap->a_next ) {
348                 index_values( be, ap->a_desc, ap->a_vals, e->e_id, op );
349         }
350
351 #ifdef NEW_LOGGING
352         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
353                    "index_entry: success\n" ));
354 #else
355         Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
356             op == SLAP_INDEX_ADD_OP ? "add" : "del",
357                 e->e_id, e->e_dn );
358 #endif
359
360         return LDAP_SUCCESS;
361 }
362