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