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