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