index.c 6.64 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* index.c - routines for dealing with attribute indexes */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
6
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
7

Kurt Zeilenga's avatar
Kurt Zeilenga committed
8
9
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
10
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
11
12
13
14

#include <ac/string.h>
#include <ac/socket.h>

Kurt Zeilenga's avatar
Kurt Zeilenga committed
15
16
17
#include "slap.h"
#include "back-ldbm.h"

18
static slap_mask_t index_mask(
19
20
21
	Backend *be,
	AttributeDescription *desc,
	char **dbname,
22
	struct berval *atname )
23
24
{
	AttributeType *at;
25
	slap_mask_t mask = 0;
26

27
	attr_mask( be->be_private, desc, &mask );
28
29

	if( mask ) {
30
		*atname = desc->ad_cname;
31
		*dbname = desc->ad_cname.bv_val;
32
33
34
		return mask;
	}

35
36
37
38
	/* If there is a language tag, did we ever index the base
	 * type? If so, check for mask, otherwise it's not there.
	 */
	if( slap_ad_is_lang( desc ) && desc != desc->ad_type->sat_ad ) {
39
		/* has language tag */
40
		attr_mask( be->be_private, desc->ad_type->sat_ad, &mask );
41

42
		if( !( mask & SLAP_INDEX_NOLANG ) ) {
43
			*atname = desc->ad_type->sat_cname;
44
			*dbname = desc->ad_type->sat_cname.bv_val;
45
46
47
48
49
50
			return mask;
		}
	}

	/* see if supertype defined mask for its subtypes */
	for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
51
52
53
54
55
		/* If no AD, we've never indexed this type */
		if (!at->sat_ad)
			continue;
		
		attr_mask( be->be_private, at->sat_ad, &mask );
56
57
58

		if( mask & SLAP_INDEX_AUTO_SUBTYPES ) {
			*atname = desc->ad_type->sat_cname;
59
			*dbname = at->sat_cname.bv_val;
60
61
			return mask;
		}
62
		if( !( mask & SLAP_INDEX_NOSUBTYPES ) ) {
63
			*atname = at->sat_cname;
64
			*dbname = at->sat_cname.bv_val;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
			return mask;
		}

		if( mask ) break;
	}

	return 0;
}

int index_param(
	Backend *be,
	AttributeDescription *desc,
	int ftype,
	char **dbnamep,
79
	slap_mask_t *maskp,
80
	struct berval *prefixp )
81
{
82
	slap_mask_t mask;
83
84
	char *dbname;

85
	mask = index_mask( be, desc, &dbname, prefixp );
86
87
88
89
90

	if( mask == 0 ) {
		return LDAP_INAPPROPRIATE_MATCHING;
	}

91
	switch( ftype ) {
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	case LDAP_FILTER_PRESENT:
		if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
			goto done;
		}
		break;

	case LDAP_FILTER_APPROX:
		if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
			goto done;
		}
		/* fall thru */

	case LDAP_FILTER_EQUALITY:
		if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
			goto done;
		}
		break;

	case LDAP_FILTER_SUBSTRINGS:
		if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
			goto done;
		}
		break;

	default:
		return LDAP_OTHER;
	}

	return LDAP_INAPPROPRIATE_MATCHING;

done:
	*dbnamep = dbname;
	*maskp = mask;
	return LDAP_SUCCESS;
}

static int indexer(
	Backend *be,
	char *dbname,
131
	struct berval *atname,
132
133
134
	struct berval **vals,
	ID id,
	int op,
135
	slap_mask_t mask )
136
137
138
139
140
{
	int rc, i;
	const char *text;
    DBCache	*db;
	AttributeDescription *ad = NULL;
141
	struct berval *keys;
142
143
144

	assert( mask );

145
	rc = slap_bv2ad( atname, &ad, &text );
146
147
148
149
150
151

	if( rc != LDAP_SUCCESS ) return rc;

	db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
	
	if ( db == NULL ) {
Gary Williams's avatar
Gary Williams committed
152
153
154
155
156
#ifdef NEW_LOGGING
		LDAP_LOG(( "index", LDAP_LEVEL_ERR,
			   "index_read: Could not open db %s%s\n",
			   dbname, LDBM_SUFFIX ));
#else
157
158
159
		Debug( LDAP_DEBUG_ANY,
		    "<= index_read NULL (could not open %s%s)\n",
			dbname, LDBM_SUFFIX, 0 );
Gary Williams's avatar
Gary Williams committed
160
161
#endif

162
163
164
165
		return LDAP_OTHER;
	}

	if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
166
		key_change( be, db, atname, id, op );
167
168
169
170
	}

	if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
		rc = ad->ad_type->sat_equality->smr_indexer(
171
			LDAP_FILTER_EQUALITY,
172
173
174
			mask,
			ad->ad_type->sat_syntax,
			ad->ad_type->sat_equality,
175
			atname, vals, &keys );
176

Kurt Zeilenga's avatar
Kurt Zeilenga committed
177
		if( rc == LDAP_SUCCESS && keys != NULL ) {
178
179
			for( i=0; keys[i].bv_val != NULL; i++ ) {
				key_change( be, db, &keys[i], id, op );
Gary Williams's avatar
Gary Williams committed
180
			}
181
			bvarray_free( keys );
182
183
184
185
186
		}
	}

	if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
		rc = ad->ad_type->sat_approx->smr_indexer(
187
			LDAP_FILTER_APPROX,
188
189
190
			mask,
			ad->ad_type->sat_syntax,
			ad->ad_type->sat_approx,
191
			atname, vals, &keys );
