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