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