]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
c7bc9c1135be8f49908fdc6b3e61ed3b8c5726f0
[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         return 0;
197
198 }/* static int delete_value() */
199
200 static int
201 add_value(
202     Backend             *be,
203     struct dbcache      *db,
204     char                *type,
205     int                 indextype,
206     char                *val,
207     ID                  id
208 )
209 {
210         int     rc;
211         Datum   key;
212         /* XXX do we need idl ??? */
213         ID_BLOCK        *idl = NULL;
214         char    *tmpval = NULL;
215         char    *realval = val;
216         char    buf[BUFSIZ];
217
218         char    prefix = index2prefix( indextype );
219
220         ldbm_datum_init( key );
221
222         Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
223
224         if ( prefix != UNKNOWN_PREFIX ) {
225               unsigned int     len = strlen( val );
226
227               if ( (len + 2) < sizeof(buf) ) {
228                         realval = buf;
229                 } else {
230                         /* value + prefix + null */
231                         tmpval = (char *) ch_malloc( len + 2 );
232                         realval = tmpval;
233                 }
234               realval[0] = prefix;
235               strcpy( &realval[1], val );
236         }
237
238         key.dptr = realval;
239         key.dsize = strlen( realval ) + 1;
240
241         rc = idl_insert_key( be, db, key, id );
242
243         if ( tmpval != NULL ) {
244                 free( tmpval );
245         }
246
247         if( idl != NULL ) {
248                 idl_free( idl );
249         }
250
251         ldap_pvt_thread_yield();
252
253         /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
254         return( rc );
255 }
256
257 /* Remove entries from index files */
258
259 int
260 index_delete_values(
261     Backend             *be,
262     char                *type,
263     struct berval       **vals,
264     ID                  id
265 )
266 {
267         int             indexmask, syntax;
268         char            *at_cn; /* Attribute canonical name */
269         struct dbcache  *db;
270         char            *val, *p, *code, *w;
271         unsigned        i, j, len;
272         char            buf[SUBLEN + 1];
273         char            vbuf[BUFSIZ];
274         char            *bigbuf;
275
276
277         Debug( LDAP_DEBUG_TRACE,
278                "=> index_delete_values( \"%s\", %ld )\n", 
279                (type ? type : "(NULL)"),
280                id,
281                0 );
282                
283         attr_normalize(type);
284         attr_masks( be->be_private, type, &indexmask, &syntax );
285         
286         if ( indexmask == 0 ) {
287                 return( 0 );
288         }
289
290         at_cn = at_canonical_name( type );
291
292         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRITER ))
293              == NULL ) {
294
295                 Debug( LDAP_DEBUG_ANY,
296                        "<= index_delete_values -1 (could not open(wr) %s%s)\n",
297                        at_cn,
298                        LDBM_SUFFIX,
299                        0 );
300                 return( -1 );
301
302         }
303
304         /* Remove each value from index file */
305         
306         for ( i = 0; vals[i] != NULL; i++ ) {
307
308                 /*
309                  * Presence index entry
310                  */
311
312                 if ( indexmask & INDEX_PRESENCE ) {
313                         delete_value( be, db, at_cn, INDEX_PRESENCE, "*", id );
314                 }
315
316                 Debug( LDAP_DEBUG_TRACE,
317                        "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
318                        syntax, SYNTAX_BIN, 0 );
319
320                 if ( syntax & SYNTAX_BIN ) {
321                         ldbm_cache_close( be, db );
322                         return( 0 );
323                 }
324
325                 bigbuf = NULL;
326                 len = vals[i]->bv_len;
327
328                 /* value + null */
329                 if ( len + 2 > sizeof(vbuf) ) {
330
331                         bigbuf = (char *) ch_malloc( len + 1 );
332                         val = bigbuf;
333
334                 } else {
335
336                         val = vbuf;
337
338                 }
339
340                 (void) memcpy( val, vals[i]->bv_val, len );
341                 val[len] = '\0';
342
343                 value_normalize( val, syntax );
344
345                 /* value_normalize could change the length of val */
346
347                 len = strlen( val );
348
349                 /*
350                  * equality index entry
351                  */
352
353                 if ( indexmask & INDEX_EQUALITY ) {
354                     
355                         delete_value( be, db, at_cn, INDEX_EQUALITY, val, id );
356
357                 }
358
359                 /*
360                  * approximate index entry
361                  */
362                 if ( indexmask & INDEX_APPROX ) {
363                     
364                         for ( w = first_word( val );
365                               w != NULL;
366                               w = next_word( w ) ) {
367                             
368                                 if ( (code = phonetic( w )) != NULL ) {
369
370                                         delete_value( be,
371                                                       db,
372                                                       at_cn,
373                                                       INDEX_APPROX,
374                                                       code,
375                                                       id );
376                                         free( code );
377                                 }
378                         }
379
380                 }
381
382                 /*
383                  * substrings index entry
384                  */
385
386                 if ( indexmask & INDEX_SUB ) {
387
388                         /* leading and trailing */
389                         if ( len > SUBLEN - 2 ) {
390
391                                 buf[0] = '^';
392                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
393                                         buf[j + 1] = val[j];
394                                 }
395                                 buf[SUBLEN] = '\0';
396
397                                 delete_value( be,
398                                               db,
399                                               at_cn,
400                                               INDEX_SUB,
401                                               buf,
402                                               id );
403
404                                 p = val + len - SUBLEN + 1;
405                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
406                                         buf[j] = p[j];
407                                 }
408                                 buf[SUBLEN - 1] = '$';
409                                 buf[SUBLEN] = '\0';
410
411                                 delete_value( be,
412                                               db,
413                                               at_cn,
414                                               INDEX_SUB,
415                                               buf,
416                                               id );
417
418                         }
419
420                         /* any */
421
422                         for (p = val; p < (val + len - SUBLEN + 1); p++) {
423
424                                 for ( j = 0; j < SUBLEN; j++ ) {
425                                         buf[j] = p[j];
426                                 }
427                                 buf[SUBLEN] = '\0';
428
429                                 delete_value( be,
430                                               db,
431                                               at_cn,
432                                               INDEX_SUB,
433                                               buf,
434                                               id );
435                         }/* for (p = val; p < (val + len - SUBLEN + 1); p++) */
436
437                 }/* if ( indexmask & INDEX_SUB ) */
438
439                 if ( bigbuf != NULL ) {
440
441                         free( bigbuf );
442
443                 }
444
445         }/* for ( i = 0; vals[i] != NULL; i++ ) */
446
447         ldbm_cache_close( be, db );
448
449         return 0;
450
451 }
452
453 int
454 index_add_values(
455     Backend             *be,
456     char                *type,
457     struct berval       **vals,
458     ID                  id
459 )
460 {
461         char            *val, *p, *code, *w;
462         unsigned        i, j, len;
463         int             indexmask, syntax;
464         char            buf[SUBLEN + 1];
465         char            vbuf[BUFSIZ];
466         char            *bigbuf;
467         struct dbcache  *db;
468
469         char            *at_cn; /* Attribute canonical name */
470
471         Debug( LDAP_DEBUG_TRACE, "=> index_add_values( \"%s\", %ld )\n", type,
472             id, 0 );
473         attr_normalize(type);
474         attr_masks( be->be_private, type, &indexmask, &syntax );
475         if ( indexmask == 0 ) {
476                 return( 0 );
477         }
478         at_cn = at_canonical_name( type );
479         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
480             == NULL ) {
481                 Debug( LDAP_DEBUG_ANY,
482                     "<= index_add_values -1 (could not open/create %s%s)\n",
483                     at_cn, LDBM_SUFFIX, 0 );
484                 return( -1 );
485         }
486
487
488         for ( i = 0; vals[i] != NULL; i++ ) {
489                 /*
490                  * presence index entry
491                  */
492                 if ( indexmask & INDEX_PRESENCE ) {
493                         add_value( be, db, at_cn, INDEX_PRESENCE, "*", id );
494                 }
495
496                 Debug( LDAP_DEBUG_TRACE, "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
497                     syntax, SYNTAX_BIN, 0 );
498                 if ( syntax & SYNTAX_BIN ) {
499                         ldbm_cache_close( be, db );
500                         return( 0 );
501                 }
502
503                 bigbuf = NULL;
504                 len = vals[i]->bv_len;
505
506                 /* value + null */
507                 if ( len + 2 > sizeof(vbuf) ) {
508                         bigbuf = (char *) ch_malloc( len + 1 );
509                         val = bigbuf;
510                 } else {
511                         val = vbuf;
512                 }
513                 (void) memcpy( val, vals[i]->bv_val, len );
514                 val[len] = '\0';
515
516                 value_normalize( val, syntax );
517
518                 /* value_normalize could change the length of val */
519                 len = strlen( val );
520
521                 /*
522                  * equality index entry
523                  */
524                 if ( indexmask & INDEX_EQUALITY ) {
525                         add_value( be, db, at_cn, INDEX_EQUALITY, val, id );
526                 }
527
528                 /*
529                  * approximate index entry
530                  */
531                 if ( indexmask & INDEX_APPROX ) {
532                         for ( w = first_word( val ); w != NULL;
533                             w = next_word( w ) ) {
534                                 if ( (code = phonetic( w )) != NULL ) {
535                                         add_value( be, db, at_cn, INDEX_APPROX,
536                                             code, id );
537                                         free( code );
538                                 }
539                         }
540                 }
541
542                 /*
543                  * substrings index entry
544                  */
545                 if ( indexmask & INDEX_SUB ) {
546                         /* leading and trailing */
547                         if ( len > SUBLEN - 2 ) {
548                                 buf[0] = '^';
549                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
550                                         buf[j + 1] = val[j];
551                                 }
552                                 buf[SUBLEN] = '\0';
553
554                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
555
556                                 p = val + len - SUBLEN + 1;
557                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
558                                         buf[j] = p[j];
559                                 }
560                                 buf[SUBLEN - 1] = '$';
561                                 buf[SUBLEN] = '\0';
562
563                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
564                         }
565
566                         /* any */
567                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
568                                 for ( j = 0; j < SUBLEN; j++ ) {
569                                         buf[j] = p[j];
570                                 }
571                                 buf[SUBLEN] = '\0';
572
573                                 add_value( be, db, at_cn, INDEX_SUB, buf, id );
574                         }
575                 }
576
577                 if ( bigbuf != NULL ) {
578                         free( bigbuf );
579                 }
580         }
581         ldbm_cache_close( be, db );
582
583         return( 0 );
584 }
585
586 static int
587 index2prefix( int indextype )
588 {
589         int     prefix;
590
591         switch ( indextype ) {
592         case INDEX_EQUALITY:
593                 prefix = EQ_PREFIX;
594                 break;
595         case INDEX_APPROX:
596                 prefix = APPROX_PREFIX;
597                 break;
598         case INDEX_SUB:
599                 prefix = SUB_PREFIX;
600                 break;
601         default:
602                 prefix = UNKNOWN_PREFIX;
603                 break;
604         }
605
606         return( prefix );
607 }