]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
Initial step of index files fix, more tomorrow.
[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
15 static int      change_value(Backend *be,
16                           struct dbcache *db,
17                           char *type,
18                           int indextype,
19                           char *val,
20                           ID id,
21                           int
22                           (*idl_func)(Backend *, struct dbcache *, Datum, ID));
23 static int      index2prefix(int indextype);
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 = ch_strdup( e->e_ndn );
45         bv.bv_len = strlen( bv.bv_val );
46         bvals[0] = &bv;
47         bvals[1] = NULL;
48
49         /* add the dn to the indexes */
50         {
51                 char *dn = ch_strdup("dn");
52                 index_change_values( be, dn, bvals, e->e_id, __INDEX_ADD_OP );
53                 free( dn );
54         }
55
56         free( bv.bv_val );
57
58         /* add each attribute to the indexes */
59         for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
60                 index_change_values( be, ap->a_type, ap->a_vals, e->e_id,
61                                      __INDEX_ADD_OP );
62         }
63
64         Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
65             e->e_ndn, 0 );
66         return( 0 );
67 }
68
69 int
70 index_add_mods(
71     Backend     *be,
72     LDAPMod     *mods,
73     ID          id
74 )
75 {
76         int     rc;
77
78         for ( ; mods != NULL; mods = mods->mod_next ) {
79                 switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) {
80                 case LDAP_MOD_REPLACE:
81                         /* XXX: Delete old index data==>problem when this 
82                          * gets called we lost values already!
83                          */
84                 case LDAP_MOD_ADD:
85                         rc = index_change_values( be,
86                                                   mods->mod_type,
87                                                   mods->mod_bvalues,
88                                                   id,
89                                                   __INDEX_ADD_OP);
90                         break;
91                 case LDAP_MOD_SOFTADD:  /* SOFTADD means index was there already */
92                         rc = 0;
93                         break;
94                 case LDAP_MOD_DELETE:
95                         rc =  index_change_values( be,
96                                                    mods->mod_type,
97                                                    mods->mod_bvalues,
98                                                    id,
99                                                    __INDEX_DEL_OP );
100                         break;
101                 }
102
103                 if ( rc != 0 ) {
104                         return( rc );
105                 }
106         }
107
108         return( 0 );
109 }
110
111 ID_BLOCK *
112 index_read(
113     Backend     *be,
114     char        *type,
115     int         indextype,
116     char        *val
117 )
118 {
119         struct dbcache  *db;
120         Datum           key;
121         ID_BLOCK                *idl;
122         int             indexmask, syntax;
123         char            prefix;
124         char            *realval, *tmpval;
125         char            buf[BUFSIZ];
126
127         ldbm_datum_init( key );
128
129         prefix = index2prefix( indextype );
130         Debug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" \"%c\" \"%s\" )\n",
131             type, prefix, val );
132
133         attr_masks( be->be_private, type, &indexmask, &syntax );
134         if ( ! (indextype & indexmask) ) {
135                 idl =  idl_allids( be );
136                 Debug( LDAP_DEBUG_TRACE,
137                     "<= index_read %lu candidates (allids - not indexed)\n",
138                     idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
139                 return( idl );
140         }
141
142         attr_normalize( type );
143         if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
144             == NULL ) {
145                 Debug( LDAP_DEBUG_ANY,
146                     "<= index_read NULL (could not open %s%s)\n", type,
147                     LDBM_SUFFIX, 0 );
148                 return( NULL );
149         }
150
151         realval = val;
152         tmpval = NULL;
153         if ( prefix != UNKNOWN_PREFIX ) {
154               unsigned int      len = strlen( val );
155
156               if ( (len + 2) < sizeof(buf) ) {
157                         realval = buf;
158                 } else {
159                         /* value + prefix + null */
160                         tmpval = (char *) ch_malloc( len + 2 );
161                         realval = tmpval;
162                 }
163               realval[0] = prefix;
164               strcpy( &realval[1], val );
165         }
166
167         key.dptr = realval;
168         key.dsize = strlen( realval ) + 1;
169
170         idl = idl_fetch( be, db, key );
171       if ( tmpval != NULL ) {
172               free( tmpval );
173       }
174
175         ldbm_cache_close( be, db );
176
177         Debug( LDAP_DEBUG_TRACE, "<= index_read %lu candidates\n",
178             idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
179         return( idl );
180 }
181
182 /* Add or remove stuff from index files */
183
184 static int
185 change_value(
186     Backend             *be,
187     struct dbcache      *db,
188     char                *type,
189     int                 indextype,
190     char                *val,
191     ID                  id,
192     int                 (*idl_func)(Backend *, struct dbcache *, Datum, ID)
193 )
194 {
195         int     rc;
196         Datum   key;
197         char    *tmpval = NULL;
198         char    *realval = val;
199         char    buf[BUFSIZ];
200
201         char    prefix = index2prefix( indextype );
202
203         ldbm_datum_init( key );
204
205         Debug( LDAP_DEBUG_TRACE,
206                "=> change_value( \"%c%s\", op=%s )\n",
207                prefix, val, (idl_func == idl_insert_key ? "ADD":"DELETE") );
208
209         if ( prefix != UNKNOWN_PREFIX ) {
210               unsigned int     len = strlen( val );
211
212               if ( (len + 2) < sizeof(buf) ) {
213                         realval = buf;
214               } else {
215                         /* value + prefix + null */
216                         tmpval = (char *) ch_malloc( len + 2 );
217                         realval = tmpval;
218               }
219               realval[0] = prefix;
220               strcpy( &realval[1], val );
221         }
222
223         key.dptr = realval;
224         key.dsize = strlen( realval ) + 1;
225
226         rc = idl_func( be, db, key, id );
227
228         if ( tmpval != NULL ) {
229                 free( tmpval );
230         }
231
232         ldap_pvt_thread_yield();
233
234         Debug( LDAP_DEBUG_TRACE, "<= change_value %d\n", rc, 0, 0 );
235
236         return( rc );
237
238 }/* static int change_value() */
239
240 int
241 index_change_values(
242     Backend             *be,
243     char                *type,
244     struct berval       **vals,
245     ID                  id,
246     unsigned int        op
247 )
248 {
249         char            *val, *p, *code, *w;
250         unsigned        i, j, len;
251         int             indexmask, syntax;
252         char            buf[SUBLEN + 1];
253         char            vbuf[BUFSIZ];
254         char            *bigbuf;
255         struct dbcache  *db;
256
257         int             (*idl_funct)(Backend *,
258                                     struct dbcache *,
259                                     Datum, ID);
260         char            *at_cn; /* Attribute canonical name */
261         int             mode;
262
263         Debug( LDAP_DEBUG_TRACE,
264                "=> index_change_values( \"%s\", %ld, op=%s )\n", 
265                type, id, ((op == __INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
266
267         
268         if (op == __INDEX_ADD_OP) {
269
270             /* Add values */
271
272             idl_funct =  idl_insert_key;
273             mode = LDBM_WRCREAT;
274
275         } else {
276
277             /* Delete values */
278
279             idl_funct = idl_delete_key;
280             mode = LDBM_WRITER;
281
282         }
283
284         attr_normalize(type);
285         attr_masks( be->be_private, type, &indexmask, &syntax );
286
287         if ( indexmask == 0 ) {
288                 return( 0 );
289         }
290
291         /* at_cn = at_canonical_name( type ); */
292         at_cn = type;
293
294         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, mode ))
295              == NULL ) {
296                 Debug( LDAP_DEBUG_ANY,
297                        "<= index_change_values (couldn't open(%s%s),md=%s)\n",
298                        at_cn,
299                        LDBM_SUFFIX,
300                        ((mode==LDBM_WRCREAT)?"LDBM_WRCREAT":"LDBM_WRITER") );
301                 return( -1 );
302         }
303
304
305         for ( i = 0; vals[i] != NULL; i++ ) {
306                 /*
307                  * presence index entry
308                  */
309                 if ( indexmask & INDEX_PRESENCE ) {
310
311                         change_value( be, db, at_cn, INDEX_PRESENCE,
312                                       "*", id, idl_funct );
313
314                 }
315
316                 Debug( LDAP_DEBUG_TRACE,
317                        "index_change_values syntax 0x%x syntax bin 0x%x\n",
318                        syntax, SYNTAX_BIN, 0 );
319
320                 if ( syntax & SYNTAX_BIN ) {
321
322                         ldbm_cache_close( be, db );
323                         return( 0 );
324
325                 }
326
327                 bigbuf = NULL;
328                 len = vals[i]->bv_len;
329
330                 /* value + null */
331                 if ( len + 2 > sizeof(vbuf) ) {
332                         bigbuf = (char *) ch_malloc( len + 1 );
333                         val = bigbuf;
334                 } else {
335                         val = vbuf;
336                 }
337                 (void) memcpy( val, vals[i]->bv_val, len );
338                 val[len] = '\0';
339
340                 value_normalize( val, syntax );
341
342                 /* value_normalize could change the length of val */
343                 len = strlen( val );
344
345                 /*
346                  * equality index entry
347                  */
348                 if ( indexmask & INDEX_EQUALITY ) {
349                     
350                         change_value( be, db, at_cn, INDEX_EQUALITY,
351                                       val, id, idl_funct);
352
353                 }
354
355                 /*
356                  * approximate index entry
357                  */
358                 if ( indexmask & INDEX_APPROX ) {
359                         for ( w = first_word( val ); w != NULL;
360                             w = next_word( w ) ) {
361                                 if ( (code = phonetic( w )) != NULL ) {
362                                         change_value( be,
363                                                       db,
364                                                       at_cn,
365                                                       INDEX_APPROX,
366                                                       code,
367                                                       id,
368                                                       idl_funct );
369                                         free( code );
370                                 }
371                         }
372                 }
373
374                 /*
375                  * substrings index entry
376                  */
377                 if ( indexmask & INDEX_SUB ) {
378                         /* leading and trailing */
379                         if ( len > SUBLEN - 2 ) {
380                                 buf[0] = '^';
381                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
382                                         buf[j + 1] = val[j];
383                                 }
384                                 buf[SUBLEN] = '\0';
385
386                                 change_value( be, db, at_cn, INDEX_SUB,
387                                               buf, id, idl_funct );
388
389                                 p = val + len - SUBLEN + 1;
390                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
391                                         buf[j] = p[j];
392                                 }
393                                 buf[SUBLEN - 1] = '$';
394                                 buf[SUBLEN] = '\0';
395
396                                 change_value( be, db, at_cn, INDEX_SUB,
397                                               buf, id, idl_funct );
398                         }
399
400                         /* any */
401                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
402                                 for ( j = 0; j < SUBLEN; j++ ) {
403                                         buf[j] = p[j];
404                                 }
405                                 buf[SUBLEN] = '\0';
406
407                                 change_value( be, db, at_cn, INDEX_SUB,
408                                               buf, id, idl_funct );
409                         }
410                 }
411
412                 if ( bigbuf != NULL ) {
413                         free( bigbuf );
414                 }
415         }
416         ldbm_cache_close( be, db );
417
418         return( 0 );
419
420 }/* int index_change_values() */
421
422 static int
423 index2prefix( int indextype )
424 {
425         int     prefix;
426
427         switch ( indextype ) {
428         case INDEX_EQUALITY:
429                 prefix = EQ_PREFIX;
430                 break;
431         case INDEX_APPROX:
432                 prefix = APPROX_PREFIX;
433                 break;
434         case INDEX_SUB:
435                 prefix = SUB_PREFIX;
436                 break;
437         default:
438                 prefix = UNKNOWN_PREFIX;
439                 break;
440         }
441
442         return( prefix );
443 }