]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
4fe0f98871be164b46059ab43547db22c078096b
[openldap] / servers / slapd / back-ldbm / 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-ldbm.h"
12
13 static int      add_value(Backend *be, struct dbcache *db, char *type, int indextype, char *val, ID id);
14 static int      index2prefix(int indextype);
15
16 int
17 index_add_entry(
18     Backend     *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 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         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                 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 index_add_mods(
58     Backend     *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 = 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 IDList *
89 index_read(
90     Backend     *be,
91     char        *type,
92     int         indextype,
93     char        *val
94 )
95 {
96         struct dbcache  *db;
97         Datum           key;
98         IDList          *idl;
99         int             indexmask, syntax;
100         char            prefix;
101         char            *realval, *tmpval;
102         char            buf[BUFSIZ];
103
104 #ifdef HAVE_BERKELEY_DB2
105         memset( &key, 0, sizeof( key ) );
106 #endif
107
108         prefix = index2prefix( indextype );
109         Debug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" \"%c\" \"%s\" )\n",
110             type, prefix, val );
111
112         attr_masks( be->be_private, type, &indexmask, &syntax );
113         if ( ! (indextype & indexmask) ) {
114                 idl =  idl_allids( be );
115                 Debug( LDAP_DEBUG_TRACE,
116                     "<= index_read %lu candidates (allids - not indexed)\n",
117                     idl ? idl->b_nids : 0, 0, 0 );
118                 return( idl );
119         }
120
121         attr_normalize( type );
122         if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
123             == NULL ) {
124                 Debug( LDAP_DEBUG_ANY,
125                     "<= index_read NULL (could not open %s%s)\n", type,
126                     LDBM_SUFFIX, 0 );
127                 return( NULL );
128         }
129
130         realval = val;
131         tmpval = NULL;
132         if ( prefix != '\0' ) {
133               unsigned int      len = strlen( val );
134
135               if ( (len + 2) < sizeof(buf) ) {
136                         realval = buf;
137                 } else {
138                         /* value + prefix + null */
139                         tmpval = (char *) ch_malloc( len + 2 );
140                         realval = tmpval;
141                 }
142               realval[0] = prefix;
143               strcpy( &realval[1], val );
144         }
145
146         key.dptr = realval;
147         key.dsize = strlen( realval ) + 1;
148
149         idl = idl_fetch( be, db, key );
150       if ( tmpval != NULL ) {
151               free( tmpval );
152       }
153
154         ldbm_cache_close( be, db );
155
156         Debug( LDAP_DEBUG_TRACE, "<= index_read %lu candidates\n",
157             idl ? idl->b_nids : 0, 0, 0 );
158         return( idl );
159 }
160
161 static int
162 add_value(
163     Backend             *be,
164     struct dbcache      *db,
165     char                *type,
166     int                 indextype,
167     char                *val,
168     ID                  id
169 )
170 {
171         int     rc;
172         Datum   key;
173         IDList  *idl;
174         char    prefix;
175         char    *realval, *tmpval, *s;
176         char    buf[BUFSIZ];
177
178 #ifdef HAVE_BERKELEY_DB2
179         memset( &key, 0, sizeof( key ) );
180 #endif
181
182         prefix = index2prefix( indextype );
183         Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
184
185         realval = val;
186         tmpval = NULL;
187         idl = NULL;
188         if ( prefix != '\0' ) {
189               unsigned int     len = strlen( val );
190
191               if ( (len + 2) < sizeof(buf) ) {
192                         realval = buf;
193                 } else {
194                         /* value + prefix + null */
195                         tmpval = (char *) ch_malloc( len + 2 );
196                         realval = tmpval;
197                 }
198               realval[0] = prefix;
199               strcpy( &realval[1], val );
200         }
201
202         key.dptr = realval;
203         key.dsize = strlen( realval ) + 1;
204
205         rc = idl_insert_key( be, db, key, id );
206
207         if ( tmpval != NULL ) {
208                 free( tmpval );
209         }
210         idl_free( idl );
211
212         pthread_yield();
213
214         /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
215         return( rc );
216 }
217
218 int
219 index_add_values(
220     Backend             *be,
221     char                *type,
222     struct berval       **vals,
223     ID                  id
224 )
225 {
226         char            *val, *p, *code, *w;
227         unsigned        i, j, len;
228         int             indexmask, syntax;
229         char            buf[SUBLEN + 1];
230         char            vbuf[BUFSIZ];
231         char            *bigbuf;
232         struct dbcache  *db;
233
234         Debug( LDAP_DEBUG_TRACE, "=> index_add_values( \"%s\", %ld )\n", type,
235             id, 0 );
236
237         attr_masks( be->be_private, type, &indexmask, &syntax );
238         if ( indexmask == 0 ) {
239                 return( 0 );
240         }
241
242         if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
243             == NULL ) {
244                 Debug( LDAP_DEBUG_ANY,
245                     "<= index_add_values -1 (could not open/create %s%s)\n",
246                     type, LDBM_SUFFIX, 0 );
247                 return( -1 );
248         }
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, type, INDEX_PRESENCE, "*", id );
257                 }
258
259                 Debug( LDAP_DEBUG_TRACE, "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
260                     syntax, SYNTAX_BIN, 0 );
261                 if ( syntax & SYNTAX_BIN ) {
262                         ldbm_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                 /*
282                  * equality index entry
283                  */
284                 if ( indexmask & INDEX_EQUALITY ) {
285                         add_value( be, db, type, INDEX_EQUALITY, val, id );
286                 }
287
288                 /*
289                  * approximate index entry
290                  */
291                 if ( indexmask & INDEX_APPROX ) {
292                         for ( w = first_word( val ); w != NULL;
293                             w = next_word( w ) ) {
294                                 if ( (code = phonetic( w )) != NULL ) {
295                                         add_value( be, db, type, INDEX_APPROX,
296                                             code, id );
297                                         free( code );
298                                 }
299                         }
300                 }
301
302                 /*
303                  * substrings index entry
304                  */
305                 if ( indexmask & INDEX_SUB ) {
306                         /* leading and trailing */
307                         if ( len > SUBLEN - 2 ) {
308                                 buf[0] = '^';
309                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
310                                         buf[j + 1] = val[j];
311                                 }
312                                 buf[SUBLEN] = '\0';
313
314                                 add_value( be, db, type, INDEX_SUB, buf, id );
315
316                                 p = val + len - SUBLEN + 1;
317                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
318                                         buf[j] = p[j];
319                                 }
320                                 buf[SUBLEN - 1] = '$';
321                                 buf[SUBLEN] = '\0';
322
323                                 add_value( be, db, type, INDEX_SUB, buf, id );
324                         }
325
326                         /* any */
327                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
328                                 for ( j = 0; j < SUBLEN; j++ ) {
329                                         buf[j] = p[j];
330                                 }
331                                 buf[SUBLEN] = '\0';
332
333                                 add_value( be, db, type, INDEX_SUB, buf, id );
334                         }
335                 }
336
337                 if ( bigbuf != NULL ) {
338                         free( bigbuf );
339                 }
340         }
341         ldbm_cache_close( be, db );
342
343         return( 0 );
344 }
345
346 static int
347 index2prefix( int indextype )
348 {
349         int     prefix;
350
351         switch ( indextype ) {
352         case INDEX_EQUALITY:
353                 prefix = EQ_PREFIX;
354                 break;
355         case INDEX_APPROX:
356                 prefix = APPROX_PREFIX;
357                 break;
358         case INDEX_SUB:
359                 prefix = SUB_PREFIX;
360                 break;
361         default:
362                 prefix = '\0';
363                 break;
364         }
365
366         return( prefix );
367 }