]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
7dc4f57f96d57f5581dc9e8d526f003f4b4c0971
[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         struct berval   bv;
24         struct berval   *bvals[2];
25
26         Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
27             e->e_dn, 0 );
28
29         /*
30          * dn index entry - make it look like an attribute so it works
31          * with index_add_values() call
32          */
33
34         bv.bv_val = ch_strdup( e->e_ndn );
35         bv.bv_len = strlen( bv.bv_val );
36         bvals[0] = &bv;
37         bvals[1] = NULL;
38
39         /* add the dn to the indexes */
40         {
41                 char *dn = ch_strdup("dn");
42                 index_add_values( be, dn, bvals, e->e_id );
43                 free( dn );
44         }
45
46         free( bv.bv_val );
47
48         /* add each attribute to the indexes */
49         for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
50
51                 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 index_add_mods(
61     Backend     *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_REPLACE:
73                         /* XXX: Delete old index data==>problem when this 
74                          * gets called we lost values already!
75                          */
76                 case LDAP_MOD_ADD:
77                         rc = index_add_values( be, mod->mod_type,
78                             mod->mod_bvalues, id );
79                         break;
80                 case LDAP_MOD_DELETE:
81                         rc =  index_delete_values( be, mod->mod_type,
82                             mod->mod_bvalues, id );
83                         break;
84                 case LDAP_MOD_SOFTADD:  /* SOFTADD means index was there */
85                         rc = 0;
86                         break;
87                 }
88
89                 if ( rc != 0 ) {
90                         return( rc );
91                 }
92         }
93
94         return( 0 );
95 }
96
97 ID_BLOCK *
98 index_read(
99     Backend     *be,
100     char        *type,
101     int         indextype,
102     char        *val
103 )
104 {
105         struct dbcache  *db;
106         Datum           key;
107         ID_BLOCK                *idl;
108         int             indexmask, syntax;
109         char            prefix;
110         char            *realval, *tmpval;
111         char            buf[BUFSIZ];
112
113         char            *at_cn;
114
115         ldbm_datum_init( key );
116
117         prefix = index2prefix( indextype );
118         Debug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" \"%c\" \"%s\" )\n",
119             type, prefix, val );
120
121         attr_masks( be->be_private, type, &indexmask, &syntax );
122         if ( ! (indextype & indexmask) ) {
123                 idl =  idl_allids( be );
124                 Debug( LDAP_DEBUG_TRACE,
125                     "<= index_read %ld candidates (allids - not indexed)\n",
126                     idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
127                 return( idl );
128         }
129
130         attr_normalize( type );
131         at_cn = at_canonical_name( type );
132
133         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
134             == NULL ) {
135                 Debug( LDAP_DEBUG_ANY,
136                     "<= index_read NULL (could not open %s%s)\n", at_cn,
137                     LDBM_SUFFIX, 0 );
138                 return( NULL );
139         }
140
141         realval = val;
142         tmpval = NULL;
143         if ( prefix != UNKNOWN_PREFIX ) {
144               unsigned int      len = strlen( val );
145
146               if ( (len + 2) < sizeof(buf) ) {
147                         realval = buf;
148                 } else {
149                         /* value + prefix + null */
150                         tmpval = (char *) ch_malloc( len + 2 );
151                         realval = tmpval;
152                 }
153               realval[0] = prefix;
154               strcpy( &realval[1], val );
155         }
156
157         key.dptr = realval;
158         key.dsize = strlen( realval ) + 1;
159
160         idl = idl_fetch( be, db, key );
161       if ( tmpval != NULL ) {
162               free( tmpval );
163       }
164
165         ldbm_cache_close( be, db );
166
167         Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n",
168             idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
169         return( idl );
170 }
171
172 static int
173 add_value(
174     Backend             *be,
175     struct dbcache      *db,
176     char                *type,
177     int                 indextype,
178     char                *val,
179     ID                  id
180 )
181 {
182         int     rc;
183         Datum   key;
184         /* XXX do we need idl ??? */
185         ID_BLOCK        *idl = NULL;
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 = idl_insert_key( be, db, key, id );
214
215         if ( tmpval != NULL ) {
216                 free( tmpval );
217         }
218
219         if( idl != NULL ) {
220                 idl_free( idl );
221         }
222
223         ldap_pvt_thread_yield();
224
225         /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
226         return( rc );
227 }
228
229 /* Remove entries from index files */
230
231 int
232 index_delete_values(
233     Backend             *be,
234     char                *type,
235     struct berval       **vals,
236     ID                  id
237 )
238 {
239
240         return 0;
241
242 }
243
244 int
245 index_add_values(
246     Backend             *be,
247     char                *type,
248     struct berval       **vals,
249     ID                  id
250 )
251 {
252         char            *val, *p, *code, *w;
253         unsigned        i, j, len;
254         int             indexmask, syntax;
255         char            buf[SUBLEN + 1];
256         char            vbuf[BUFSIZ];
257         char            *bigbuf;
258         struct dbcache  *db;
259
260         char            *at_cn; /* Attribute canonical name */
261
262         Debug( LDAP_DEBUG_TRACE, "=> index_add_values( \"%s\", %ld )\n", type,
263             id, 0 );
264         attr_normalize(type);
265         attr_masks( be->be_private, type, &indexmask, &syntax );
266         if ( indexmask == 0 ) {
267                 return( 0 );
268         }
269         at_cn = at_canonical_name( type );
270         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
271             == NULL ) {
272                 Debug( LDAP_DEBUG_ANY,
273                     "<= index_add_values -1 (could not open/create %s%s)\n",
274                     at_cn, LDBM_SUFFIX, 0 );
275                 return( -1 );
276         }
277
278
279         for ( i = 0; vals[i] != NULL; i++ ) {
280                 /*
281                  * presence index entry
282                  */
283                 if ( indexmask & INDEX_PRESENCE ) {
284                         add_value( be, db, at_cn, INDEX_PRESENCE, "*", id );
285                 }
286
287                 Debug( LDAP_DEBUG_TRACE, "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
288                     syntax, SYNTAX_BIN, 0 );
289                 if ( syntax & SYNTAX_BIN ) {
290                         ldbm_cache_close( be, db );
291                         return( 0 );
292                 }
293
294                 bigbuf = NULL;
295                 len = vals[i]->bv_len;
296
297                 /* value + null */
298                 if ( len + 2 > sizeof(vbuf) ) {
299                         bigbuf = (char *) ch_malloc( len + 1 );
300                         val = bigbuf;
301                 } else {
302                         val = vbuf;
303                 }
304                 (void) memcpy( val, vals[i]->bv_val, len );
305                 val[len] = '\0';
306
307                 value_normalize( val, syntax );
308
309                 /* value_normalize could change the length of val */
310                 len = strlen( val );
311
312                 /*
313                  * equality index entry
314                  */
315                 if ( indexmask & INDEX_EQUALITY ) {
316                         add_value( be, db, at_cn, INDEX_EQUALITY, val, id );
317                 }
318
319                 /*
320                  * approximate index entry
321                  */
322                 if ( indexmask & INDEX_APPROX ) {
323                         for ( w = first_word( val ); w != NULL;
324                             w = next_word( w ) ) {
325                                 if ( (code = phonetic( w )) != NULL ) {
326                                         add_value( be, db, at_cn, INDEX_APPROX,
327                                             code, id );
328                                         free( code );
329                                 }
330                         }
331                 }
332
333                 /*
334                  * substrings index entry
335                  */
336                 if ( indexmask & INDEX_SUB ) {
337                         /* leading and trailing */
338                         if ( len > SUBLEN - 2 ) {
339                                 buf[0] = '^';
340                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
341                                         buf[j + 1] = val[j];
342                                 }
343                                 buf[SUBLEN] = '\0';
344
345                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
346
347                                 p = val + len - SUBLEN + 1;
348                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
349                                         buf[j] = p[j];
350                                 }
351                                 buf[SUBLEN - 1] = '$';
352                                 buf[SUBLEN] = '\0';
353
354                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
355                         }
356
357                         /* any */
358                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
359                                 for ( j = 0; j < SUBLEN; j++ ) {
360                                         buf[j] = p[j];
361                                 }
362                                 buf[SUBLEN] = '\0';
363
364                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
365                         }
366                 }
367
368                 if ( bigbuf != NULL ) {
369                         free( bigbuf );
370                 }
371         }
372         ldbm_cache_close( be, db );
373
374         return( 0 );
375 }
376
377 static int
378 index2prefix( int indextype )
379 {
380         int     prefix;
381
382         switch ( indextype ) {
383         case INDEX_EQUALITY:
384                 prefix = EQ_PREFIX;
385                 break;
386         case INDEX_APPROX:
387                 prefix = APPROX_PREFIX;
388                 break;
389         case INDEX_SUB:
390                 prefix = SUB_PREFIX;
391                 break;
392         default:
393                 prefix = UNKNOWN_PREFIX;
394                 break;
395         }
396
397         return( prefix );
398 }