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