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