]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
96abe68b909fd84457cb118a633b2b580443a2a5
[openldap] / servers / slapd / back-ldbm / index.c
1 /* index.c - routines for dealing with attribute indexes */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/string.h>
13 #include <ac/socket.h>
14
15 #include "slap.h"
16 #include "back-ldbm.h"
17
18 #ifndef SLAPD_SCHEMA_NOT_COMPAT
19
20 static int      change_value(Backend *be,
21                           DBCache *db,
22                           char *type,
23                           int indextype,
24                           char *val,
25                           ID id,
26                           int
27                           (*idl_func)(Backend *, DBCache *, Datum, ID));
28 static int      index2prefix(int indextype);
29 #endif
30
31 int
32 index_add_entry(
33     Backend     *be,
34     Entry       *e
35 )
36 {
37 #ifndef SLAPD_SCHEMA_NOT_COMPAT
38         Attribute       *ap;
39         struct berval   bv;
40         struct berval   *bvals[2];
41
42         Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
43             e->e_dn, 0 );
44
45         /*
46          * dn index entry - make it look like an attribute so it works
47          * with index_change_values() call
48          */
49
50         bv.bv_val = ch_strdup( e->e_ndn );
51         bv.bv_len = strlen( bv.bv_val );
52         bvals[0] = &bv;
53         bvals[1] = NULL;
54
55         /* add the dn to the indexes */
56         {
57                 char *dn = ch_strdup("dn");
58 #ifdef SLAPD_SCHEMA_NOT_COMPAT
59                 /* not yet implemented */
60 #else
61                 index_change_values( be, dn, bvals, e->e_id, SLAP_INDEX_ADD_OP );
62 #endif
63                 free( dn );
64         }
65
66         free( bv.bv_val );
67
68         /* add each attribute to the indexes */
69         for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
70 #ifdef SLAPD_SCHEMA_NOT_COMPAT
71                 /* index_change_values( be, SLAP_INDEX_ADD_OP, e->e_id, ap ); */
72 #else
73                 index_change_values( be, ap->a_type, ap->a_vals, e->e_id,
74                                      SLAP_INDEX_ADD_OP );
75 #endif
76         }
77
78         Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
79             e->e_ndn, 0 );
80 #endif
81         return( 0 );
82 }
83
84 #ifndef SLAPD_SCHEMA_NOT_COMPAT
85 ID_BLOCK *
86 index_read(
87     Backend     *be,
88     char        *type,
89     int         indextype,
90     char        *val
91 )
92 {
93         DBCache *db;
94         Datum           key;
95         ID_BLOCK                *idl;
96         int             indexmask;
97         char            prefix;
98         char            *realval, *tmpval;
99         char            buf[BUFSIZ];
100
101         char            *at_cn;
102
103         ldbm_datum_init( key );
104
105         prefix = index2prefix( indextype );
106         Debug( LDAP_DEBUG_TRACE, "=> index_read(\"%c%s\"->\"%s\")\n",
107             prefix, type, val );
108
109         attr_mask( be->be_private, type, &indexmask );
110         if ( ! (indextype & indexmask) ) {
111                 idl =  idl_allids( be );
112                 Debug( LDAP_DEBUG_TRACE,
113                     "<= index_read %ld candidates (allids - not indexed)\n",
114                     idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
115                 return( idl );
116         }
117
118 #ifdef SLAPD_SCHEMA_NOT_COMPAT
119         at_cn = at_canonical_name( at_find( type ) );
120 #else
121         attr_normalize( type );
122         at_cn = at_canonical_name( type );
123 #endif
124
125         if ( at_cn == NULL ) {
126                 Debug( LDAP_DEBUG_ANY,
127                     "<= index_read no canonical name for type \"%s\"\n",
128                         type != NULL ? type : "(NULL)", 0, 0 );
129                 return( NULL );
130         }
131
132         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
133             == NULL ) {
134                 Debug( LDAP_DEBUG_ANY,
135                     "<= index_read NULL (could not open %s%s)\n",
136                         at_cn, LDBM_SUFFIX, 0 );
137                 return( NULL );
138         }
139
140         realval = val;
141         tmpval = NULL;
142         if ( prefix != UNKNOWN_PREFIX ) {
143                 unsigned int    len = strlen( val );
144
145                 if ( (len + 2) < sizeof(buf) ) {
146                         realval = buf;
147                 } else {
148                         /* value + prefix + null */
149                         tmpval = (char *) ch_malloc( len + 2 );
150                         realval = tmpval;
151                 }
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 /* Add or remove stuff from index files */
173
174 static int
175 change_value(
176     Backend             *be,
177     DBCache     *db,
178     char                *type,
179     int                 indextype,
180     char                *val,
181     ID                  id,
182     int                 (*idl_func)(Backend *, DBCache *, Datum, ID)
183 )
184 {
185         int     rc;
186         Datum   key;
187         char    *tmpval = NULL;
188         char    *realval = val;
189         char    buf[BUFSIZ];
190
191         char    prefix = index2prefix( indextype );
192
193         ldbm_datum_init( key );
194
195         Debug( LDAP_DEBUG_TRACE,
196                "=> change_value( \"%c%s\", op=%s )\n",
197                prefix, val, (idl_func == idl_insert_key ? "ADD":"DELETE") );
198
199         if ( prefix != UNKNOWN_PREFIX ) {
200               unsigned int     len = strlen( val );
201
202               if ( (len + 2) < sizeof(buf) ) {
203                         realval = buf;
204               } else {
205                         /* value + prefix + null */
206                         tmpval = (char *) ch_malloc( len + 2 );
207                         realval = tmpval;
208               }
209               realval[0] = prefix;
210               strcpy( &realval[1], val );
211         }
212
213         key.dptr = realval;
214         key.dsize = strlen( realval ) + 1;
215
216         rc = idl_func( be, db, key, id );
217
218         if ( tmpval != NULL ) {
219                 free( tmpval );
220         }
221
222         ldap_pvt_thread_yield();
223
224         Debug( LDAP_DEBUG_TRACE, "<= change_value %d\n", rc, 0, 0 );
225
226         return( rc );
227
228 }
229 #endif
230
231 int
232 index_change_values(
233     Backend             *be,
234     char                *type,
235     struct berval       **vals,
236     ID                  id,
237     unsigned int        op
238 )
239 {
240 #ifndef SLAPD_SCHEMA_NOT_COMPAT
241         char            *val, *p, *code, *w;
242         unsigned        i, j, len;
243         int             indexmask, syntax;
244         char            buf[SUBLEN + 1];
245         char            vbuf[BUFSIZ];
246         char            *bigbuf;
247         DBCache *db;
248
249         int             (*idl_funct)(Backend *,
250                                     DBCache *,
251                                     Datum, ID);
252         char            *at_cn; /* Attribute canonical name */
253         int             mode;
254
255         if( vals == NULL ) {
256                 Debug( LDAP_DEBUG_TRACE,
257                         "=> index_change_values( %s, NULL, %ld, op=%s )\n", 
258                         type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
259                 return 0;
260         }
261
262         Debug( LDAP_DEBUG_TRACE,
263                "=> index_change_values( \"%s\", %ld, op=%s )\n", 
264                type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
265
266         
267         if (op == SLAP_INDEX_ADD_OP) {
268             /* Add values */
269             idl_funct =  idl_insert_key;
270             mode = LDBM_WRCREAT;
271
272         } else {
273             /* Delete values */
274             idl_funct = idl_delete_key;
275             mode = LDBM_WRITER;
276         }
277
278 #ifndef SLAPD_SCHEMA_NOT_COMPAT
279         attr_normalize(type);
280 #endif
281         attr_mask( be->be_private, type, &indexmask );
282
283         if ( indexmask == 0 ) {
284                 return( 0 );
285         }
286
287 #ifdef SLAPD_SCHEMA_NOT_COMPAT
288         at_cn = at_canonical_name( at_find( type ) );
289 #else
290         syntax = attr_syntax( type );
291         at_cn = at_canonical_name( type );
292 #endif
293
294         if ( at_cn == NULL ) {
295                 Debug( LDAP_DEBUG_ANY,
296                     "<= index_change_values no canonical name for type \"%s\"\n",
297                         type != NULL ? type : "(NULL)", 0, 0 );
298                 return( -1 );
299         }
300
301         if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, mode ))
302              == NULL ) {
303                 Debug( LDAP_DEBUG_ANY,
304                        "<= index_change_values (couldn't open(%s%s),md=%s)\n",
305                        at_cn, LDBM_SUFFIX,
306                        ((mode==LDBM_WRCREAT)?"LDBM_WRCREAT":"LDBM_WRITER") );
307                 return( -1 );
308         }
309
310 #ifdef SLAPD_SCHEMA_NOT_COMPAT
311         /* not yet implemented */
312 #else
313         /*
314          * presence index entry
315          */
316         if ( indexmask & SLAP_INDEX_PRESENCE ) {
317                 change_value( be, db, at_cn, SLAP_INDEX_PRESENCE,
318                         "*", id, idl_funct );
319         }
320
321         if ( syntax & SYNTAX_BIN ) {
322                 goto done;
323         }
324
325         for ( i = 0; vals[i] != NULL; i++ ) {
326                 Debug( LDAP_DEBUG_TRACE,
327                        "index_change_values syntax 0x%x\n",
328                        syntax, 0, 0 );
329
330                 bigbuf = NULL;
331                 len = vals[i]->bv_len;
332
333                 /* value + null */
334                 if ( len + 2 > sizeof(vbuf) ) {
335                         bigbuf = (char *) ch_malloc( len + 1 );
336                         val = bigbuf;
337                 } else {
338                         val = vbuf;
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                 len = strlen( val );
347
348                 /*
349                  * equality index entry
350                  */
351                 if ( indexmask & SLAP_INDEX_EQUALITY ) {
352                         change_value( be, db, at_cn, SLAP_INDEX_EQUALITY,
353                                       val, id, idl_funct);
354                 }
355
356                 /*
357                  * approximate index entry
358                  */
359                 if ( indexmask & SLAP_INDEX_APPROX ) {
360                         for ( w = first_word( val ); w != NULL;
361                             w = next_word( w ) ) {
362                                 if ( (code = phonetic( w )) != NULL ) {
363                                         change_value( be,
364                                                       db,
365                                                       at_cn,
366                                                       SLAP_INDEX_APPROX,
367                                                       code,
368                                                       id,
369                                                       idl_funct );
370                                         free( code );
371                                 }
372                         }
373                 }
374
375                 /*
376                  * substrings index entry
377                  */
378                 if ( indexmask & SLAP_INDEX_SUBSTR ) {
379                         /* leading and trailing */
380                         if ( len > SUBLEN - 2 ) {
381                                 buf[0] = '^';
382                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
383                                         buf[j + 1] = val[j];
384                                 }
385                                 buf[SUBLEN] = '\0';
386
387                                 change_value( be, db, at_cn, SLAP_INDEX_SUBSTR,
388                                               buf, id, idl_funct );
389
390                                 p = val + len - SUBLEN + 1;
391                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
392                                         buf[j] = p[j];
393                                 }
394                                 buf[SUBLEN - 1] = '$';
395                                 buf[SUBLEN] = '\0';
396
397                                 change_value( be, db, at_cn, SLAP_INDEX_SUBSTR,
398                                               buf, id, idl_funct );
399                         }
400
401                         /* any */
402                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
403                                 for ( j = 0; j < SUBLEN; j++ ) {
404                                         buf[j] = p[j];
405                                 }
406                                 buf[SUBLEN] = '\0';
407
408                                 change_value( be, db, at_cn, SLAP_INDEX_SUBSTR,
409                                               buf, id, idl_funct );
410                         }
411                 }
412
413                 if ( bigbuf != NULL ) {
414                         free( bigbuf );
415                 }
416         }
417 #endif
418
419 done:
420         ldbm_cache_close( be, db );
421 #endif
422         return( 0 );
423 }
424
425 #ifndef SLAPD_SCHEMA_NOT_COMPAT
426 static int
427 index2prefix( int indextype )
428 {
429         int     prefix;
430
431         switch ( indextype ) {
432         case SLAP_INDEX_EQUALITY:
433                 prefix = EQ_PREFIX;
434                 break;
435         case SLAP_INDEX_APPROX:
436                 prefix = APPROX_PREFIX;
437                 break;
438         case SLAP_INDEX_SUBSTR:
439                 prefix = SUB_PREFIX;
440                 break;
441         default:
442                 prefix = UNKNOWN_PREFIX;
443                 break;
444         }
445
446         return( prefix );
447 }
448 #endif