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