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