]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
d4e908da9385aaaa6ef63eed59f9615c855fa683
[openldap] / servers / slapd / back-ldbm / index.c
1 /* index.c - routines for dealing with attribute indexes */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 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_param(
75         Backend *be,
76         AttributeDescription *desc,
77         int ftype,
78         char **dbnamep,
79         slap_mask_t *maskp,
80         struct berval *prefixp )
81 {
82         slap_mask_t mask;
83         char *dbname;
84
85         mask = index_mask( be, desc, &dbname, prefixp );
86
87         if( mask == 0 ) {
88                 return LDAP_INAPPROPRIATE_MATCHING;
89         }
90
91         switch( ftype ) {
92         case LDAP_FILTER_PRESENT:
93                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
94                         goto done;
95                 }
96                 break;
97
98         case LDAP_FILTER_APPROX:
99                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
100                         goto done;
101                 }
102                 /* fall thru */
103
104         case LDAP_FILTER_EQUALITY:
105                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
106                         goto done;
107                 }
108                 break;
109
110         case LDAP_FILTER_SUBSTRINGS:
111                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
112                         goto done;
113                 }
114                 break;
115
116         default:
117                 return LDAP_OTHER;
118         }
119
120         return LDAP_INAPPROPRIATE_MATCHING;
121
122 done:
123         *dbnamep = dbname;
124         *maskp = mask;
125         return LDAP_SUCCESS;
126 }
127
128 static int indexer(
129         Backend *be,
130         char *dbname,
131         struct berval *atname,
132         BVarray vals,
133         ID id,
134         int op,
135         slap_mask_t mask )
136 {
137         int rc, i;
138         const char *text;
139     DBCache     *db;
140         AttributeDescription *ad = NULL;
141         struct berval *keys;
142
143         assert( mask );
144
145         rc = slap_bv2ad( atname, &ad, &text );
146
147         if( rc != LDAP_SUCCESS ) return rc;
148
149         db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
150         
151         if ( db == NULL ) {
152 #ifdef NEW_LOGGING
153                 LDAP_LOG(( "index", LDAP_LEVEL_ERR,
154                            "index_read: Could not open db %s%s\n",
155                            dbname, LDBM_SUFFIX ));
156 #else
157                 Debug( LDAP_DEBUG_ANY,
158                     "<= index_read NULL (could not open %s%s)\n",
159                         dbname, LDBM_SUFFIX, 0 );
160 #endif
161
162                 return LDAP_OTHER;
163         }
164
165         if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
166                 key_change( be, db, atname, id, op );
167         }
168
169         if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
170                 rc = ad->ad_type->sat_equality->smr_indexer(
171                         LDAP_FILTER_EQUALITY,
172                         mask,
173                         ad->ad_type->sat_syntax,
174                         ad->ad_type->sat_equality,
175                         atname, vals, &keys );
176
177                 if( rc == LDAP_SUCCESS && keys != NULL ) {
178                         for( i=0; keys[i].bv_val != NULL; i++ ) {
179                                 key_change( be, db, &keys[i], id, op );
180                         }
181                         bvarray_free( keys );
182                 }
183         }
184
185         if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
186                 rc = ad->ad_type->sat_approx->smr_indexer(
187                         LDAP_FILTER_APPROX,
188                         mask,
189                         ad->ad_type->sat_syntax,
190                         ad->ad_type->sat_approx,
191                         atname, vals, &keys );
192
193                 if( rc == LDAP_SUCCESS && keys != NULL ) {
194                         for( i=0; keys[i].bv_val != NULL; i++ ) {
195                                 key_change( be, db, &keys[i], id, op );
196                         }
197                         bvarray_free( keys );
198                 }
199         }
200
201         if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
202                 rc = ad->ad_type->sat_substr->smr_indexer(
203                         LDAP_FILTER_SUBSTRINGS,
204                         mask,
205                         ad->ad_type->sat_syntax,
206                         ad->ad_type->sat_substr,
207                         atname, vals, &keys );
208
209                 if( rc == LDAP_SUCCESS && keys != NULL ) {
210                         for( i=0; keys[i].bv_val != NULL; i++ ) {
211                                 key_change( be, db, &keys[i], id, op );
212                         }
213                         bvarray_free( keys );
214                 }
215         }
216
217         ldbm_cache_close( be, db );
218         return LDAP_SUCCESS;
219 }
220
221 static int index_at_values(
222         Backend *be,
223         AttributeType *type,
224         struct berval *lang,
225         BVarray vals,
226         ID id,
227         int op,
228         char ** dbnamep,
229         slap_mask_t *maskp )
230 {
231         slap_mask_t mask = 0;
232         slap_mask_t tmpmask = 0;
233
234         if( type->sat_sup ) {
235                 /* recurse */
236                 (void) index_at_values( be,
237                         type->sat_sup, lang,
238                         vals, id, op,
239                         dbnamep, &tmpmask );
240         }
241
242         /* If this type has no AD, we've never used it before */
243         if( type->sat_ad ) {
244                 attr_mask( be->be_private, type->sat_ad, &mask );
245         }
246
247         if( mask ) {
248                 *dbnamep = type->sat_cname.bv_val;
249         } else if ( tmpmask & SLAP_INDEX_AUTO_SUBTYPES ) {
250                 mask = tmpmask;
251         }
252
253         if( mask ) {
254                 indexer( be, *dbnamep,
255                         &type->sat_cname,
256                         vals, id, op,
257                         mask );
258         }
259
260         if( lang->bv_len ) {
261                 char *dbname = NULL;
262                 struct berval lname;
263                 AttributeDescription *desc;
264
265                 tmpmask = 0;
266                 lname.bv_val = NULL;
267
268                 desc = ad_find_lang(type, lang);
269                 if( desc ) {
270                         attr_mask( be->be_private, desc, &tmpmask );
271                 }
272
273                 if( tmpmask ) {
274                         dbname = desc->ad_cname.bv_val;
275                         lname = desc->ad_cname;
276                         mask = tmpmask;
277                 }
278
279                 if( dbname != NULL ) {
280                         indexer( be, dbname, &lname,
281                                 vals, id, op,
282                                 mask );
283                         if( !tmpmask ) {
284                                 ch_free( lname.bv_val );
285                         }
286                 }
287         }
288
289         return LDAP_SUCCESS;
290 }
291
292 int index_values(
293         Backend *be,
294         AttributeDescription *desc,
295         BVarray vals,
296         ID id,
297         int op )
298 {
299         char *dbname = NULL;
300         slap_mask_t mask;
301
302         (void) index_at_values( be,
303                 desc->ad_type, &desc->ad_lang,
304                 vals, id, op,
305                 &dbname, &mask );
306
307         return LDAP_SUCCESS;
308 }
309
310 int
311 index_entry(
312     Backend     *be,
313         int op,
314     Entry *e,
315         Attribute *ap )
316 {
317 #ifdef NEW_LOGGING
318         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
319                    "index_entry: %s (%s)%ld\n",
320                    op == SLAP_INDEX_ADD_OP ? "add" : "del",
321                    e->e_dn, e->e_id ));
322 #else
323         Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
324                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
325                 e->e_id, e->e_dn );
326 #endif
327
328         /* add each attribute to the indexes */
329         for ( ; ap != NULL; ap = ap->a_next ) {
330                 index_values( be, ap->a_desc, ap->a_vals, e->e_id, op );
331         }
332
333 #ifdef NEW_LOGGING
334         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
335                    "index_entry: success\n" ));
336 #else
337         Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
338             op == SLAP_INDEX_ADD_OP ? "add" : "del",
339                 e->e_id, e->e_dn );
340 #endif
341
342         return LDAP_SUCCESS;
343 }
344