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