void slap_index2bvlen( slap_mask_t idx, struct berval *bv ) { int i; bv->bv_len = 0; for ( i=0; !BER_BVISNULL( &idxstr[i].word ); i++ ) { if ( !idxstr[i].mask ) continue; if ( IS_SLAP_INDEX( idx, idxstr[i].mask )) { if ( (idxstr[i].mask & SLAP_INDEX_SUBSTR) && ((idx & SLAP_INDEX_SUBSTR_DEFAULT) != idxstr[i].mask)) continue; if ( bv->bv_len ) bv->bv_len++; bv->bv_len += idxstr[i].word.bv_len; } } }
/* caller must provide buffer space, after calling index2bvlen */ void slap_index2bv( slap_mask_t idx, struct berval *bv ) { int i; char *ptr; if ( !bv->bv_len ) return; ptr = bv->bv_val; for ( i=0; !BER_BVISNULL( &idxstr[i].word ); i++ ) { if ( !idxstr[i].mask ) continue; if ( IS_SLAP_INDEX( idx, idxstr[i].mask )) { if ( (idxstr[i].mask & SLAP_INDEX_SUBSTR) && ((idx & SLAP_INDEX_SUBSTR_DEFAULT) != idxstr[i].mask)) continue; if ( ptr != bv->bv_val ) *ptr++ = ','; ptr = lutil_strcopy( ptr, idxstr[i].word.bv_val ); } } }
/* This function is only called when evaluating search filters. */ int wt_index_param( Backend *be, AttributeDescription *desc, int ftype, slap_mask_t *maskp, struct berval *prefixp ) { AttrInfo *ai; int rc; slap_mask_t mask, type = 0; ai = wt_index_mask( be, desc, prefixp ); if ( !ai ) { /* TODO: add monitor */ return LDAP_INAPPROPRIATE_MATCHING; } mask = ai->ai_indexmask; switch( ftype ) { case LDAP_FILTER_PRESENT: type = SLAP_INDEX_PRESENT; if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { *prefixp = presence_key; *maskp = mask; return LDAP_SUCCESS; } break; case LDAP_FILTER_APPROX: type = SLAP_INDEX_APPROX; if ( desc->ad_type->sat_approx ) { if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) { *maskp = mask; return LDAP_SUCCESS; } break; } /* Use EQUALITY rule and index for approximate match */ /* fall thru */ case LDAP_FILTER_EQUALITY: type = SLAP_INDEX_EQUALITY; if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) { *maskp = mask; return LDAP_SUCCESS; } break; case LDAP_FILTER_SUBSTRINGS: type = SLAP_INDEX_SUBSTR; if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) { *maskp = mask; return LDAP_SUCCESS; } break; default: return LDAP_OTHER; } /* TODO: add monitor index */ return LDAP_INAPPROPRIATE_MATCHING; }
static int indexer( Operation *op, wt_ctx *wc, AttributeDescription *ad, struct berval *atname, BerVarray vals, ID id, int opid, slap_mask_t mask ) { int rc, i; struct berval *keys; WT_CURSOR *cursor = NULL; WT_SESSION *session = wc->session; assert( mask != 0 ); cursor = wt_ctx_index_cursor(wc, atname, 1); if( !cursor ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(indexer) ": open index cursor failed: %s\n", atname->bv_val, 0, 0 ); goto done; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { rc = wt_key_change( op->o_bd, cursor, &presence_key, id, opid ); if( rc ) { goto done; } } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } done: if(cursor){ cursor->close(cursor); } return rc; }
/* This function is only called when evaluating search filters. */ int bdb_index_param( Backend *be, AttributeDescription *desc, int ftype, DB **dbp, slap_mask_t *maskp, struct berval *prefixp ) { AttrInfo *ai; int rc; slap_mask_t mask, type = 0; DB *db; ai = bdb_index_mask( be, desc, prefixp ); if ( !ai ) { #ifdef BDB_MONITOR_IDX switch ( ftype ) { case LDAP_FILTER_PRESENT: type = SLAP_INDEX_PRESENT; break; case LDAP_FILTER_APPROX: type = SLAP_INDEX_APPROX; break; case LDAP_FILTER_EQUALITY: type = SLAP_INDEX_EQUALITY; break; case LDAP_FILTER_SUBSTRINGS: type = SLAP_INDEX_SUBSTR; break; default: return LDAP_INAPPROPRIATE_MATCHING; } bdb_monitor_idx_add( be->be_private, desc, type ); #endif /* BDB_MONITOR_IDX */ return LDAP_INAPPROPRIATE_MATCHING; } mask = ai->ai_indexmask; rc = bdb_db_cache( be, prefixp, &db ); if( rc != LDAP_SUCCESS ) { return rc; } switch( ftype ) { case LDAP_FILTER_PRESENT: type = SLAP_INDEX_PRESENT; if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { *prefixp = presence_key; goto done; } break; case LDAP_FILTER_APPROX: type = SLAP_INDEX_APPROX; if ( desc->ad_type->sat_approx ) { if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) { goto done; } break; } /* Use EQUALITY rule and index for approximate match */ /* fall thru */ case LDAP_FILTER_EQUALITY: type = SLAP_INDEX_EQUALITY; if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) { goto done; } break; case LDAP_FILTER_SUBSTRINGS: type = SLAP_INDEX_SUBSTR; if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) { goto done; } break; default: return LDAP_OTHER; } #ifdef BDB_MONITOR_IDX bdb_monitor_idx_add( be->be_private, desc, type ); #endif /* BDB_MONITOR_IDX */ return LDAP_INAPPROPRIATE_MATCHING; done: *dbp = db; *maskp = mask; return LDAP_SUCCESS; }
static int indexer( Operation *op, DB_TXN *txn, AttributeDescription *ad, struct berval *atname, BerVarray vals, ID id, int opid, slap_mask_t mask ) { int rc, i; DB *db; struct berval *keys; assert( mask != 0 ); rc = bdb_db_cache( op->o_bd, atname, &db ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "bdb_index_read: Could not open DB %s\n", atname->bv_val, 0, 0 ); return LDAP_OTHER; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid ); if( rc ) { goto done; } } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } done: switch( rc ) { /* The callers all know how to deal with these results */ case 0: case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: break; /* Anything else is bad news */ default: rc = LDAP_OTHER; } return rc; }
static int indexer( Operation *op, MDB_txn *txn, struct mdb_attrinfo *ai, AttributeDescription *ad, struct berval *atname, BerVarray vals, ID id, int opid, slap_mask_t mask ) { int rc = LDAP_OTHER; struct berval *keys; MDB_cursor *mc = ai->ai_cursor; mdb_idl_keyfunc *keyfunc; char *err __maybe_unused; assert( mask != 0 ); if ( !mc ) { err = "c_open"; rc = mdb_cursor_open( txn, ai->ai_dbi, &mc ); if ( rc ) goto done; if ( slapMode & SLAP_TOOL_QUICK ) ai->ai_cursor = mc; } if ( opid == SLAP_INDEX_ADD_OP ) { #ifdef MDB_TOOL_IDL_CACHING if (( slapMode & SLAP_TOOL_QUICK ) && slap_tool_thread_max > 2 ) { keyfunc = mdb_tool_idl_add; mc = (MDB_cursor *)ai; } else #endif keyfunc = mdb_idl_insert_keys; } else keyfunc = mdb_idl_delete_keys; if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { rc = keyfunc( op->o_bd, mc, presence_key, id ); if( rc ) { err = "presence"; goto done; } } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { rc = keyfunc( op->o_bd, mc, keys, id ); ber_bvarray_free_x( keys, op->o_tmpmemctx ); if ( rc ) { err = "equality"; goto done; } } rc = LDAP_SUCCESS; } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { rc = keyfunc( op->o_bd, mc, keys, id ); ber_bvarray_free_x( keys, op->o_tmpmemctx ); if ( rc ) { err = "approx"; goto done; } } rc = LDAP_SUCCESS; } 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, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { rc = keyfunc( op->o_bd, mc, keys, id ); ber_bvarray_free_x( keys, op->o_tmpmemctx ); if( rc ) { err = "substr"; goto done; } } rc = LDAP_SUCCESS; } done: if ( !(slapMode & SLAP_TOOL_QUICK)) { if (mc == ai->ai_cursor) ai->ai_cursor = NULL; mdb_cursor_close( mc ); } switch( rc ) { /* The callers all know how to deal with these results */ case 0: break; /* Anything else is bad news */ default: rc = LDAP_OTHER; } return rc; }
int bdb_attr_index_config( struct bdb_info *bdb, const char *fname, int lineno, int argc, char **argv, struct config_reply_s *c_reply) { int rc = 0; int i; slap_mask_t mask; char **attrs; char **indexes = NULL; attrs = ldap_str2charray( argv[0], "," ); if( attrs == NULL ) { fprintf( stderr, "%s: line %d: " "no attributes specified: %s\n", fname, lineno, argv[0] ); return LDAP_PARAM_ERROR; } if ( argc > 1 ) { indexes = ldap_str2charray( argv[1], "," ); if( indexes == NULL ) { fprintf( stderr, "%s: line %d: " "no indexes specified: %s\n", fname, lineno, argv[1] ); rc = LDAP_PARAM_ERROR; goto done; } } if( indexes == NULL ) { mask = bdb->bi_defaultmask; } else { mask = 0; for ( i = 0; indexes[i] != NULL; i++ ) { slap_mask_t index; rc = slap_str2index( indexes[i], &index ); if( rc != LDAP_SUCCESS ) { if ( c_reply ) { snprintf(c_reply->msg, sizeof(c_reply->msg), "index type \"%s\" undefined", indexes[i] ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } rc = LDAP_PARAM_ERROR; goto done; } mask |= index; } } if( !mask ) { if ( c_reply ) { snprintf(c_reply->msg, sizeof(c_reply->msg), "no indexes selected" ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } rc = LDAP_PARAM_ERROR; goto done; } for ( i = 0; attrs[i] != NULL; i++ ) { AttrInfo *a; AttributeDescription *ad; const char *text; #ifdef LDAP_COMP_MATCH ComponentReference* cr = NULL; AttrInfo *a_cr = NULL; #endif if( strcasecmp( attrs[i], "default" ) == 0 ) { bdb->bi_defaultmask |= mask; continue; } #ifdef LDAP_COMP_MATCH if ( is_component_reference( attrs[i] ) ) { rc = extract_component_reference( attrs[i], &cr ); if ( rc != LDAP_SUCCESS ) { if ( c_reply ) { snprintf(c_reply->msg, sizeof(c_reply->msg), "index component reference\"%s\" undefined", attrs[i] ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } goto done; } cr->cr_indexmask = mask; /* * After extracting a component reference * only the name of a attribute will be remaining */ } else { cr = NULL; } #endif ad = NULL; rc = slap_str2ad( attrs[i], &ad, &text ); if( rc != LDAP_SUCCESS ) { if ( c_reply ) { snprintf(c_reply->msg, sizeof(c_reply->msg), "index attribute \"%s\" undefined", attrs[i] ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } goto done; } if( ad == slap_schema.si_ad_entryDN || slap_ad_is_binary( ad ) ) { if (c_reply) { snprintf(c_reply->msg, sizeof(c_reply->msg), "index of attribute \"%s\" disallowed", attrs[i] ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } rc = LDAP_UNWILLING_TO_PERFORM; goto done; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !( ad->ad_type->sat_approx && ad->ad_type->sat_approx->smr_indexer && ad->ad_type->sat_approx->smr_filter ) ) { if (c_reply) { snprintf(c_reply->msg, sizeof(c_reply->msg), "approx index of attribute \"%s\" disallowed", attrs[i] ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } rc = LDAP_INAPPROPRIATE_MATCHING; goto done; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !( ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_indexer && ad->ad_type->sat_equality->smr_filter ) ) { if (c_reply) { snprintf(c_reply->msg, sizeof(c_reply->msg), "equality index of attribute \"%s\" disallowed", attrs[i] ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } rc = LDAP_INAPPROPRIATE_MATCHING; goto done; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !( ad->ad_type->sat_substr && ad->ad_type->sat_substr->smr_indexer && ad->ad_type->sat_substr->smr_filter ) ) { if (c_reply) { snprintf(c_reply->msg, sizeof(c_reply->msg), "substr index of attribute \"%s\" disallowed", attrs[i] ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } rc = LDAP_INAPPROPRIATE_MATCHING; goto done; } Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n", ad->ad_cname.bv_val, mask, 0 ); a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) ); #ifdef LDAP_COMP_MATCH a->ai_cr = NULL; #endif a->ai_desc = ad; if ( bdb->bi_flags & BDB_IS_OPEN ) { a->ai_indexmask = 0; a->ai_newmask = mask; } else { a->ai_indexmask = mask; a->ai_newmask = 0; } #ifdef LDAP_COMP_MATCH if ( cr ) { a_cr = bdb_attr_mask( bdb, ad ); if ( a_cr ) { /* * AttrInfo is already in AVL * just add the extracted component reference * in the AttrInfo */ rc = insert_component_reference( cr, &a_cr->ai_cr ); if ( rc != LDAP_SUCCESS) { fprintf( stderr, " error during inserting component reference in %s ", attrs[i]); rc = LDAP_PARAM_ERROR; goto done; } continue; } else { rc = insert_component_reference( cr, &a->ai_cr ); if ( rc != LDAP_SUCCESS) { fprintf( stderr, " error during inserting component reference in %s ", attrs[i]); rc = LDAP_PARAM_ERROR; goto done; } } } #endif rc = ainfo_insert( bdb, a ); if( rc ) { if ( bdb->bi_flags & BDB_IS_OPEN ) { AttrInfo *b = bdb_attr_mask( bdb, ad ); /* If there is already an index defined for this attribute * it must be replaced. Otherwise we end up with multiple * olcIndex values for the same attribute */ if ( b->ai_indexmask & BDB_INDEX_DELETING ) { /* If we were editing this attr, reset it */ b->ai_indexmask &= ~BDB_INDEX_DELETING; /* If this is leftover from a previous add, commit it */ if ( b->ai_newmask ) b->ai_indexmask = b->ai_newmask; b->ai_newmask = a->ai_newmask; ch_free( a ); rc = 0; continue; } } if (c_reply) { snprintf(c_reply->msg, sizeof(c_reply->msg), "duplicate index definition for attr \"%s\"", attrs[i] ); fprintf( stderr, "%s: line %d: %s\n", fname, lineno, c_reply->msg ); } rc = LDAP_PARAM_ERROR; goto done; } } done: ldap_charray_free( attrs ); if ( indexes != NULL ) ldap_charray_free( indexes ); return rc; }