]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
b27327dccb27b4bc50abba09406354c131cc43e8
[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,
14                           struct dbcache *db,
15                           char *type,
16                           int indextype,
17                           char *val,
18                           ID id);
19 static int      delete_value(Backend *be,
20                              struct dbcache *db,
21                              char *type,
22                              int indextype,
23                              char *val,
24                              ID id);
25 static int      index2prefix(int indextype);
26
27 int
28 index_add_entry(
29     Backend     *be,
30     Entry       *e
31 )
32 {
33         Attribute       *ap;
34         struct berval   bv;
35         struct berval   *bvals[2];
36
37         Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
38             e->e_dn, 0 );
39
40         /*
41          * dn index entry - make it look like an attribute so it works
42          * with index_add_values() call
43          */
44
45         bv.bv_val = ch_strdup( e->e_ndn );
46         bv.bv_len = strlen( bv.bv_val );
47         bvals[0] = &bv;
48         bvals[1] = NULL;
49
50         /* add the dn to the indexes */
51         {
52                 char *dn = ch_strdup("dn");
53                 index_add_values( be, dn, bvals, e->e_id );
54                 free( dn );
55         }
56
57         free( bv.bv_val );
58
59         /* add each attribute to the indexes */
60         for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
61
62                 index_add_values( be, ap->a_type, ap->a_vals, e->e_id );
63         }
64
65         Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
66             e->e_ndn, 0 );
67         return( 0 );
68 }
69
70 int
71 index_add_mods(
72     Backend     *be,
73     LDAPModList *ml,
74     ID          id
75 )
76 {
77         int     rc;
78
79         for ( ; ml != NULL; ml = ml->ml_next ) {
80                 LDAPMod *mod = &ml->ml_mod;
81
82                 switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
83                 case LDAP_MOD_REPLACE:
84                         /* XXX: Delete old index data==>problem when this 
85                          * gets called we lost values already!
86                          */
87                 case LDAP_MOD_ADD:
88                         rc = index_add_values( be, mod->mod_type,
89                             mod->mod_bvalues, id );
90                         break;
91                 case LDAP_MOD_DELETE:
92                         rc =  index_delete_values( be, mod->mod_type,
93                             mod->mod_bvalues, id );
94                         break;
95                 case LDAP_MOD_SOFTADD:  /* SOFTADD means index was there */
96                         rc = 0;
97                         break;
98                 }
99
100                 if ( rc != 0 ) {
101                         return( rc );
102                 }
103         }
104
105         return( 0 );
106 }
107
108 ID_BLOCK *
109 index_read(
110     Backend     *be,
111     char        *type,
112     int         indextype,
113     char        *val
114 )
115 {
116         struct dbcache  *db;
117         Datum           key;
118         ID_BLOCK                *idl;
119         int             indexmask, syntax;
120         char            prefix;
121         char            *realval, *tmpval;
122         char            buf[BUFSIZ];
123
124         char            *at_cn;
125
126         ldbm_datum_init( key );
127
128         prefix = index2prefix( indextype );
129         Debug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" \"%c\" \"%s\" )\n",
130             type, prefix, val );
131
132         attr_masks( be->be_private, type, &indexmask, &syntax );
133         if ( ! (indextype & indexmask) ) {
134                 idl =  idl_allids( be );
135                 Debug( LDAP_DEBUG_TRACE,
136                     "<= index_read %ld candidates (allids - not indexed)\n",
137                     idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
138                 return( idl );
139         }
140
141         attr_normalize( type );
142         at_cn = at_canonical_name( type );
143
144         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
145             == NULL ) {
146                 Debug( LDAP_DEBUG_ANY,
147                     "<= index_read NULL (could not open %s%s)\n", at_cn,
148                     LDBM_SUFFIX, 0 );
149                 return( NULL );
150         }
151
152         realval = val;
153         tmpval = NULL;
154         if ( prefix != UNKNOWN_PREFIX ) {
155               unsigned int      len = strlen( val );
156
157               if ( (len + 2) < sizeof(buf) ) {
158                         realval = buf;
159                 } else {
160                         /* value + prefix + null */
161                         tmpval = (char *) ch_malloc( len + 2 );
162                         realval = tmpval;
163                 }
164               realval[0] = prefix;
165               strcpy( &realval[1], val );
166         }
167
168         key.dptr = realval;
169         key.dsize = strlen( realval ) + 1;
170
171         idl = idl_fetch( be, db, key );
172       if ( tmpval != NULL ) {
173               free( tmpval );
174       }
175
176         ldbm_cache_close( be, db );
177
178         Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n",
179             idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
180         return( idl );
181 }
182
183 /* Remove values from index files */
184
185 static int
186 delete_value(
187     Backend             *be,
188     struct dbcache      *db,
189     char                *type,
190     int                 indextype,
191     char                *val,
192     ID                  id
193 )
194 {
195
196         int     rc;
197         Datum   key;
198         /* XXX do we need idl ??? */
199         ID_BLOCK        *idl = NULL;
200         char    *tmpval = NULL;
201         char    *realval = val;
202         char    buf[BUFSIZ];
203
204         char    prefix = index2prefix( indextype );
205
206         ldbm_datum_init( key );
207
208         Debug( LDAP_DEBUG_TRACE,
209                "=> delete_value( \"%c%s\" )\n",
210                prefix, val, 0 );
211
212         if ( prefix != UNKNOWN_PREFIX ) {
213               unsigned int     len = strlen( val );
214
215               if ( (len + 2) < sizeof(buf) ) {
216                         realval = buf;
217               } else {
218                         /* value + prefix + null */
219                         tmpval = (char *) ch_malloc( len + 2 );
220                         realval = tmpval;
221               }
222               realval[0] = prefix;
223               strcpy( &realval[1], val );
224         }
225
226         key.dptr = realval;
227         key.dsize = strlen( realval ) + 1;
228
229         rc = idl_delete_key( be, db, key, id );
230
231         if ( tmpval != NULL ) {
232                 free( tmpval );
233         }
234
235         if( idl != NULL ) {
236                 idl_free( idl );
237         }
238
239         ldap_pvt_thread_yield();
240
241         Debug( LDAP_DEBUG_TRACE, "<= delete_value %d\n", rc, 0, 0 );
242
243         return( rc );
244
245 }/* static int delete_value() */
246
247 static int
248 add_value(
249     Backend             *be,
250     struct dbcache      *db,
251     char                *type,
252     int                 indextype,
253     char                *val,
254     ID                  id
255 )
256 {
257         int     rc;
258         Datum   key;
259         /* XXX do we need idl ??? */
260         ID_BLOCK        *idl = NULL;
261         char    *tmpval = NULL;
262         char    *realval = val;
263         char    buf[BUFSIZ];
264
265         char    prefix = index2prefix( indextype );
266
267         ldbm_datum_init( key );
268
269         Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
270
271         if ( prefix != UNKNOWN_PREFIX ) {
272               unsigned int     len = strlen( val );
273
274               if ( (len + 2) < sizeof(buf) ) {
275                         realval = buf;
276                 } else {
277                         /* value + prefix + null */
278                         tmpval = (char *) ch_malloc( len + 2 );
279                         realval = tmpval;
280                 }
281               realval[0] = prefix;
282               strcpy( &realval[1], val );
283         }
284
285         key.dptr = realval;
286         key.dsize = strlen( realval ) + 1;
287
288         rc = idl_insert_key( be, db, key, id );
289
290         if ( tmpval != NULL ) {
291                 free( tmpval );
292         }
293
294         if( idl != NULL ) {
295                 idl_free( idl );
296         }
297
298         ldap_pvt_thread_yield();
299
300         /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
301         return( rc );
302 }
303
304 /* Remove entries from index files */
305
306 int
307 index_delete_values(
308     Backend             *be,
309     char                *type,
310     struct berval       **vals,
311     ID                  id
312 )
313 {
314         int             indexmask, syntax;
315         char            *at_cn; /* Attribute canonical name */
316         struct dbcache  *db;
317         char            *val, *p, *code, *w;
318         unsigned        i, j, len;
319         char            buf[SUBLEN + 1];
320         char            vbuf[BUFSIZ];
321         char            *bigbuf;
322
323
324         Debug( LDAP_DEBUG_TRACE,
325                "=> index_delete_values( \"%s\", %ld )\n", 
326                (type ? type : "(NULL)"),
327                id,
328                0 );
329                
330         attr_normalize(type);
331         attr_masks( be->be_private, type, &indexmask, &syntax );
332         
333         if ( indexmask == 0 ) {
334                 return( 0 );
335         }
336
337         at_cn = at_canonical_name( type );
338
339         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRITER ))
340              == NULL ) {
341
342                 Debug( LDAP_DEBUG_ANY,
343                        "<= index_delete_values -1 (could not open(wr) %s%s)\n",
344                        at_cn,
345                        LDBM_SUFFIX,
346                        0 );
347                 return( -1 );
348
349         }
350
351         /* Remove each value from index file */
352         
353         for ( i = 0; vals[i] != NULL; i++ ) {
354
355                 /*
356                  * Presence index entry
357                  */
358
359                 if ( indexmask & INDEX_PRESENCE ) {
360                         delete_value( be, db, at_cn, INDEX_PRESENCE, "*", id );
361                 }
362
363                 Debug( LDAP_DEBUG_TRACE,
364                        "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
365                        syntax, SYNTAX_BIN, 0 );
366
367                 if ( syntax & SYNTAX_BIN ) {
368                         ldbm_cache_close( be, db );
369                         return( 0 );
370                 }
371
372                 bigbuf = NULL;
373                 len = vals[i]->bv_len;
374
375                 /* value + null */
376                 if ( len + 2 > sizeof(vbuf) ) {
377
378                         bigbuf = (char *) ch_malloc( len + 1 );
379                         val = bigbuf;
380
381                 } else {
382
383                         val = vbuf;
384
385                 }
386
387                 (void) memcpy( val, vals[i]->bv_val, len );
388                 val[len] = '\0';
389
390                 value_normalize( val, syntax );
391
392                 /* value_normalize could change the length of val */
393
394                 len = strlen( val );
395
396                 /*
397                  * equality index entry
398                  */
399
400                 if ( indexmask & INDEX_EQUALITY ) {
401                     
402                         delete_value( be, db, at_cn, INDEX_EQUALITY, val, id );
403
404                 }
405
406                 /*
407                  * approximate index entry
408                  */
409                 if ( indexmask & INDEX_APPROX ) {
410                     
411                         for ( w = first_word( val );
412                               w != NULL;
413                               w = next_word( w ) ) {
414                             
415                                 if ( (code = phonetic( w )) != NULL ) {
416
417                                         delete_value( be,
418                                                       db,
419                                                       at_cn,
420                                                       INDEX_APPROX,
421                                                       code,
422                                                       id );
423                                         free( code );
424                                 }
425                         }
426
427                 }
428
429                 /*
430                  * substrings index entry
431                  */
432
433                 if ( indexmask & INDEX_SUB ) {
434
435                         /* leading and trailing */
436                         if ( len > SUBLEN - 2 ) {
437
438                                 buf[0] = '^';
439                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
440                                         buf[j + 1] = val[j];
441                                 }
442                                 buf[SUBLEN] = '\0';
443
444                                 delete_value( be,
445                                               db,
446                                               at_cn,
447                                               INDEX_SUB,
448                                               buf,
449                                               id );
450
451                                 p = val + len - SUBLEN + 1;
452                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
453                                         buf[j] = p[j];
454                                 }
455                                 buf[SUBLEN - 1] = '$';
456                                 buf[SUBLEN] = '\0';
457
458                                 delete_value( be,
459                                               db,
460                                               at_cn,
461                                               INDEX_SUB,
462                                               buf,
463                                               id );
464
465                         }
466
467                         /* any */
468
469                         for (p = val; p < (val + len - SUBLEN + 1); p++) {
470
471                                 for ( j = 0; j < SUBLEN; j++ ) {
472                                         buf[j] = p[j];
473                                 }
474                                 buf[SUBLEN] = '\0';
475
476                                 delete_value( be,
477                                               db,
478                                               at_cn,
479                                               INDEX_SUB,
480                                               buf,
481                                               id );
482                         }/* for (p = val; p < (val + len - SUBLEN + 1); p++) */
483
484                 }/* if ( indexmask & INDEX_SUB ) */
485
486                 if ( bigbuf != NULL ) {
487
488                         free( bigbuf );
489
490                 }
491
492         }/* for ( i = 0; vals[i] != NULL; i++ ) */
493
494         ldbm_cache_close( be, db );
495
496         return 0;
497
498 }
499
500 int
501 index_add_values(
502     Backend             *be,
503     char                *type,
504     struct berval       **vals,
505     ID                  id
506 )
507 {
508         char            *val, *p, *code, *w;
509         unsigned        i, j, len;
510         int             indexmask, syntax;
511         char            buf[SUBLEN + 1];
512         char            vbuf[BUFSIZ];
513         char            *bigbuf;
514         struct dbcache  *db;
515
516         char            *at_cn; /* Attribute canonical name */
517
518         Debug( LDAP_DEBUG_TRACE, "=> index_add_values( \"%s\", %ld )\n", type,
519             id, 0 );
520         attr_normalize(type);
521         attr_masks( be->be_private, type, &indexmask, &syntax );
522         if ( indexmask == 0 ) {
523                 return( 0 );
524         }
525         at_cn = at_canonical_name( type );
526         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
527             == NULL ) {
528                 Debug( LDAP_DEBUG_ANY,
529                     "<= index_add_values -1 (could not open/create %s%s)\n",
530                     at_cn, LDBM_SUFFIX, 0 );
531                 return( -1 );
532         }
533
534
535         for ( i = 0; vals[i] != NULL; i++ ) {
536                 /*
537                  * presence index entry
538                  */
539                 if ( indexmask & INDEX_PRESENCE ) {
540                         add_value( be, db, at_cn, INDEX_PRESENCE, "*", id );
541                 }
542
543                 Debug( LDAP_DEBUG_TRACE, "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
544                     syntax, SYNTAX_BIN, 0 );
545                 if ( syntax & SYNTAX_BIN ) {
546                         ldbm_cache_close( be, db );
547                         return( 0 );
548                 }
549
550                 bigbuf = NULL;
551                 len = vals[i]->bv_len;
552
553                 /* value + null */
554                 if ( len + 2 > sizeof(vbuf) ) {
555                         bigbuf = (char *) ch_malloc( len + 1 );
556                         val = bigbuf;
557                 } else {
558                         val = vbuf;
559                 }
560                 (void) memcpy( val, vals[i]->bv_val, len );
561                 val[len] = '\0';
562
563                 value_normalize( val, syntax );
564
565                 /* value_normalize could change the length of val */
566                 len = strlen( val );
567
568                 /*
569                  * equality index entry
570                  */
571                 if ( indexmask & INDEX_EQUALITY ) {
572                         add_value( be, db, at_cn, INDEX_EQUALITY, val, id );
573                 }
574
575                 /*
576                  * approximate index entry
577                  */
578                 if ( indexmask & INDEX_APPROX ) {
579                         for ( w = first_word( val ); w != NULL;
580                             w = next_word( w ) ) {
581                                 if ( (code = phonetic( w )) != NULL ) {
582                                         add_value( be, db, at_cn, INDEX_APPROX,
583                                             code, id );
584                                         free( code );
585                                 }
586                         }
587                 }
588
589                 /*
590                  * substrings index entry
591                  */
592                 if ( indexmask & INDEX_SUB ) {
593                         /* leading and trailing */
594                         if ( len > SUBLEN - 2 ) {
595                                 buf[0] = '^';
596                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
597                                         buf[j + 1] = val[j];
598                                 }
599                                 buf[SUBLEN] = '\0';
600
601                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
602
603                                 p = val + len - SUBLEN + 1;
604                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
605                                         buf[j] = p[j];
606                                 }
607                                 buf[SUBLEN - 1] = '$';
608                                 buf[SUBLEN] = '\0';
609
610                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
611                         }
612
613                         /* any */
614                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
615                                 for ( j = 0; j < SUBLEN; j++ ) {
616                                         buf[j] = p[j];
617                                 }
618                                 buf[SUBLEN] = '\0';
619
620                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
621                         }
622                 }
623
624                 if ( bigbuf != NULL ) {
625                         free( bigbuf );
626                 }
627         }
628         ldbm_cache_close( be, db );
629
630         return( 0 );
631 }
632
633 static int
634 index2prefix( int indextype )
635 {
636         int     prefix;
637
638         switch ( indextype ) {
639         case INDEX_EQUALITY:
640                 prefix = EQ_PREFIX;
641                 break;
642         case INDEX_APPROX:
643                 prefix = APPROX_PREFIX;
644                 break;
645         case INDEX_SUB:
646                 prefix = SUB_PREFIX;
647                 break;
648         default:
649                 prefix = UNKNOWN_PREFIX;
650                 break;
651         }
652
653         return( prefix );
654 }