1 /* $NetBSD: index.c,v 1.2 2021/08/14 16:15:02 christos Exp $ */
2
3 /* OpenLDAP WiredTiger backend */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2002-2021 The OpenLDAP Foundation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18 /* ACKNOWLEDGEMENTS:
19 * This work was developed by HAMANO Tsukasa <hamano@osstech.co.jp>
20 * based on back-bdb for inclusion in OpenLDAP Software.
21 * WiredTiger is a product of MongoDB Inc.
22 */
23
24 #include <sys/cdefs.h>
25 __RCSID("$NetBSD: index.c,v 1.2 2021/08/14 16:15:02 christos Exp $");
26
27 #include "portable.h"
28
29 #include <stdio.h>
30 #include "back-wt.h"
31 #include "slap-config.h"
32
33 static char presence_keyval[] = {0,0};
34 static struct berval presence_key = BER_BVC(presence_keyval);
35
wt_index_mask(Backend * be,AttributeDescription * desc,struct berval * atname)36 AttrInfo *wt_index_mask(
37 Backend *be,
38 AttributeDescription *desc,
39 struct berval *atname )
40 {
41 AttributeType *at;
42 AttrInfo *ai = wt_attr_mask( be->be_private, desc );
43
44 if( ai ) {
45 *atname = desc->ad_cname;
46 return ai;
47 }
48
49 /* If there is a tagging option, did we ever index the base
50 * type? If so, check for mask, otherwise it's not there.
51 */
52 if( slap_ad_is_tagged( desc ) && desc != desc->ad_type->sat_ad ) {
53 /* has tagging option */
54 ai = wt_attr_mask( be->be_private, desc->ad_type->sat_ad );
55
56 if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOTAGS ) ) {
57 *atname = desc->ad_type->sat_cname;
58 return ai;
59 }
60 }
61
62 /* see if supertype defined mask for its subtypes */
63 for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
64 /* If no AD, we've never indexed this type */
65 if ( !at->sat_ad ) continue;
66
67 ai = wt_attr_mask( be->be_private, at->sat_ad );
68
69 if ( ai && !( ai->ai_indexmask & SLAP_INDEX_NOSUBTYPES ) ) {
70 *atname = at->sat_cname;
71 return ai;
72 }
73 }
74
75 return 0;
76 }
77
78 /* This function is only called when evaluating search filters.
79 */
wt_index_param(Backend * be,AttributeDescription * desc,int ftype,slap_mask_t * maskp,struct berval * prefixp)80 int wt_index_param(
81 Backend *be,
82 AttributeDescription *desc,
83 int ftype,
84 slap_mask_t *maskp,
85 struct berval *prefixp )
86 {
87 AttrInfo *ai;
88 int rc;
89 slap_mask_t mask, type = 0;
90
91 ai = wt_index_mask( be, desc, prefixp );
92
93 if ( !ai ) {
94 /* TODO: add monitor */
95 return LDAP_INAPPROPRIATE_MATCHING;
96 }
97 mask = ai->ai_indexmask;
98
99 switch( ftype ) {
100 case LDAP_FILTER_PRESENT:
101 type = SLAP_INDEX_PRESENT;
102 if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
103 *prefixp = presence_key;
104 *maskp = mask;
105 return LDAP_SUCCESS;
106 }
107 break;
108
109 case LDAP_FILTER_APPROX:
110 type = SLAP_INDEX_APPROX;
111 if ( desc->ad_type->sat_approx ) {
112 if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
113 *maskp = mask;
114 return LDAP_SUCCESS;
115 }
116 break;
117 }
118
119 /* Use EQUALITY rule and index for approximate match */
120 /* fall thru */
121
122 case LDAP_FILTER_EQUALITY:
123 type = SLAP_INDEX_EQUALITY;
124 if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
125 *maskp = mask;
126 return LDAP_SUCCESS;
127 }
128 break;
129
130 case LDAP_FILTER_SUBSTRINGS:
131 type = SLAP_INDEX_SUBSTR;
132 if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
133 *maskp = mask;
134 return LDAP_SUCCESS;
135 }
136 break;
137
138 default:
139 return LDAP_OTHER;
140 }
141
142 /* TODO: add monitor index */
143 return LDAP_INAPPROPRIATE_MATCHING;
144 }
145
indexer(Operation * op,wt_ctx * wc,AttributeDescription * ad,struct berval * atname,BerVarray vals,ID id,int opid,slap_mask_t mask)146 static int indexer(
147 Operation *op,
148 wt_ctx *wc,
149 AttributeDescription *ad,
150 struct berval *atname,
151 BerVarray vals,
152 ID id,
153 int opid,
154 slap_mask_t mask )
155 {
156 int rc, i;
157 struct berval *keys;
158 WT_CURSOR *cursor = NULL;
159 WT_SESSION *session = wc->session;
160 assert( mask != 0 );
161
162 cursor = wt_ctx_index_cursor(wc, atname, 1);
163 if( !cursor ) {
164 Debug( LDAP_DEBUG_ANY,
165 LDAP_XSTRING(indexer)
166 ": open index cursor failed: %s\n",
167 atname->bv_val );
168 goto done;
169 }
170
171 if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
172 rc = wt_key_change( op->o_bd, cursor, &presence_key, id, opid );
173 if( rc ) {
174 goto done;
175 }
176 }
177
178 if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
179 rc = ad->ad_type->sat_equality->smr_indexer(
180 LDAP_FILTER_EQUALITY,
181 mask,
182 ad->ad_type->sat_syntax,
183 ad->ad_type->sat_equality,
184 atname, vals, &keys, op->o_tmpmemctx );
185
186 if( rc == LDAP_SUCCESS && keys != NULL ) {
187 for( i=0; keys[i].bv_val != NULL; i++ ) {
188 rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid );
189 if( rc ) {
190 ber_bvarray_free_x( keys, op->o_tmpmemctx );
191 goto done;
192 }
193 }
194 ber_bvarray_free_x( keys, op->o_tmpmemctx );
195 }
196 rc = LDAP_SUCCESS;
197 }
198
199 if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
200 rc = ad->ad_type->sat_approx->smr_indexer(
201 LDAP_FILTER_APPROX,
202 mask,
203 ad->ad_type->sat_syntax,
204 ad->ad_type->sat_approx,
205 atname, vals, &keys, op->o_tmpmemctx );
206
207 if( rc == LDAP_SUCCESS && keys != NULL ) {
208 for( i=0; keys[i].bv_val != NULL; i++ ) {
209 rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid );
210 if( rc ) {
211 ber_bvarray_free_x( keys, op->o_tmpmemctx );
212 goto done;
213 }
214 }
215 ber_bvarray_free_x( keys, op->o_tmpmemctx );
216 }
217
218 rc = LDAP_SUCCESS;
219 }
220
221 if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
222 rc = ad->ad_type->sat_substr->smr_indexer(
223 LDAP_FILTER_SUBSTRINGS,
224 mask,
225 ad->ad_type->sat_syntax,
226 ad->ad_type->sat_substr,
227 atname, vals, &keys, op->o_tmpmemctx );
228
229 if( rc == LDAP_SUCCESS && keys != NULL ) {
230 for( i=0; keys[i].bv_val != NULL; i++ ) {
231 rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid );
232 if( rc ) {
233 ber_bvarray_free_x( keys, op->o_tmpmemctx );
234 goto done;
235 }
236 }
237 ber_bvarray_free_x( keys, op->o_tmpmemctx );
238 }
239
240 rc = LDAP_SUCCESS;
241 }
242
243 done:
244 if(cursor){
245 cursor->close(cursor);
246 }
247 return rc;
248 }
249
index_at_values(Operation * op,wt_ctx * wc,AttributeDescription * ad,AttributeType * type,struct berval * tags,BerVarray vals,ID id,int opid)250 static int index_at_values(
251 Operation *op,
252 wt_ctx *wc,
253 AttributeDescription *ad,
254 AttributeType *type,
255 struct berval *tags,
256 BerVarray vals,
257 ID id,
258 int opid )
259 {
260 int rc;
261 slap_mask_t mask = 0;
262 int ixop = opid;
263 AttrInfo *ai = NULL;
264
265 if ( opid == WT_INDEX_UPDATE_OP )
266 ixop = SLAP_INDEX_ADD_OP;
267
268 if( type->sat_sup ) {
269 /* recurse */
270 rc = index_at_values( op, wc, NULL,
271 type->sat_sup, tags,
272 vals, id, opid );
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 ai = wt_attr_mask( op->o_bd->be_private, type->sat_ad );
280 if ( ai ) {
281 #ifdef LDAP_COMP_MATCH
282 /* component indexing */
283 if ( ai->ai_cr ) {
284 ComponentReference *cr;
285 for( cr = ai->ai_cr ; cr ; cr = cr->cr_next ) {
286 rc = indexer( op, wc, cr->cr_ad, &type->sat_cname,
287 cr->cr_nvals, id, ixop,
288 cr->cr_indexmask );
289 }
290 }
291 #endif
292 ad = type->sat_ad;
293 /* If we're updating the index, just set the new bits that aren't
294 * already in the old mask.
295 */
296 if ( opid == WT_INDEX_UPDATE_OP )
297 mask = ai->ai_newmask & ~ai->ai_indexmask;
298 else
299 /* For regular updates, if there is a newmask use it. Otherwise
300 * just use the old mask.
301 */
302 mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
303 if( mask ) {
304 rc = indexer( op, wc, ad, &type->sat_cname,
305 vals, id, ixop, mask );
306 if( rc ) return rc;
307 }
308 }
309 }
310
311 if( tags->bv_len ) {
312 AttributeDescription *desc;
313
314 desc = ad_find_tags( type, tags );
315 if( desc ) {
316 ai = wt_attr_mask( op->o_bd->be_private, desc );
317
318 if( ai ) {
319 if ( opid == WT_INDEX_UPDATE_OP )
320 mask = ai->ai_newmask & ~ai->ai_indexmask;
321 else
322 mask = ai->ai_newmask ? ai->ai_newmask : ai->ai_indexmask;
323 if ( mask ) {
324 rc = indexer( op, wc, desc, &desc->ad_cname,
325 vals, id, ixop, mask );
326
327 if( rc ) {
328 return rc;
329 }
330 }
331 }
332 }
333 }
334
335 return LDAP_SUCCESS;
336 }
337
wt_index_values(Operation * op,wt_ctx * wc,AttributeDescription * desc,BerVarray vals,ID id,int opid)338 int wt_index_values(
339 Operation *op,
340 wt_ctx *wc,
341 AttributeDescription *desc,
342 BerVarray vals,
343 ID id,
344 int opid )
345 {
346 int rc;
347
348 /* Never index ID 0 */
349 if ( id == 0 )
350 return 0;
351
352 rc = index_at_values( op, wc, desc,
353 desc->ad_type, &desc->ad_tags,
354 vals, id, opid );
355
356 return rc;
357 }
358
359 int
wt_index_entry(Operation * op,wt_ctx * wc,int opid,Entry * e)360 wt_index_entry( Operation *op, wt_ctx *wc, int opid, Entry *e )
361 {
362 int rc;
363 Attribute *ap = e->e_attrs;
364
365 if ( e->e_id == 0 )
366 return 0;
367
368 Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
369 opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
370 (long) e->e_id, e->e_dn ? e->e_dn : "" );
371
372 for ( ; ap != NULL; ap = ap->a_next ) {
373 rc = wt_index_values( op, wc, ap->a_desc,
374 ap->a_nvals, e->e_id, opid );
375 if( rc != LDAP_SUCCESS ) {
376 Debug( LDAP_DEBUG_TRACE,
377 "<= index_entry_%s( %ld, \"%s\" ) failure\n",
378 opid == SLAP_INDEX_ADD_OP ? "add" : "del",
379 (long) e->e_id, e->e_dn );
380 return rc;
381 }
382 }
383
384 Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
385 opid == SLAP_INDEX_DELETE_OP ? "del" : "add",
386 (long) e->e_id, e->e_dn ? e->e_dn : "" );
387 return 0;
388 }
389
390 /*
391 * Local variables:
392 * indent-tabs-mode: t
393 * tab-width: 4
394 * c-basic-offset: 4
395 * End:
396 */
397