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