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