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