]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/index.c
Use EntryInfo navigation for search scope checks
[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         Operation *op,
146         DB_TXN *txn,
147         AttributeDescription *ad,
148         struct berval *atname,
149         BerVarray vals,
150         ID id,
151         int opid,
152         slap_mask_t mask )
153 {
154         int rc, i;
155         const char *text;
156         DB *db;
157         struct berval *keys;
158         void *mark;
159
160         assert( mask );
161
162         rc = bdb_db_cache( op->o_bd, txn, atname->bv_val, &db );
163         
164         if ( rc != LDAP_SUCCESS ) {
165 #ifdef NEW_LOGGING
166                 LDAP_LOG( INDEX, ERR, 
167                         "bdb_index_read: Could not open DB %s\n",
168                         atname->bv_val, 0, 0 );
169 #else
170                 Debug( LDAP_DEBUG_ANY,
171                         "bdb_index_read: Could not open DB %s\n",
172                         atname->bv_val, 0, 0 );
173 #endif
174                 return LDAP_OTHER;
175         }
176
177         mark = sl_mark(op->o_tmpmemctx);
178
179         if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
180                 rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid );
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, op->o_tmpmemctx );
193
194                 if( rc == LDAP_SUCCESS && keys != NULL ) {
195                         for( i=0; keys[i].bv_val != NULL; i++ ) {
196                                 rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
197                                 if( rc ) {
198                                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
199                                         goto done;
200                                 }
201                         }
202                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
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, op->o_tmpmemctx );
214
215                 if( rc == LDAP_SUCCESS && keys != NULL ) {
216                         for( i=0; keys[i].bv_val != NULL; i++ ) {
217                                 rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
218                                 if( rc ) {
219                                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
220                                         goto done;
221                                 }
222                         }
223                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
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, op->o_tmpmemctx );
236
237                 if( rc == LDAP_SUCCESS && keys != NULL ) {
238                         for( i=0; keys[i].bv_val != NULL; i++ ) {
239                                 bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
240                                 if( rc ) {
241                                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
242                                         goto done;
243                                 }
244                         }
245                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
246                 }
247
248                 rc = LDAP_SUCCESS;
249         }
250
251 done:
252         sl_release( mark, op->o_tmpmemctx );
253         return rc;
254 }
255
256 static int index_at_values(
257         Operation *op,
258         DB_TXN *txn,
259         AttributeDescription *ad,
260         AttributeType *type,
261         struct berval *tags,
262         BerVarray vals,
263         ID id,
264         int opid )
265 {
266         int rc;
267         slap_mask_t mask = 0;
268
269         if( type->sat_sup ) {
270                 /* recurse */
271                 rc = index_at_values( op, txn, NULL,
272                         type->sat_sup, tags,
273                         vals, id, opid );
274
275                 if( rc ) return rc;
276         }
277
278         /* If this type has no AD, we've never used it before */
279         if( type->sat_ad ) {
280                 bdb_attr_mask( op->o_bd->be_private, type->sat_ad, &mask );
281                 ad = type->sat_ad;
282         }
283
284         if( mask ) {
285                 rc = indexer( op, txn, ad, &type->sat_cname,
286                         vals, id, opid,
287                         mask );
288
289                 if( rc ) return rc;
290         }
291
292         if( tags->bv_len ) {
293                 AttributeDescription *desc;
294
295                 mask = 0;
296
297                 desc = ad_find_tags( type, tags );
298                 if( desc ) {
299                         bdb_attr_mask( op->o_bd->be_private, desc, &mask );
300                 }
301
302                 if( mask ) {
303                         rc = indexer( op, txn, desc, &desc->ad_cname,
304                                 vals, id, opid,
305                                 mask );
306
307                         if( rc ) {
308                                 return rc;
309                         }
310                 }
311         }
312
313         return LDAP_SUCCESS;
314 }
315
316 int bdb_index_values(
317         Operation *op,
318         DB_TXN *txn,
319         AttributeDescription *desc,
320         BerVarray vals,
321         ID id,
322         int opid )
323 {
324         int rc;
325
326         rc = index_at_values( op, txn, desc,
327                 desc->ad_type, &desc->ad_tags,
328                 vals, id, opid );
329
330         return rc;
331 }
332
333 int
334 bdb_index_entry(
335         Operation *op,
336         DB_TXN *txn,
337         int opid,
338         Entry   *e )
339 {
340         int rc;
341         Attribute *ap = e->e_attrs;
342
343 #ifdef NEW_LOGGING
344         LDAP_LOG( INDEX, ENTRY, "index_entry: %s (%s) %ld\n",
345                 opid == SLAP_INDEX_ADD_OP ? "add" : "del", e->e_dn, (long) e->e_id );
346 #else
347         Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
348                 opid == SLAP_INDEX_ADD_OP ? "add" : "del",
349                 (long) e->e_id, e->e_dn );
350 #endif
351
352         /* add each attribute to the indexes */
353         for ( ; ap != NULL; ap = ap->a_next ) {
354                 rc = bdb_index_values( op, txn, ap->a_desc,
355                         ap->a_nvals, e->e_id, opid );
356
357                 if( rc != LDAP_SUCCESS ) {
358 #ifdef NEW_LOGGING
359                         LDAP_LOG( INDEX, ENTRY, 
360                                 "index_entry: failure (%d)\n", rc, 0, 0 );
361 #else
362                         Debug( LDAP_DEBUG_TRACE,
363                                 "<= index_entry_%s( %ld, \"%s\" ) failure\n",
364                                 opid == SLAP_INDEX_ADD_OP ? "add" : "del",
365                                 (long) e->e_id, e->e_dn );
366 #endif
367                         return rc;
368                 }
369         }
370
371 #ifdef NEW_LOGGING
372         LDAP_LOG( INDEX, ENTRY, "index_entry: success\n", 0, 0, 0  );
373 #else
374         Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
375                 opid == SLAP_INDEX_ADD_OP ? "add" : "del",
376                 (long) e->e_id, e->e_dn );
377 #endif
378
379         return LDAP_SUCCESS;
380 }