]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb2/index.c
Make dbEnv a private toy of back-bdb2.
[openldap] / servers / slapd / back-bdb2 / index.c
1 /* index.c - routines for dealing with attribute indexes */
2
3 #include "portable.h"
4
5 #include <stdio.h>
6
7 #include <ac/string.h>
8 #include <ac/socket.h>
9
10 #include "slap.h"
11 #include "back-bdb2.h"
12
13 static int      add_value(BackendDB *be, struct dbcache *db, char *type, int indextype, char *val, ID id);
14 static int      index2prefix(int indextype);
15
16 int
17 bdb2i_index_add_entry(
18     BackendDB   *be,
19     Entry       *e
20 )
21 {
22         Attribute       *ap;
23         char            *dnval;
24         struct berval   bv;
25         struct berval   *bvals[2];
26
27         Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
28             e->e_dn, 0 );
29
30         /*
31          * dn index entry - make it look like an attribute so it works
32          * with bdb2i_index_add_values() call
33          */
34
35         bv.bv_val = ch_strdup( e->e_dn );
36         bv.bv_len = strlen( bv.bv_val );
37         (void) dn_normalize_case( bv.bv_val );
38         bvals[0] = &bv;
39         bvals[1] = NULL;
40
41         /* add the dn to the indexes */
42         bdb2i_index_add_values( be, "dn", bvals, e->e_id );
43
44         free( bv.bv_val );
45
46         /* add each attribute to the indexes */
47         for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
48                 bdb2i_index_add_values( be, ap->a_type, ap->a_vals, e->e_id );
49         }
50
51         Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
52             e->e_dn, 0 );
53         return( 0 );
54 }
55
56 int
57 bdb2i_index_add_mods(
58     BackendDB   *be,
59     LDAPModList *ml,
60     ID          id
61 )
62 {
63         int     rc;
64
65         for ( ; ml != NULL; ml = ml->ml_next ) {
66                 LDAPMod *mod = &ml->ml_mod;
67
68                 switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
69                 case LDAP_MOD_ADD:
70                 case LDAP_MOD_REPLACE:
71                         rc = bdb2i_index_add_values( be, mod->mod_type,
72                             mod->mod_bvalues, id );
73                         break;
74
75                 case LDAP_MOD_DELETE:
76                         rc = 0;
77                         break;
78                 }
79
80                 if ( rc != 0 ) {
81                         return( rc );
82                 }
83         }
84
85         return( 0 );
86 }
87
88 ID_BLOCK *
89 bdb2i_index_read(
90     BackendDB   *be,
91     char        *type,
92     int         indextype,
93     char        *val
94 )
95 {
96         struct dbcache  *db;
97         Datum           key;
98         ID_BLOCK                *idl;
99         int             indexmask, syntax;
100         char            prefix;
101         char            *realval, *tmpval;
102         char            buf[BUFSIZ];
103
104         ldbm_datum_init( key );
105
106         prefix = index2prefix( indextype );
107         Debug( LDAP_DEBUG_TRACE, "=> bdb2i_index_read( \"%s\" \"%c\" \"%s\" )\n",
108             type, prefix, val );
109
110         bdb2i_attr_masks( be->be_private, type, &indexmask, &syntax );
111         if ( ! (indextype & indexmask) ) {
112                 idl =  bdb2i_idl_allids( be );
113                 Debug( LDAP_DEBUG_TRACE,
114                     "<= bdb2i_index_read %ld candidates (allids - not indexed)\n",
115                     idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
116                 return( idl );
117         }
118
119         attr_normalize( type );
120         if ( (db = bdb2i_cache_open( be, type, BDB2_SUFFIX, LDBM_WRCREAT ))
121             == NULL ) {
122                 Debug( LDAP_DEBUG_ANY,
123                     "<= bdb2i_index_read NULL (could not open %s%s)\n", type,
124                     BDB2_SUFFIX, 0 );
125                 return( NULL );
126         }
127
128         realval = val;
129         tmpval = NULL;
130         if ( prefix != UNKNOWN_PREFIX ) {
131         unsigned int    len = strlen( val );
132
133         if ( (len + 2) < sizeof(buf) ) {
134                         realval = buf;
135                 } else {
136                         /* value + prefix + null */
137                         tmpval = (char *) ch_malloc( len + 2 );
138                         realval = tmpval;
139                 }
140         realval[0] = prefix;
141         strcpy( &realval[1], val );
142         }
143
144         key.dptr = realval;
145         key.dsize = strlen( realval ) + 1;
146
147         idl = bdb2i_idl_fetch( be, db, key );
148     if ( tmpval != NULL ) {
149         free( tmpval );
150     }
151
152         bdb2i_cache_close( be, db );
153
154         Debug( LDAP_DEBUG_TRACE, "<= bdb2i_index_read %ld candidates\n",
155             idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
156         return( idl );
157 }
158
159 static int
160 add_value(
161     BackendDB           *be,
162     struct dbcache      *db,
163     char                *type,
164     int                 indextype,
165     char                *val,
166     ID                  id
167 )
168 {
169         int     rc;
170         Datum   key;
171         char    *tmpval = NULL;
172         char    *realval = val;
173         char    buf[BUFSIZ];
174
175         char    prefix = index2prefix( indextype );
176
177         ldbm_datum_init( key );
178
179         Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
180
181         if ( prefix != UNKNOWN_PREFIX ) {
182         unsigned int     len = strlen( val );
183
184         if ( (len + 2) < sizeof(buf) ) {
185                         realval = buf;
186                 } else {
187                         /* value + prefix + null */
188                         tmpval = (char *) ch_malloc( len + 2 );
189                         realval = tmpval;
190                 }
191         realval[0] = prefix;
192         strcpy( &realval[1], val );
193         }
194
195         key.dptr = realval;
196         key.dsize = strlen( realval ) + 1;
197
198         rc = bdb2i_idl_insert_key( be, db, key, id );
199
200         if ( tmpval != NULL ) {
201                 free( tmpval );
202         }
203
204         ldap_pvt_thread_yield();
205
206         /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
207         return( rc );
208 }
209
210 int
211 bdb2i_index_add_values(
212     BackendDB           *be,
213     char                *type,
214     struct berval       **vals,
215     ID                  id
216 )
217 {
218         char            *val, *p, *code, *w;
219         unsigned        i, j, len;
220         int             indexmask, syntax;
221         char            buf[SUBLEN + 1];
222         char            vbuf[BUFSIZ];
223         char            *bigbuf;
224         struct dbcache  *db;
225
226         Debug( LDAP_DEBUG_TRACE, "=> bdb2i_index_add_values( \"%s\", %ld )\n", type,
227             id, 0 );
228
229         bdb2i_attr_masks( be->be_private, type, &indexmask, &syntax );
230         if ( indexmask == 0 ) {
231                 return( 0 );
232         }
233
234         if ( (db = bdb2i_cache_open( be, type, BDB2_SUFFIX, LDBM_WRCREAT ))
235             == NULL ) {
236                 Debug( LDAP_DEBUG_ANY,
237                     "<= bdb2i_index_add_values -1 (could not open/create %s%s)\n",
238                     type, BDB2_SUFFIX, 0 );
239                 return( -1 );
240         }
241
242         for ( i = 0; vals[i] != NULL; i++ ) {
243                 /*
244                  * presence index entry
245                  */
246                 if ( indexmask & INDEX_PRESENCE ) {
247                         add_value( be, db, type, INDEX_PRESENCE, "*", id );
248                 }
249
250                 Debug( LDAP_DEBUG_TRACE, "*** bdb2i_index_add_values syntax 0x%x syntax bin 0x%x\n",
251                     syntax, SYNTAX_BIN, 0 );
252                 if ( syntax & SYNTAX_BIN ) {
253                         bdb2i_cache_close( be, db );
254                         return( 0 );
255                 }
256
257                 bigbuf = NULL;
258                 len = vals[i]->bv_len;
259
260                 /* value + null */
261                 if ( len + 2 > sizeof(vbuf) ) {
262                         bigbuf = (char *) ch_malloc( len + 1 );
263                         val = bigbuf;
264                 } else {
265                         val = vbuf;
266                 }
267                 (void) memcpy( val, vals[i]->bv_val, len );
268                 val[len] = '\0';
269
270                 value_normalize( val, syntax );
271
272                 /*
273                  * equality index entry
274                  */
275                 if ( indexmask & INDEX_EQUALITY ) {
276                         add_value( be, db, type, INDEX_EQUALITY, val, id );
277                 }
278
279                 /*
280                  * approximate index entry
281                  */
282                 if ( indexmask & INDEX_APPROX ) {
283                         for ( w = first_word( val ); w != NULL;
284                             w = next_word( w ) ) {
285                                 if ( (code = phonetic( w )) != NULL ) {
286                                         add_value( be, db, type, INDEX_APPROX,
287                                             code, id );
288                                         free( code );
289                                 }
290                         }
291                 }
292
293                 /*
294                  * substrings index entry
295                  */
296                 if ( indexmask & INDEX_SUB ) {
297                         /* leading and trailing */
298                         if ( len > SUBLEN - 2 ) {
299                                 buf[0] = '^';
300                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
301                                         buf[j + 1] = val[j];
302                                 }
303                                 buf[SUBLEN] = '\0';
304
305                                 add_value( be, db, type, INDEX_SUB, buf, id );
306
307                                 p = val + len - SUBLEN + 1;
308                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
309                                         buf[j] = p[j];
310                                 }
311                                 buf[SUBLEN - 1] = '$';
312                                 buf[SUBLEN] = '\0';
313
314                                 add_value( be, db, type, INDEX_SUB, buf, id );
315                         }
316
317                         /* any */
318                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
319                                 for ( j = 0; j < SUBLEN; j++ ) {
320                                         buf[j] = p[j];
321                                 }
322                                 buf[SUBLEN] = '\0';
323
324                                 add_value( be, db, type, INDEX_SUB, buf, id );
325                         }
326                 }
327
328                 if ( bigbuf != NULL ) {
329                         free( bigbuf );
330                 }
331         }
332         bdb2i_cache_close( be, db );
333
334         return( 0 );
335 }
336
337 static int
338 index2prefix( int indextype )
339 {
340         int     prefix;
341
342         switch ( indextype ) {
343         case INDEX_EQUALITY:
344                 prefix = EQ_PREFIX;
345                 break;
346         case INDEX_APPROX:
347                 prefix = APPROX_PREFIX;
348                 break;
349         case INDEX_SUB:
350                 prefix = SUB_PREFIX;
351                 break;
352         default:
353                 prefix = UNKNOWN_PREFIX;
354                 break;
355         }
356
357         return( prefix );
358 }