index.c 7.68 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* index.c - routines for dealing with attribute indexes */
/* $OpenLDAP$ */
/*
 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */

#include "portable.h"

#include <stdio.h>

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

#include "slap.h"
#include "back-bdb.h"
17
18
19
#include "lutil_hash.h"

static char presence_keyval[LUTIL_HASH_BYTES] = {0,0,0,1};
Kurt Zeilenga's avatar
Kurt Zeilenga committed
20
static struct berval presence_key = {LUTIL_HASH_BYTES, presence_keyval};
21
22
23
24
25

static slap_mask_t index_mask(
	Backend *be,
	AttributeDescription *desc,
	char **dbname,
26
	struct berval *atname )
27
28
29
30
{
	AttributeType *at;
	slap_mask_t mask = 0;

31
	bdb_attr_mask( be->be_private, desc, &mask );
32
33

	if( mask ) {
34
		*atname = desc->ad_cname;
35
		*dbname = desc->ad_cname.bv_val;
36
37
38
		return mask;
	}

39
40
41
42
	/* 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 ) {
43
		/* has language tag */
44
		bdb_attr_mask( be->be_private, desc->ad_type->sat_ad, &mask );
45

46
		if (! ( mask & SLAP_INDEX_NOLANG ) ) {
47
			*atname = desc->ad_type->sat_cname;
48
			*dbname = desc->ad_type->sat_cname.bv_val;
49
50
51
52
53
54
			return mask;
		}
	}

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

		bdb_attr_mask( be->be_private, at->sat_ad, &mask );
59
60
61

		if( mask & SLAP_INDEX_AUTO_SUBTYPES ) {
			*atname = desc->ad_type->sat_cname;
62
			*dbname = at->sat_cname.bv_val;
63
64
			return mask;
		}
65
66

		if( !( mask & SLAP_INDEX_NOSUBTYPES ) ) {
67
			*atname = at->sat_cname;
68
			*dbname = at->sat_cname.bv_val;
69
70
71
72
73
74
75
76
77
78
79
80
81
			return mask;
		}

		if( mask ) break;
	}

	return 0;
}

int bdb_index_param(
	Backend *be,
	AttributeDescription *desc,
	int ftype,
82
	DB **dbp,
83
	slap_mask_t *maskp,
84
	struct berval *prefixp )
85
{
86
	int rc;
87
	slap_mask_t mask;
88
	DB *db;
89
90
	char *dbname;

91
	mask = index_mask( be, desc, &dbname, prefixp );
92
93
94
95
96

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

97
98
99
100
101
102
	rc = bdb_db_cache( be, dbname, &db );

	if( rc != LDAP_SUCCESS ) {
		return rc;
	}

103
	switch( ftype ) {
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
131
132
133
134
	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:
135
	*dbp = db;
136
137
138
139
140
141
142
143
	*maskp = mask;
	return LDAP_SUCCESS;
}

static int indexer(
	Backend *be,
	DB_TXN *txn,
	char *dbname,
144
	struct berval *atname,
145
146
147
148
149
150
151
152
153
	struct berval **vals,
	ID id,
	int op,
	slap_mask_t mask )
{
	int rc, i;
	const char *text;
	DB *db;
	AttributeDescription *ad = NULL;
154
	struct berval *keys;
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

	assert( mask );

	rc = bdb_db_cache( be, dbname, &db );
	
	if ( rc != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
		LDAP_LOG(( "index", LDAP_LEVEL_ERR,
			"bdb_index_read: Could not open DB %s\n", dbname));
#else
		Debug( LDAP_DEBUG_ANY,
			"<= bdb_index_read NULL (could not open %s)\n",
			dbname, 0, 0 );
#endif
		return LDAP_OTHER;
	}

172
	rc = slap_bv2ad( atname, &ad, &text );
173
174
	if( rc != LDAP_SUCCESS ) return rc;

175
	if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
176
		rc = bdb_key_change( be, db, txn, &presence_key, id, op );
177
178
179
		if( rc ) {
			goto done;
		}
180
181
182
183
184
185
186
187
	}

	if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
		rc = ad->ad_type->sat_equality->smr_indexer(
			LDAP_FILTER_EQUALITY,
			mask,
			ad->ad_type->sat_syntax,
			ad->ad_type->sat_equality,
188
			atname, vals, &keys );
189
190

		if( rc == LDAP_SUCCESS && keys != NULL ) {
191
192
			for( i=0; keys[i].bv_val != NULL; i++ ) {
				rc = bdb_key_change( be, db, txn, &keys[i], id, op );
193
				if( rc ) {
194
					bvarray_free( keys );
195
196
					goto done;
				}
197
			}
198
			bvarray_free( keys );
199
		}
200
		rc = LDAP_SUCCESS;
201
202
203
204
205
206
207
208
	}

	if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
		rc = ad->ad_type->sat_approx->smr_indexer(
			LDAP_FILTER_APPROX,
			mask,
			ad->ad_type->sat_syntax,
			ad->ad_type->sat_approx,
209
			atname, vals, &keys );
210
211

		if( rc == LDAP_SUCCESS && keys != NULL ) {
212
213
			for( i=0; keys[i].bv_val != NULL; i++ ) {
				rc = bdb_key_change( be, db, txn, &keys[i], id, op );
214
				if( rc ) {
215
					bvarray_free( keys );
216
217
					goto done;
				}
218
			}
219
			bvarray_free( keys );
220
		}
