]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/index.c
include portable.h
[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 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include "slap.h"
10 #include "back-ldbm.h"
11
12 extern char             *first_word();
13 extern char             *next_word();
14 extern char             *phonetic();
15 extern IDList           *idl_fetch();
16 extern IDList           *idl_allids();
17 extern struct dbcache   *ldbm_cache_open();
18
19 int     index_add_values();
20
21 static int      add_value();
22 static int      index2prefix();
23
24 int
25 index_add_entry(
26     Backend     *be,
27     Entry       *e
28 )
29 {
30         Attribute       *ap;
31         char            *dnval;
32         struct berval   bv;
33         struct berval   *bvals[2];
34
35         Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
36             e->e_dn, 0 );
37
38         /*
39          * dn index entry - make it look like an attribute so it works
40          * with index_add_values() call
41          */
42
43         bv.bv_val = strdup( e->e_dn );
44         bv.bv_len = strlen( bv.bv_val );
45         (void) dn_normalize_case( bv.bv_val );
46         bvals[0] = &bv;
47         bvals[1] = NULL;
48
49         /* add the dn to the indexes */
50         index_add_values( be, "dn", bvals, e->e_id );
51
52         free( bv.bv_val );
53
54         /* add each attribute to the indexes */
55         for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
56                 index_add_values( be, ap->a_type, ap->a_vals, e->e_id );
57         }
58
59         Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
60             e->e_dn, 0 );
61         return( 0 );
62 }
63
64 int
65 index_add_mods(
66     Backend     *be,
67     LDAPMod     *mods,
68     ID          id
69 )
70 {
71         int     rc;
72
73         for ( ; mods != NULL; mods = mods->mod_next ) {
74                 switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) {
75                 case LDAP_MOD_ADD:
76                 case LDAP_MOD_REPLACE:
77                         rc = index_add_values( be, mods->mod_type,
78                             mods->mod_bvalues, id );
79                         break;
80
81                 case LDAP_MOD_DELETE:
82                         rc = 0;
83                         break;
84                 }
85
86                 if ( rc != 0 ) {
87                         return( rc );
88                 }
89         }
90
91         return( 0 );
92 }
93
94 IDList *
95 index_read(
96     Backend     *be,
97     char        *type,
98     int         indextype,
99     char        *val
100 )
101 {
102         struct dbcache  *db;
103         Datum           key;
104         IDList          *idl;
105         int             indexmask, syntax;
106         char            prefix;
107         char            *realval, *tmpval;
108         char            buf[BUFSIZ];
109
110 #ifdef LDBM_USE_DB2
111         memset( &key, 0, sizeof( key ) );
112 #endif
113
114         prefix = index2prefix( indextype );
115         Debug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" \"%c\" \"%s\" )\n",
116             type, prefix, val );
117
118         attr_masks( be->be_private, type, &indexmask, &syntax );
119         if ( ! (indextype & indexmask) ) {
120                 idl =  idl_allids( be );
121                 Debug( LDAP_DEBUG_TRACE,
122                     "<= index_read %d candidates (allids - not indexed)\n",
123                     idl ? idl->b_nids : 0, 0, 0 );
124                 return( idl );
125         }
126
127         attr_normalize( type );
128         if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
129             == NULL ) {
130                 Debug( LDAP_DEBUG_ANY,
131                     "<= index_read NULL (could not open %s%s)\n", type,
132                     LDBM_SUFFIX, 0 );
133                 return( NULL );
134         }
135
136         realval = val;
137         tmpval = NULL;
138         if ( prefix != '\0' ) {
139               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               realval[0] = prefix;
149               strcpy( &realval[1], val );
150         }
151
152         key.dptr = realval;
153         key.dsize = strlen( realval ) + 1;
154
155         idl = idl_fetch( be, db, key );
156       if ( tmpval != NULL ) {
157               free( tmpval );
158       }
159
160         ldbm_cache_close( be, db );
161
162         Debug( LDAP_DEBUG_TRACE, "<= index_read %d candidates\n",
163             idl ? idl->b_nids : 0, 0, 0 );
164         return( idl );
165 }
166
167 static int
168 add_value(
169     Backend             *be,
170     struct dbcache      *db,
171     char                *type,
172     int                 indextype,
173     char                *val,
174     ID                  id
175 )
176 {
177         int     rc;
178         Datum   key;
179         IDList  *idl;
180         char    prefix;
181         char    *realval, *tmpval, *s;
182         char    buf[BUFSIZ];
183
184 #ifdef LDBM_USE_DB2
185         memset( &key, 0, sizeof( key ) );
186 #endif
187
188         prefix = index2prefix( indextype );
189         Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
190
191         realval = val;
192         tmpval = NULL;
193         idl = NULL;
194         if ( prefix != '\0' ) {
195               int     len = strlen( val );
196
197               if ( (len + 2) < sizeof(buf) ) {
198                         realval = buf;
199                 } else {
200                         /* value + prefix + null */
201                         tmpval = (char *) ch_malloc( len + 2 );
202                         realval = tmpval;
203                 }
204               realval[0] = prefix;
205               strcpy( &realval[1], val );
206         }
207
208         key.dptr = realval;
209         key.dsize = strlen( realval ) + 1;
210
211         rc = idl_insert_key( be, db, key, id );
212
213         if ( tmpval != NULL ) {
214                 free( tmpval );
215         }
216         idl_free( idl );
217
218         pthread_yield();
219
220         /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
221         return( rc );
222 }
223
224 int
225 index_add_values(
226     Backend             *be,
227     char                *type,
228     struct berval       **vals,
229     ID                  id
230 )
231 {
232         char            *val, *p, *code, *w;
233         int             i, j, len;
234         int             indexmask, syntax;
235         char            buf[SUBLEN + 1];
236         char            vbuf[BUFSIZ];
237         char            *bigbuf;
238         struct dbcache  *db;
239
240         Debug( LDAP_DEBUG_TRACE, "=> index_add_values( \"%s\", %ld )\n", type,
241             id, 0 );
242
243         attr_masks( be->be_private, type, &indexmask, &syntax );
244         if ( indexmask == 0 ) {
245                 return( 0 );
246         }
247
248         if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
249             == NULL ) {
250                 Debug( LDAP_DEBUG_ANY,
251                     "<= index_add_values -1 (could not open/create %s%s)\n",
252                     type, LDBM_SUFFIX, 0 );
253                 return( -1 );
254         }
255
256
257         for ( i = 0; vals[i] != NULL; i++ ) {
258                 /*
259                  * presence index entry
260                  */
261                 if ( indexmask & INDEX_PRESENCE ) {
262                         add_value( be, db, type, INDEX_PRESENCE, "*", id );
263                 }
264
265                 Debug( LDAP_DEBUG_TRACE, "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
266                     syntax, SYNTAX_BIN, 0 );
267                 if ( syntax & SYNTAX_BIN ) {
268                         ldbm_cache_close( be, db );
269                         return( 0 );
270                 }
271
272                 bigbuf = NULL;
273                 len = vals[i]->bv_len;
274
275                 /* value + null */
276                 if ( len + 2 > sizeof(vbuf) ) {
277                         bigbuf = (char *) ch_malloc( len + 1 );
278                         val = bigbuf;
279                 } else {
280                         val = vbuf;
281                 }
282                 (void) memcpy( val, vals[i]->bv_val, len );
283                 val[len] = '\0';
284
285                 value_normalize( val, syntax );
286
287                 /*
288                  * equality index entry
289                  */
290                 if ( indexmask & INDEX_EQUALITY ) {
291                         add_value( be, db, type, INDEX_EQUALITY, val, id );
292                 }
293
294                 /*
295                  * approximate index entry
296                  */
297                 if ( indexmask & INDEX_APPROX ) {
298                         for ( w = first_word( val ); w != NULL;
299                             w = next_word( w ) ) {
300                                 if ( (code = phonetic( w )) != NULL ) {
301                                         add_value( be, db, type, INDEX_APPROX,
302                                             code, id );
303                                         free( code );
304                                 }
305                         }
306                 }
307
308                 /*
309                  * substrings index entry
310                  */
311                 if ( indexmask & INDEX_SUB ) {
312                         /* leading and trailing */
313                         if ( len > SUBLEN - 2 ) {
314                                 buf[0] = '^';
315                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
316                                         buf[j + 1] = val[j];
317                                 }
318                                 buf[SUBLEN] = '\0';
319
320                                 add_value( be, db, type, INDEX_SUB, buf, id );
321
322                                 p = val + len - SUBLEN + 1;
323                                 for ( j = 0; j < SUBLEN - 1; j++ ) {
324                                         buf[j] = p[j];
325                                 }
326                                 buf[SUBLEN - 1] = '$';
327                                 buf[SUBLEN] = '\0';
328
329                                 add_value( be, db, type, INDEX_SUB, buf, id );
330                         }
331
332                         /* any */
333                         for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
334                                 for ( j = 0; j < SUBLEN; j++ ) {
335                                         buf[j] = p[j];
336                                 }
337                                 buf[SUBLEN] = '\0';
338
339                                 add_value( be, db, type, INDEX_SUB, buf, id );
340                         }
341                 }
342
343                 if ( bigbuf != NULL ) {
344                         free( bigbuf );
345                 }
346         }
347         ldbm_cache_close( be, db );
348
349         return( 0 );
350 }
351
352 static int
353 index2prefix( int indextype )
354 {
355         int     prefix;
356
357         switch ( indextype ) {
358         case INDEX_EQUALITY:
359                 prefix = EQ_PREFIX;
360                 break;
361         case INDEX_APPROX:
362                 prefix = APPROX_PREFIX;
363                 break;
364         case INDEX_SUB:
365                 prefix = SUB_PREFIX;
366                 break;
367         default:
368                 prefix = '\0';
369                 break;
370         }
371
372         return( prefix );
373 }