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