]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/index.c
Do something with the error text.
[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         return rc;
252 }
253
254 static int index_at_values(
255         Backend *be,
256         DB_TXN *txn,
257         AttributeType *type,
258         struct berval *lang,
259         struct berval **vals,
260         ID id,
261         int op,
262         char ** dbnamep,
263         slap_mask_t *maskp )
264 {
265         int rc;
266         slap_mask_t mask;
267         slap_mask_t tmpmask = 0;
268         int lindex = 0;
269
270         if( type->sat_sup ) {
271                 /* recurse */
272                 rc = index_at_values( be, txn,
273                         type->sat_sup, lang,
274                         vals, id, op,
275                         dbnamep, &tmpmask );
276
277                 if( rc ) return rc;
278         }
279
280         bdb_attr_mask( be->be_private, type->sat_cname, &mask );
281
282         if( mask ) {
283                 *dbnamep = type->sat_cname;
284         } else if ( tmpmask & SLAP_INDEX_AUTO_SUBTYPES ) {
285                 mask = tmpmask;
286         }
287
288         if( mask ) {
289                 rc = indexer( be, txn, *dbnamep,
290                         type->sat_cname,
291                         vals, id, op,
292                         mask );
293
294                 if( rc ) return rc;
295         }
296
297         if( lang->bv_len ) {
298                 char *dbname = NULL;
299                 size_t tlen = strlen( type->sat_cname );
300                 size_t llen = lang->bv_len;
301                 char *lname = ch_malloc( tlen + llen + sizeof(";") );
302
303                 sprintf( lname, "%s;%s", type->sat_cname, lang->bv_val );
304
305                 bdb_attr_mask( be->be_private, lname, &tmpmask );
306
307                 if( tmpmask ) {
308                         dbname = lname;
309                 } else if ( mask & SLAP_INDEX_AUTO_LANG ) {
310                         dbname = *dbnamep;
311                         tmpmask = mask;
312                 }
313
314                 if( dbname != NULL ) {
315                         rc = indexer( be, txn, dbname, lname,
316                                 vals, id, op,
317                                 tmpmask );
318
319                         if( rc ) {
320                                 ch_free( lname );
321                                 return rc;
322                         }
323                 }
324
325                 ch_free( lname );
326         }
327
328         return LDAP_SUCCESS;
329 }
330
331 int bdb_index_values(
332         Backend *be,
333         DB_TXN *txn,
334         AttributeDescription *desc,
335         struct berval **vals,
336         ID id,
337         int op )
338 {
339         int rc;
340         char *dbname = NULL;
341         slap_mask_t mask;
342
343         if( slap_ad_is_binary( desc ) ) {
344                 /* binary attributes have no index capabilities */
345                 return LDAP_SUCCESS;
346         }
347
348         rc = index_at_values( be, txn,
349                 desc->ad_type, &desc->ad_lang,
350                 vals, id, op,
351                 &dbname, &mask );
352
353         return rc;
354 }
355
356 int
357 bdb_index_entry(
358         Backend *be,
359         DB_TXN *txn,
360         int op,
361         Entry   *e,
362         Attribute *ap )
363 {
364         int rc;
365
366 #ifdef NEW_LOGGING
367         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
368                 "index_entry: %s (%s) %ld\n",
369                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
370                 e->e_dn, (long) e->e_id ));
371 #else
372         Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
373                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
374                 (long) e->e_id, e->e_dn );
375 #endif
376
377         /* add each attribute to the indexes */
378         for ( ; ap != NULL; ap = ap->a_next ) {
379                 rc = bdb_index_values( be, txn,
380                         ap->a_desc, ap->a_vals, e->e_id, op );
381
382                 if( rc != LDAP_SUCCESS ) {
383 #ifdef NEW_LOGGING
384                         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
385                            "index_entry: success\n" ));
386 #else
387                         Debug( LDAP_DEBUG_TRACE,
388                                 "<= index_entry_%s( %ld, \"%s\" ) success\n",
389                                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
390                                 (long) e->e_id, e->e_dn );
391 #endif
392                         return rc;
393                 }
394         }
395
396 #ifdef NEW_LOGGING
397         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
398                 "index_entry: success\n" ));
399 #else
400         Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
401                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
402                 (long) e->e_id, e->e_dn );
403 #endif
404
405         return LDAP_SUCCESS;
406 }