]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
Apply devel IDL fixes...
[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_DELETE:
92                         rc =  index_change_values( be,
93                                                    mods->mod_type,
94                                                    mods->mod_bvalues,
95                                                    id,
96                                                    __INDEX_DEL_OP );
97                         break;
98                 case LDAP_MOD_SOFTADD:  /* SOFTADD means index was there */
99                         rc = 0;
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         if( vals == NULL ) {
264                 Debug( LDAP_DEBUG_TRACE,
265                "=> index_change_values( \"%s\", NULL, %ld, op=%s )\n", 
266                type, id, ((op == __INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
267                 return 0;
268         }
269
270         Debug( LDAP_DEBUG_TRACE,
271                "=> index_change_values( \"%s\", %ld, op=%s )\n", 
272                type, id, ((op == __INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
273
274         
275         if (op == __INDEX_ADD_OP) {
276
277             /* Add values */
278
279             idl_funct =  idl_insert_key;
280             mode = LDBM_WRCREAT;
281
282         } else {
283
284             /* Delete values */
285
286             idl_funct = idl_delete_key;
287             mode = LDBM_WRITER;
288
289         }
290
291         attr_normalize(type);
292         attr_masks( be->be_private, type, &indexmask, &syntax );
293
294         if ( indexmask == 0 ) {
295                 return( 0 );
296         }
297
298         /* at_cn = at_canonical_name( type ); */
299         at_cn = type;
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,
306                        LDBM_SUFFIX,
307                        ((mode==LDBM_WRCREAT)?"LDBM_WRCREAT":"LDBM_WRITER") );
308                 return( -1 );
309         }
310
311
312         for ( i = 0; vals[i] != NULL; i++ ) {
313                 /*
314                  * presence index entry
315                  */
316                 if ( indexmask & INDEX_PRESENCE ) {
317
318                         change_value( be, db, at_cn, INDEX_PRESENCE,
319                                       "*", id, idl_funct );
320
321                 }
322
323                 Debug( LDAP_DEBUG_TRACE,
324                        "index_change_values syntax 0x%x syntax bin 0x%x\n",
325                        syntax, SYNTAX_BIN, 0 );
326
327                 if ( syntax & SYNTAX_BIN ) {
328
329                         ldbm_cache_close( be, db );
330                         return( 0 );
331
332                 }
333
334                 bigbuf = NULL;
335                 len = vals[i]->bv_len;
336
337                 /* value + null */
338                 if ( len + 2 > sizeof(vbuf) ) {
339                         bigbuf = (char *) ch_malloc( len + 1 );
340                         val = bigbuf;
341                 } else {
342                         val = vbuf;
343                 }
344                 (void) memcpy( val, vals[i]->bv_val, len );
345                 val[len] = '\0';
346
347                 value_normalize( val, syntax );
348
349                 /* value_normalize could change the length of val */
350                 len = strlen( val );
351
352                 /*
353                  * equality index entry
354                  */
355                 if ( indexmask & INDEX_EQUALITY ) {
356                     
357                         change_value( be, db, at_cn, INDEX_EQUALITY,
358                                       val, id, idl_funct);
359
360                 }
361
362                 /*
363                  * approximate index entry
364                  */
365                 if ( indexmask & INDEX_APPROX ) {
366                         for ( w = first_word( val ); w != NULL;
367                             w = next_word( w ) ) {
368                                 if ( (code = phonetic( w )) != NULL ) {
369                                         change_value( be,
370                                                       db,
371                                                       at_cn,
372                                                       INDEX_APPROX,
373                                                       code,
374                                                       id,
375                                                       idl_funct );
376                                         free( code );
377                                 }
378                         }
379                 }
380
381                 /*
382                  * substrings index entry
383                  */
384                 if ( indexmask & INDEX_SUB ) {
385                         /* leading and trailing */
386                         if ( len > SUBLEN - 2 ) {
387                                 buf[0] = '^';
388                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
389                                         buf[j + 1] = val[j];
390                                 }
391                                 buf[SUBLEN] = '\0';
392
393                                 change_value( be, db, at_cn, INDEX_SUB,
394                                               buf, id, idl_funct );
395
396                                 p = val + len - SUBLEN + 1;
397                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
398                                         buf[j] = p[j];
399                                 }
400                                 buf[SUBLEN - 1] = '$';
401                                 buf[SUBLEN] = '\0';
402
403                                 change_value( be, db, at_cn, INDEX_SUB,
404                                               buf, id, idl_funct );
405                         }
406
407                         /* any */
408                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
409                                 for ( j = 0; j < SUBLEN; j++ ) {
410                                         buf[j] = p[j];
411                                 }
412                                 buf[SUBLEN] = '\0';
413
414                                 change_value( be, db, at_cn, INDEX_SUB,
415                                               buf, id, idl_funct );
416                         }
417                 }
418
419                 if ( bigbuf != NULL ) {
420                         free( bigbuf );
421                 }
422         }
423         ldbm_cache_close( be, db );
424
425         return( 0 );
426
427 }/* int index_change_values() */
428
429 static int
430 index2prefix( int indextype )
431 {
432         int     prefix;
433
434         switch ( indextype ) {
435         case INDEX_EQUALITY:
436                 prefix = EQ_PREFIX;
437                 break;
438         case INDEX_APPROX:
439                 prefix = APPROX_PREFIX;
440                 break;
441         case INDEX_SUB:
442                 prefix = SUB_PREFIX;
443                 break;
444         default:
445                 prefix = UNKNOWN_PREFIX;
446                 break;
447         }
448
449         return( prefix );
450 }