221
222

		rc = LDAP_SUCCESS;
223
224
225
226
227
228
229
230
	}

	if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
		rc = ad->ad_type->sat_substr->smr_indexer(
			LDAP_FILTER_SUBSTRINGS,
			mask,
			ad->ad_type->sat_syntax,
			ad->ad_type->sat_substr,
231
			atname, vals, &keys );
232
233

		if( rc == LDAP_SUCCESS && keys != NULL ) {
234
235
			for( i=0; keys[i].bv_val != NULL; i++ ) {
				bdb_key_change( be, db, txn, &keys[i], id, op );
236
				if( rc ) {
237
					bvarray_free( keys );
238
239
					goto done;
				}
240
			}
241
			bvarray_free( keys );
242
		}
243
244

		rc = LDAP_SUCCESS;
245
246
	}

247
248
done:
	return rc;
249
250
251
252
253
254
}

static int index_at_values(
	Backend *be,
	DB_TXN *txn,
	AttributeType *type,
255
	struct berval *lang,
256
257
258
259
260
261
262
	struct berval **vals,
	ID id,
	int op,
	char ** dbnamep,
	slap_mask_t *maskp )
{
	int rc;
263
	slap_mask_t mask = 0;
264
265
266
267
268
269
270
271
272
	slap_mask_t tmpmask = 0;
	int lindex = 0;

	if( type->sat_sup ) {
		/* recurse */
		rc = index_at_values( be, txn,
			type->sat_sup, lang,
			vals, id, op,
			dbnamep, &tmpmask );
273
274

		if( rc ) return rc;
275
276
	}

277
	/* If this type has no AD, we've never used it before */
278
	if( type->sat_ad ) {
279
		bdb_attr_mask( be->be_private, type->sat_ad, &mask );
280
	}
281
282

	if( mask ) {
283
		*dbnamep = type->sat_cname.bv_val;
284
	} else if ( !( tmpmask & SLAP_INDEX_AUTO_SUBTYPES ) ) {
285
286
287
288
289
		mask = tmpmask;
	}

	if( mask ) {
		rc = indexer( be, txn, *dbnamep,
290
			&type->sat_cname,
291
292
			vals, id, op,
			mask );
293
294

		if( rc ) return rc;
295
296
	}

297
	if( lang->bv_len ) {
298
		char *dbname = NULL;
299
300
		struct berval lname;
		AttributeDescription *desc;
301

302
303
		tmpmask = 0;
		lname.bv_val = NULL;
304

305
		desc = ad_find_lang( type, lang );
306
		if( desc ) {
307
			bdb_attr_mask( be->be_private, desc, &tmpmask );
308
		}
309
310

		if( tmpmask ) {
311
312
313
			dbname = desc->ad_cname.bv_val;
			lname = desc->ad_cname;
			mask = tmpmask;
314
315
316
		}

		if( dbname != NULL ) {
317
			rc = indexer( be, txn, dbname, &lname,
318
				vals, id, op,
319
				mask );
320

321
			if( !tmpmask ) {
322
				ch_free( lname.bv_val );
323
			}
324
325
326
			if( rc ) {
				return rc;
			}
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
		}
	}

	return LDAP_SUCCESS;
}

int bdb_index_values(
	Backend *be,
	DB_TXN *txn,
	AttributeDescription *desc,
	struct berval **vals,
	ID id,
	int op )
{
	int rc;
	char *dbname = NULL;
	slap_mask_t mask;

	rc = index_at_values( be, txn,
346
		desc->ad_type, &desc->ad_lang,
347
348
349
350
351
352
353
354
355
356
357
358
		vals, id, op,
		&dbname, &mask );

	return rc;
}

int
bdb_index_entry(
	Backend	*be,
	DB_TXN *txn,
	int op,
	Entry	*e,
359
	Attribute *ap )
360
361
362
363
364
{
	int rc;

#ifdef NEW_LOGGING
	LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
365
		"index_entry: %s (%s) %ld\n",
366
		op == SLAP_INDEX_ADD_OP ? "add" : "del",
367
		e->e_dn, (long) e->e_id ));
368
369
370
#else
	Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
		op == SLAP_INDEX_ADD_OP ? "add" : "del",
371
		(long) e->e_id, e->e_dn );
372
373
374
375
#endif

	/* add each attribute to the indexes */
	for ( ; ap != NULL; ap = ap->a_next ) {
376
		rc = bdb_index_values( be, txn,
377
378
379
380
381
			ap->a_desc, ap->a_vals, e->e_id, op );

		if( rc != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
			LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
382
				"index_entry: success\n" ));
383
384
385
386
#else
			Debug( LDAP_DEBUG_TRACE,
				"<= index_entry_%s( %ld, \"%s\" ) success\n",
				op == SLAP_INDEX_ADD_OP ? "add" : "del",
387
				(long) e->e_id, e->e_dn );
388
389
390
391
392
393
394
#endif
			return rc;
		}
	}

#ifdef NEW_LOGGING
	LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
395
		"index_entry: success\n" ));
396
397
398
#else
	Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
		op == SLAP_INDEX_ADD_OP ? "add" : "del",
399
		(long) e->e_id, e->e_dn );
400
401
402
403
#endif

	return LDAP_SUCCESS;
}