192

Kurt Zeilenga's avatar
Kurt Zeilenga committed
193
		if( rc == LDAP_SUCCESS && keys != NULL ) {
194
195
			for( i=0; keys[i].bv_val != NULL; i++ ) {
				key_change( be, db, &keys[i], id, op );
Gary Williams's avatar
Gary Williams committed
196
			}
197
			bvarray_free( keys );
198
199
200
201
202
		}
	}

	if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
		rc = ad->ad_type->sat_substr->smr_indexer(
203
			LDAP_FILTER_SUBSTRINGS,
204
205
206
			mask,
			ad->ad_type->sat_syntax,
			ad->ad_type->sat_substr,
207
			atname, vals, &keys );
208

Kurt Zeilenga's avatar
Kurt Zeilenga committed
209
		if( rc == LDAP_SUCCESS && keys != NULL ) {
210
211
			for( i=0; keys[i].bv_val != NULL; i++ ) {
				key_change( be, db, &keys[i], id, op );
Gary Williams's avatar
Gary Williams committed
212
			}
213
			bvarray_free( keys );
214
215
216
217
218
219
220
221
222
223
		}
	}

	ldbm_cache_close( be, db );
	return LDAP_SUCCESS;
}

static int index_at_values(
	Backend *be,
	AttributeType *type,
224
	struct berval *lang,
225
226
227
228
	struct berval **vals,
	ID id,
	int op,
	char ** dbnamep,
229
	slap_mask_t *maskp )
230
{
231
	slap_mask_t mask = 0;
232
	slap_mask_t tmpmask = 0;
233
234
235
236
237
238
239
240
241

	if( type->sat_sup ) {
		/* recurse */
		(void) index_at_values( be,
			type->sat_sup, lang,
			vals, id, op,
			dbnamep, &tmpmask );
	}

242
	/* If this type has no AD, we've never used it before */
243
	if( type->sat_ad ) {
244
		attr_mask( be->be_private, type->sat_ad, &mask );
245
	}
246
247

	if( mask ) {
248
		*dbnamep = type->sat_cname.bv_val;
249
250
251
252
253
254
	} else if ( tmpmask & SLAP_INDEX_AUTO_SUBTYPES ) {
		mask = tmpmask;
	}

	if( mask ) {
		indexer( be, *dbnamep,
255
			&type->sat_cname,
256
257
258
			vals, id, op,
			mask );
	}
259

260
	if( lang->bv_len ) {
261
		char *dbname = NULL;
262
263
		struct berval lname;
		AttributeDescription *desc;
264

265
266
		tmpmask = 0;
		lname.bv_val = NULL;
267

268
		desc = ad_find_lang(type, lang);
269
		if( desc ) {
270
			attr_mask( be->be_private, desc, &tmpmask );
271
		}
272
273

		if( tmpmask ) {
274
275
276
			dbname = desc->ad_cname.bv_val;
			lname = desc->ad_cname;
			mask = tmpmask;
277
278
279
		}

		if( dbname != NULL ) {
280
			indexer( be, dbname, &lname,
281
				vals, id, op,
282
				mask );
283
			if( !tmpmask ) {
284
				ch_free( lname.bv_val );
285
			}
286
287
288
289
290
291
292
293
294
295
296
297
298
299
		}
	}

	return LDAP_SUCCESS;
}

int index_values(
	Backend *be,
	AttributeDescription *desc,
	struct berval **vals,
	ID id,
	int op )
{
	char *dbname = NULL;
300
	slap_mask_t mask;
301
302

	(void) index_at_values( be,
303
		desc->ad_type, &desc->ad_lang,
304
305
306
307
308
309
		vals, id, op,
		&dbname, &mask );

	return LDAP_SUCCESS;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
310
int
311
index_entry(
Kurt Zeilenga's avatar
Kurt Zeilenga committed
312
    Backend	*be,
313
	int op,
314
315
    Entry *e,
	Attribute *ap )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
316
{
Gary Williams's avatar
Gary Williams committed
317
318
319
320
321
322
#ifdef NEW_LOGGING
	LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
		   "index_entry: %s (%s)%ld\n",
		   op == SLAP_INDEX_ADD_OP ? "add" : "del",
		   e->e_dn, e->e_id ));
#else
323
324
325
	Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
		op == SLAP_INDEX_ADD_OP ? "add" : "del",
		e->e_id, e->e_dn );
Gary Williams's avatar
Gary Williams committed
326
327
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
328
	/* add each attribute to the indexes */
329
	for ( ; ap != NULL; ap = ap->a_next ) {
330
		index_values( be, ap->a_desc, ap->a_vals, e->e_id, op );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
331
332
	}

Gary Williams's avatar
Gary Williams committed
333
334
335
336
#ifdef NEW_LOGGING
	LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
		   "index_entry: success\n" ));
#else
337
338
339
	Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
	    op == SLAP_INDEX_ADD_OP ? "add" : "del",
		e->e_id, e->e_dn );
Gary Williams's avatar
Gary Williams committed
340
341
#endif

342
	return LDAP_SUCCESS;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
343
344
}