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