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