]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/index.c
Merge in latest changes 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         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, 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, 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 #if 0   /* No longer needed, our frees are in order so nothing accumulates */
178         mark = sl_mark(op->o_tmpmemctx);
179 #endif
180
181         if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
182                 rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid );
183                 if( rc ) {
184                         goto done;
185                 }
186         }
187
188         if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
189                 rc = ad->ad_type->sat_equality->smr_indexer(
190                         LDAP_FILTER_EQUALITY,
191                         mask,
192                         ad->ad_type->sat_syntax,
193                         ad->ad_type->sat_equality,
194                         atname, vals, &keys, op->o_tmpmemctx );
195
196                 if( rc == LDAP_SUCCESS && keys != NULL ) {
197                         for( i=0; keys[i].bv_val != NULL; i++ ) {
198                                 rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
199                                 if( rc ) {
200                                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
201                                         goto done;
202                                 }
203                         }
204                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
205                 }
206                 rc = LDAP_SUCCESS;
207         }
208
209         if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
210                 rc = ad->ad_type->sat_approx->smr_indexer(
211                         LDAP_FILTER_APPROX,
212                         mask,
213                         ad->ad_type->sat_syntax,
214                         ad->ad_type->sat_approx,
215                         atname, vals, &keys, op->o_tmpmemctx );
216
217                 if( rc == LDAP_SUCCESS && keys != NULL ) {
218                         for( i=0; keys[i].bv_val != NULL; i++ ) {
219                                 rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
220                                 if( rc ) {
221                                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
222                                         goto done;
223                                 }
224                         }
225                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
226                 }
227
228                 rc = LDAP_SUCCESS;
229         }
230
231         if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
232                 rc = ad->ad_type->sat_substr->smr_indexer(
233                         LDAP_FILTER_SUBSTRINGS,
234                         mask,
235                         ad->ad_type->sat_syntax,
236                         ad->ad_type->sat_substr,
237                         atname, vals, &keys, op->o_tmpmemctx );
238
239                 if( rc == LDAP_SUCCESS && keys != NULL ) {
240                         for( i=0; keys[i].bv_val != NULL; i++ ) {
241                                 bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid );
242                                 if( rc ) {
243                                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
244                                         goto done;
245                                 }
246                         }
247                         ber_bvarray_free_x( keys, op->o_tmpmemctx );
248                 }
249
250                 rc = LDAP_SUCCESS;
251         }
252
253 done:
254 #if 0
255         sl_release( mark, op->o_tmpmemctx );
256 #endif
257         return rc;
258 }
259
260 static int index_at_values(
261         Operation *op,
262         DB_TXN *txn,
263         AttributeDescription *ad,
264         AttributeType *type,
265         struct berval *tags,
266         BerVarray vals,
267         ID id,
268         int opid )
269 {
270         int rc;
271         slap_mask_t mask = 0;
272
273         if( type->sat_sup ) {
274                 /* recurse */
275                 rc = index_at_values( op, txn, NULL,
276                         type->sat_sup, tags,
277                         vals, id, opid );
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( op->o_bd->be_private, type->sat_ad, &mask );
285                 ad = type->sat_ad;
286         }
287
288         if( mask ) {
289                 rc = indexer( op, txn, ad, &type->sat_cname,
290                         vals, id, opid,
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( op->o_bd->be_private, desc, &mask );
304                 }
305
306                 if( mask ) {
307                         rc = indexer( op, txn, desc, &desc->ad_cname,
308                                 vals, id, opid,
309                                 mask );
310
311                         if( rc ) {
312                                 return rc;
313                         }
314                 }
315         }
316
317         return LDAP_SUCCESS;
318 }
319
320 int bdb_index_values(
321         Operation *op,
322         DB_TXN *txn,
323         AttributeDescription *desc,
324         BerVarray vals,
325         ID id,
326         int opid )
327 {
328         int rc;
329
330         rc = index_at_values( op, txn, desc,
331                 desc->ad_type, &desc->ad_tags,
332                 vals, id, opid );
333
334         return rc;
335 }
336
337 int
338 bdb_index_entry(
339         Operation *op,
340         DB_TXN *txn,
341         int opid,
342         Entry   *e )
343 {
344         int rc;
345         Attribute *ap = e->e_attrs;
346
347 #ifdef NEW_LOGGING
348         LDAP_LOG( INDEX, ENTRY, "index_entry: %s (%s) %ld\n",
349                 opid == SLAP_INDEX_ADD_OP ? "add" : "del", e->e_dn, (long) e->e_id );
350 #else
351         Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
352                 opid == SLAP_INDEX_ADD_OP ? "add" : "del",
353                 (long) e->e_id, e->e_dn );
354 #endif
355
356         /* add each attribute to the indexes */
357         for ( ; ap != NULL; ap = ap->a_next ) {
358                 rc = bdb_index_values( op, txn, ap->a_desc,
359                         ap->a_nvals, e->e_id, opid );
360
361                 if( rc != LDAP_SUCCESS ) {
362 #ifdef NEW_LOGGING
363                         LDAP_LOG( INDEX, ENTRY, 
364                                 "index_entry: failure (%d)\n", rc, 0, 0 );
365 #else
366                         Debug( LDAP_DEBUG_TRACE,
367                                 "<= index_entry_%s( %ld, \"%s\" ) failure\n",
368                                 opid == SLAP_INDEX_ADD_OP ? "add" : "del",
369                                 (long) e->e_id, e->e_dn );
370 #endif
371                         return rc;
372                 }
373         }
374
375 #ifdef NEW_LOGGING
376         LDAP_LOG( INDEX, ENTRY, "index_entry: success\n", 0, 0, 0  );
377 #else
378         Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
379                 opid == SLAP_INDEX_ADD_OP ? "add" : "del",
380                 (long) e->e_id, e->e_dn );
381 #endif
382
383         return LDAP_SUCCESS;
384 }