diff options
author | Rich Megginson <rmeggins@redhat.com> | 2010-02-10 14:49:03 -0700 |
---|---|---|
committer | Rich Megginson <rmeggins@redhat.com> | 2010-02-17 15:04:02 -0700 |
commit | 6adbad044ef95411882ec546281a0df6d0816673 (patch) | |
tree | 03b3938432a64ebc2624d9937bd849a15f1a280a /ldap/servers/slapd/plugin_mr.c | |
parent | ca6e6538a65bc03f7b8e1c521b5d0ba6d7b82a9e (diff) | |
download | ds-6adbad044ef95411882ec546281a0df6d0816673.tar.gz ds-6adbad044ef95411882ec546281a0df6d0816673.tar.xz ds-6adbad044ef95411882ec546281a0df6d0816673.zip |
change extensible filter code to use new syntax function style mr funcs
Created wrappers around the new syntax style functions to make them look
like the old style filter functions. There are a few caveats:
1) SUBSTRING extensible filter searches are not supported. There is no
way currently to pass in the timelimit required by the syntax substring
filter functions.
2) ORDERING only does greater than or equal. There is no standard way to
do an extensible match with a standard ordering matching rule and specify
less than or greater than.
Diffstat (limited to 'ldap/servers/slapd/plugin_mr.c')
-rw-r--r-- | ldap/servers/slapd/plugin_mr.c | 426 |
1 files changed, 327 insertions, 99 deletions
diff --git a/ldap/servers/slapd/plugin_mr.c b/ldap/servers/slapd/plugin_mr.c index 014082b7..b8b0499c 100644 --- a/ldap/servers/slapd/plugin_mr.c +++ b/ldap/servers/slapd/plugin_mr.c @@ -47,9 +47,28 @@ #include "slap.h" -struct mr_indexer_private { +/* because extensible_candidates can call an indexing + operation in the middle of a filtering operation, + we have to use a structure that can be used by both + since we can only have 1 SLAPI_PLUGIN_OBJECT in + that case */ +struct mr_private { Slapi_Value **sva; /* if using index_sv_fn */ struct berval **bva; /* if using index_fn */ + /* if doing a purely indexing operation, the fields + below are not used */ + const struct slapdplugin *pi; /* our plugin */ + const char *oid; /* orig oid */ + const char *type; /* orig type from filter */ + const struct berval *value; /* orig value from filter */ + int ftype; /* filter type */ + int op; /* query op type */ + IFP match_fn; /* match func to use */ + /* note - substring matching rules not currently supported */ + char *initial; /* these are for substring matches */ + char *any[2]; /* at most one value for extensible filter */ + char *final; /* these are for substring matches */ + const struct berval *values[2]; /* for indexing */ }; static oid_item_t* global_mr_oids = NULL; @@ -86,9 +105,10 @@ plugin_mr_find( const char *nameoroid ) } static int -plugin_mr_get_type(struct slapdplugin *pi) +plugin_mr_get_type(struct slapdplugin *pi, int *ordering) { int rc = LDAP_FILTER_EQUALITY; + *ordering = 0; if (pi) { char **str = pi->plg_mr_names; for (; str && *str; ++str) { @@ -100,6 +120,10 @@ plugin_mr_get_type(struct slapdplugin *pi) rc = LDAP_FILTER_APPROX; break; } + if (PL_strcasestr(*str, "ordering")) { + *ordering = 1; + break; + } } } @@ -203,100 +227,59 @@ slapi_mr_indexer_create (Slapi_PBlock* opb) return rc; } -static int -attempt_mr_filter_create (mr_filter_t* f, struct slapdplugin* mrp, Slapi_PBlock* pb) +static struct mr_private * +mr_private_new(const struct slapdplugin *pi, const char *oid, const char *type, const struct berval *value, int ftype, int op) { - int rc; - IFP mrf_create = NULL; - f->mrf_match = NULL; - pblock_init (pb); - if (!(rc = slapi_pblock_set (pb, SLAPI_PLUGIN, mrp)) && - !(rc = slapi_pblock_get (pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, &mrf_create)) && - mrf_create != NULL && - !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_OID, f->mrf_oid)) && - !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_TYPE, f->mrf_type)) && - !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_VALUE, &(f->mrf_value))) && - !(rc = mrf_create (pb)) && - !(rc = slapi_pblock_get (pb, SLAPI_PLUGIN_MR_FILTER_MATCH_FN, &(f->mrf_match)))) { - if (f->mrf_match == NULL) - { - rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; - } - } - return rc; + struct mr_private *mrpriv; + + mrpriv = (struct mr_private *)slapi_ch_calloc(1, sizeof(struct mr_private)); + mrpriv->pi = pi; + mrpriv->oid = oid; /* should be consistent for lifetime of usage - no copy necessary */ + mrpriv->type = type; /* should be consistent for lifetime of usage - no copy necessary */ + mrpriv->value = value; /* should be consistent for lifetime of usage - no copy necessary */ + mrpriv->ftype = ftype; + mrpriv->op = op; + mrpriv->values[0] = mrpriv->value; /* for filter_index */ + + return mrpriv; } -int /* an LDAP error code, hopefully LDAP_SUCCESS */ -plugin_mr_filter_create (mr_filter_t* f) -{ - int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; - struct slapdplugin* mrp = plugin_mr_find_registered (f->mrf_oid); - Slapi_PBlock pb; - - if (mrp != NULL) - { - rc = attempt_mr_filter_create (f, mrp, &pb); - } - else - { - /* call each plugin, until one is able to handle this request. */ - for (mrp = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); mrp != NULL; mrp = mrp->plg_next) - { - if (!(rc = attempt_mr_filter_create (f, mrp, &pb))) - { - plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */ - break; - } - } - } - if (!rc) - { - /* This plugin has created the desired filter. */ - f->mrf_plugin = mrp; - slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_INDEX_FN, &(f->mrf_index)); - slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_REUSABLE, &(f->mrf_reusable)); - slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_RESET_FN, &(f->mrf_reset)); - slapi_pblock_get (&pb, SLAPI_PLUGIN_OBJECT, &(f->mrf_object)); - slapi_pblock_get (&pb, SLAPI_PLUGIN_DESTROY_FN, &(f->mrf_destroy)); - } - return rc; -} - -int /* an LDAP error code, hopefully LDAP_SUCCESS */ -slapi_mr_filter_index (Slapi_Filter* f, Slapi_PBlock* pb) -{ - int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; - if (f->f_choice == LDAP_FILTER_EXTENDED && f->f_mr.mrf_index != NULL && - !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_OBJECT, f->f_mr.mrf_object))) - { - rc = f->f_mr.mrf_index (pb); - } - return rc; -} - -static struct mr_indexer_private * -mr_indexer_private_new() +static void +mr_private_indexer_done(struct mr_private *mrpriv) { - return (struct mr_indexer_private *)slapi_ch_calloc(1, sizeof(struct mr_indexer_private)); + if (mrpriv && mrpriv->sva) { + valuearray_free(&mrpriv->sva); + } else if (mrpriv && mrpriv->bva) { + ber_bvecfree(mrpriv->bva); + mrpriv->bva = NULL; + } } static void -mr_indexer_private_done(struct mr_indexer_private *mrip) +mr_private_done(struct mr_private *mrpriv) { - if (mrip && mrip->sva) { - valuearray_free(&mrip->sva); - } else if (mrip && mrip->bva) { - ber_bvecfree(mrip->bva); - mrip->bva = NULL; + if (mrpriv) { + mrpriv->pi = NULL; + mrpriv->oid = NULL; + mrpriv->type = NULL; + mrpriv->value = NULL; + mrpriv->ftype = 0; + mrpriv->op = 0; + slapi_ch_free_string(&mrpriv->initial); + slapi_ch_free_string(&mrpriv->any[0]); + slapi_ch_free_string(&mrpriv->final); + mrpriv->match_fn = NULL; + mrpriv->values[0] = NULL; } + mr_private_indexer_done(mrpriv); } static void -mr_indexer_private_free(struct mr_indexer_private **mrip) +mr_private_free(struct mr_private **mrpriv) { - if (mrip) { - mr_indexer_private_done(*mrip); - slapi_ch_free((void **)mrip); + if (mrpriv) { + mr_private_done(*mrpriv); + slapi_ch_free((void **)mrpriv); } } @@ -318,15 +301,16 @@ mr_wrap_mr_index_sv_fn(Slapi_PBlock* pb) } else if (!pi->plg_mr_values2keys) { LDAPDebug0Args(LDAP_DEBUG_ANY, "mr_wrap_mr_index_sv_fn: error - plugin has no plg_mr_values2keys function\n"); } else { - struct mr_indexer_private *mrip = NULL; - int ftype = plugin_mr_get_type(pi); + int ordering = 0; + struct mr_private *mrpriv = NULL; + int ftype = plugin_mr_get_type(pi, &ordering); slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUES, &in_vals); (*pi->plg_mr_values2keys)(pb, in_vals, &out_vals, ftype); slapi_pblock_set(pb, SLAPI_PLUGIN_MR_KEYS, out_vals); /* we have to save out_vals to free next time or during destroy */ - slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrip); - mr_indexer_private_done(mrip); /* free old vals, if any */ - mrip->sva = out_vals; /* save pointer for later */ + slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv); + mr_private_indexer_done(mrpriv); /* free old vals, if any */ + mrpriv->sva = out_vals; /* save pointer for later */ rc = 0; } return rc; @@ -341,7 +325,7 @@ mr_wrap_mr_index_fn(Slapi_PBlock* pb) int rc = -1; struct berval **in_vals = NULL; struct berval **out_vals = NULL; - struct mr_indexer_private *mrip = NULL; + struct mr_private *mrpriv = NULL; Slapi_Value **in_vals_sv = NULL; Slapi_Value **out_vals_sv = NULL; @@ -356,22 +340,267 @@ mr_wrap_mr_index_fn(Slapi_PBlock* pb) valuearray_get_bervalarray(out_vals_sv, &out_vals); valuearray_free(&out_vals_sv); /* don't need svals */ /* we have to save out_vals to free next time or during destroy */ - slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrip); - mr_indexer_private_done(mrip); /* free old vals, if any */ - mrip->bva = out_vals; /* save pointer for later */ + slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv); + mr_private_indexer_done(mrpriv); /* free old vals, if any */ + mrpriv->bva = out_vals; /* save pointer for later */ + + return rc; +} + +static int +default_mr_filter_destroy(Slapi_PBlock* pb) +{ + struct mr_private *mrpriv = NULL; + + slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv); + mr_private_free(&mrpriv); + mrpriv = NULL; + slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv); + + return 0; +} + +static int +default_mr_filter_match(void *obj, Slapi_Entry *e, Slapi_Attr *attr) +{ +/* returns: 0 filter matched + * -1 filter did not match + * >0 an LDAP error code + */ + int rc = -1; + struct mr_private* mrpriv = (struct mr_private*)obj; + for (; (rc == -1) && (attr != NULL); slapi_entry_next_attr(e, attr, &attr)) { + char* type = NULL; + if (!slapi_attr_get_type (attr, &type) && type != NULL && + !slapi_attr_type_cmp (mrpriv->type, type, 2/*match subtypes*/)) { + Slapi_Value **vals = attr_get_present_values(attr); +#ifdef SUPPORT_MR_SUBSTRING_MATCHING + if (mrpriv->ftype == LDAP_FILTER_SUBSTRINGS) { + rc = (*mrpriv->match_fn)(pb, mrpriv->initial, mrpriv->any, mrpriv->final, vals); + } +#endif + rc = (*mrpriv->match_fn)(NULL, mrpriv->value, vals, mrpriv->ftype, NULL); + } + } + + return rc; +} + +/* convert the filter value into an array of values for use + in index key generation */ +static int +default_mr_filter_index(Slapi_PBlock *pb) +{ + int rc = 0; + struct mr_private* mrpriv = NULL; + + slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv); + + slapi_pblock_set(pb, SLAPI_PLUGIN, mrpriv->pi); + slapi_pblock_set(pb, SLAPI_PLUGIN_MR_TYPE, mrpriv->type); + /* extensible_candidates uses struct berval ** indexer */ + slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_FN, mr_wrap_mr_index_fn); + slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, mrpriv->values); + /* the OID is magic - this is used to calculate the index prefix - it + is the indextype value passed to index_index2prefix - it must be the + same OID as used in the index configuration for the index matching + rule */ + slapi_pblock_set(pb, SLAPI_PLUGIN_MR_OID, mrpriv->oid); + slapi_pblock_set(pb, SLAPI_PLUGIN_MR_QUERY_OPERATOR, &mrpriv->op); return rc; } static int +default_mr_filter_create(Slapi_PBlock *pb) +{ + int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* failed to initialize */ + char* mrOID = NULL; + char* mrTYPE = NULL; + struct berval* mrVALUE = NULL; + struct slapdplugin* pi = NULL; + + LDAPDebug0Args(LDAP_DEBUG_FILTER, "=> default_mr_filter_create\n"); + + if (!slapi_pblock_get(pb, SLAPI_PLUGIN_MR_OID, &mrOID) && mrOID != NULL && + !slapi_pblock_get(pb, SLAPI_PLUGIN_MR_TYPE, &mrTYPE) && mrTYPE != NULL && + !slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUE, &mrVALUE) && mrVALUE != NULL && + !slapi_pblock_get(pb, SLAPI_PLUGIN, &pi) && pi != NULL) { + int op = SLAPI_OP_EQUAL; + int ordering = 0; + struct mr_private *mrpriv = NULL; + + LDAPDebug2Args(LDAP_DEBUG_FILTER, "=> default_mr_filter_create(oid %s; type %s)\n", + mrOID, mrTYPE); + + int ftype = plugin_mr_get_type(pi, &ordering); + /* map the ftype to the op type */ + if (ftype == LDAP_FILTER_EQUALITY) { + if (ordering) { /* not sure what to do here - default to GE */ + op = SLAPI_OP_GREATER_OR_EQUAL; + } +/* + } else if (ftype == LDAP_FILTER_SUBSTRINGS) { + op = SLAPI_OP_SUBSTRING; +*/ + } else { /* unsupported */ + /* NOTE: we cannot currently support substring matching rules - the + reason is that the API provides no way to pass in the search time limit + required by the syntax filter substring match functions + */ + LDAPDebug1Arg(LDAP_DEBUG_FILTER, "<= default_mr_filter_create - unsupported filter type %d\n", + ftype); + goto done; + } + slapi_pblock_set(pb, SLAPI_PLUGIN_MR_QUERY_OPERATOR, &op); + mrpriv = mr_private_new(pi, mrOID, mrTYPE, mrVALUE, ftype, op); +#ifdef SUPPORT_MR_SUBSTRING_MATCHING + if ((ftype == LDAP_FILTER_SUBSTRINGS) && (mrVALUE->bv_len > 0) && (mrVALUE->bv_val)) { + char *first, *last; + int have_initial = 0, have_final = 0; + + if ((mrVALUE->bv_len > 1) && (mrVALUE->bv_val[0] == '*')) { + first = &mrVALUE->bv_val[1]; /* point at first "real" char */ + have_final = 1; /* substring final match */ + } else { + first = mrVALUE->bv_val; /* point at beginning */ + } + if ((mrVALUE->bv_len > 1) && (mrVALUE->bv_val[mrVALUE->bv_len-1] == '*')) { + last = &mrVALUE->bv_val[mrVALUE->bv_len-2]; /* point at last "real" char */ + have_initial = 1; /* substring initial match */ + } else { + last = &mrVALUE->bv_val[mrVALUE->bv_len-1]; /* point at end */ + } + if (have_initial == have_final) { /* both or none specified - assume any */ + mrpriv->any[0] = PL_strndup(first, last-first); + } else if (have_initial) { + mrpriv->initial = PL_strndup(first, last-first); + } else if (have_final) { + mrpriv->final = PL_strndup(first, last-first); + } + } + if (ftype == LDAP_FILTER_SUBSTRINGS) { + mrpriv->match_fn = pi->plg_mr_filter_sub; + } else { + mrpriv->match_fn = pi->plg_mr_filter_ava; + } +#else + mrpriv->match_fn = pi->plg_mr_filter_ava; +#endif + slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv); + slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_MATCH_FN, default_mr_filter_match); + slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_INDEX_FN, default_mr_filter_index); + slapi_pblock_set(pb, SLAPI_PLUGIN_DESTROY_FN, default_mr_filter_destroy); + rc = 0; /* success */ + } else { + LDAPDebug(LDAP_DEBUG_FILTER, + "default_mr_filter_create: missing parameter: %s%s%s\n", + mrOID ? "" : " oid", + mrTYPE ? "" : " attribute type", + mrVALUE ? "" : " filter value"); + } + +done: + LDAPDebug1Arg(LDAP_DEBUG_FILTER, "=> default_mr_filter_create: %d\n", rc); + + return rc; +} + +static int +attempt_mr_filter_create (mr_filter_t* f, struct slapdplugin* mrp, Slapi_PBlock* pb) +{ + int rc; + IFP mrf_create = NULL; + f->mrf_match = NULL; + pblock_init (pb); + if (!(rc = slapi_pblock_set (pb, SLAPI_PLUGIN, mrp)) && + !(rc = slapi_pblock_get (pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, &mrf_create)) && + mrf_create != NULL && + !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_OID, f->mrf_oid)) && + !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_TYPE, f->mrf_type)) && + !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_VALUE, &(f->mrf_value))) && + !(rc = mrf_create (pb)) && + !(rc = slapi_pblock_get (pb, SLAPI_PLUGIN_MR_FILTER_MATCH_FN, &(f->mrf_match)))) { + if (f->mrf_match == NULL) + { + rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; + } + } + return rc; +} + +int /* an LDAP error code, hopefully LDAP_SUCCESS */ +plugin_mr_filter_create (mr_filter_t* f) +{ + int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; + struct slapdplugin* mrp = plugin_mr_find_registered (f->mrf_oid); + Slapi_PBlock pb; + + if (mrp != NULL) + { + rc = attempt_mr_filter_create (f, mrp, &pb); + } + else + { + /* call each plugin, until one is able to handle this request. */ + for (mrp = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); mrp != NULL; mrp = mrp->plg_next) + { + if (!(rc = attempt_mr_filter_create (f, mrp, &pb))) + { + plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */ + break; + } + } + } + if (rc) + { + /* look for a new syntax-style mr plugin */ + mrp = plugin_mr_find(f->mrf_oid); + if (mrp) + { + /* set the default index create fn */ + pblock_init(&pb); + slapi_pblock_set(&pb, SLAPI_PLUGIN, mrp); + slapi_pblock_set(&pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, default_mr_filter_create); + if (!(rc = attempt_mr_filter_create (f, mrp, &pb))) + { + plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */ + } + } + } + if (!rc) + { + /* This plugin has created the desired filter. */ + slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_INDEX_FN, &(f->mrf_index)); + slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_REUSABLE, &(f->mrf_reusable)); + slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_RESET_FN, &(f->mrf_reset)); + slapi_pblock_get (&pb, SLAPI_PLUGIN_OBJECT, &(f->mrf_object)); + slapi_pblock_get (&pb, SLAPI_PLUGIN_DESTROY_FN, &(f->mrf_destroy)); + } + return rc; +} + +int /* an LDAP error code, hopefully LDAP_SUCCESS */ +slapi_mr_filter_index (Slapi_Filter* f, Slapi_PBlock* pb) +{ + int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; + if (f->f_choice == LDAP_FILTER_EXTENDED && f->f_mr.mrf_index != NULL && + !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_OBJECT, f->f_mr.mrf_object))) + { + rc = f->f_mr.mrf_index (pb); + } + return rc; +} + +static int default_mr_indexer_destroy(Slapi_PBlock* pb) { - struct mr_indexer_private *mrip = NULL; + struct mr_private *mrpriv = NULL; - slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrip); - mr_indexer_private_free(&mrip); - mrip = NULL; - slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrip); + slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv); + mr_private_free(&mrpriv); + mrpriv = NULL; + slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv); return 0; } @@ -396,7 +625,7 @@ default_mr_indexer_create(Slapi_PBlock* pb) goto done; } - slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mr_indexer_private_new()); + slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mr_private_new(pi, NULL, NULL, NULL, 0, 0)); slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_FN, mr_wrap_mr_index_fn); slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, mr_wrap_mr_index_sv_fn); slapi_pblock_set(pb, SLAPI_PLUGIN_DESTROY_FN, default_mr_indexer_destroy); @@ -406,4 +635,3 @@ default_mr_indexer_create(Slapi_PBlock* pb) done: return rc; } - |