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