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