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