diff options
| author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-10-24 13:54:46 -0400 |
|---|---|---|
| committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-10-24 13:54:46 -0400 |
| commit | 316ece9f122d3ee63e84734cf4b790c691963e04 (patch) | |
| tree | 9f06d9ff8e13a68220d6d2e012d07338f7a005ca /src | |
| parent | af009c9d84d37ab5880f575efcddbae782fe64d1 (diff) | |
- add referredx, as derefx
Diffstat (limited to 'src')
| -rw-r--r-- | src/back-shr.c | 187 | ||||
| -rw-r--r-- | src/format.c | 319 |
2 files changed, 501 insertions, 5 deletions
diff --git a/src/back-shr.c b/src/back-shr.c index e43b155..3db9420 100644 --- a/src/back-shr.c +++ b/src/back-shr.c @@ -784,14 +784,17 @@ backend_shr_update_references_cb(const char *group, const char *set, struct backend_shr_update_references_cbdata *cbdata; struct backend_shr_note_entry_sdn_cbdata note_cbdata; Slapi_DN *referred_to_sdn, **these_entries, **prev_entries; - Slapi_DN **these_bases, **prev_bases; + Slapi_DN **next_entries, **these_bases, **prev_bases; + Slapi_Entry *this_entry; Slapi_ValueSet *values; Slapi_Value *value; char **ref_attrs, *actual_attr, *filter, **set_bases; - char *these_attrs[2], *prev_attrs[2]; + char *these_attrs[2], *prev_attrs[2], *next_attrs[2]; struct format_inref_attr **inref_attrs; struct format_ref_attr_list **ref_attr_list, *ref_attr; + struct format_ref_attr_list **inref_attr_list, *inref_attr; struct format_ref_attr_list_link *this_attr_link, *prev_attr_link; + struct format_ref_attr_list_link *next_attr_link; const char *ndn, *dn, *map_filter; int i, j, k, l, disposition, buffer_flags, n_ref_attrs; @@ -892,7 +895,10 @@ backend_shr_update_references_cb(const char *group, const char *set, slapi_sdn_free(&referred_to_sdn); /* Determine if there are any entries in this map which directly (or - * indirectly) pull in data from this entry. */ + * indirectly) pull in data from this entry. If there are, update + * them. */ + + /* Walk the set of reference-attribute chains. */ ref_attr_list = set_data->ref_attr_list; for (i = 0; (ref_attr_list != NULL) && (ref_attr_list[i] != NULL); @@ -907,7 +913,7 @@ backend_shr_update_references_cb(const char *group, const char *set, /* Start with this entry. */ format_add_sdn_list(&these_entries, slapi_entry_get_dn(cbdata->e)); - /* Walk backwards. */ + /* Walk the chain backwards. */ for (j = ref_attr->n_links - 1; (j >= 0) && (these_entries != NULL); j--) { @@ -1055,6 +1061,179 @@ backend_shr_update_references_cb(const char *group, const char *set, } format_free_sdn_list(these_entries); } + + /* Determine if there are any entries in this map which are referred to + * (directly or indirectly) by this entry. If there are, update them. + */ + + /* Walk the set of reference-attribute chains. */ + inref_attr_list = set_data->inref_attr_list; + for (i = 0; + (inref_attr_list != NULL) && (inref_attr_list[i] != NULL); + i++) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "updating referredx[%d] references for " + "\"%s\"\n", + i, slapi_entry_get_ndn(cbdata->e)); + inref_attr = inref_attr_list[i]; + these_entries = NULL; + next_entries = NULL; + /* Start with this entry. */ + format_add_sdn_list(&these_entries, + slapi_entry_get_dn(cbdata->e)); + /* Walk the chain, backwards. */ + for (j = inref_attr->n_links - 2; + (j >= 0) && (these_entries != NULL); + j--) { + /* For each link in the chain (except the last, which + * we skip because it's not an attribute which is used + * to link to other entries), build the set of entries + * which are referred to by the entry. */ + this_attr_link = &inref_attr->links[j]; + these_attrs[0] = this_attr_link->attribute; + these_attrs[1] = NULL; + if (j > 0) { + next_attr_link = &inref_attr->links[j - 1]; + next_attrs[0] = next_attr_link->attribute; + next_attrs[1] = NULL; + } else { + next_attr_link = NULL; + next_attrs[0] = NULL; + next_attrs[1] = NULL; + } + /* Read the entries at this stage. */ + for (k = 0; + (these_entries != NULL) && + (these_entries[k] != NULL); + k++) { + /* Read the linked-to DN from the named + * attribute in the entry. */ + values = NULL; + wrap_search_internal_get_entry(these_entries[k], + these_attrs, + &this_entry, + state->plugin_identity); + if (this_entry == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "failure reading entry " + "\"%s\"\n", + slapi_sdn_get_ndn(these_entries[k])); + continue; + } + if (slapi_vattr_values_get(this_entry, + these_attrs[0], + &values, + &disposition, + &actual_attr, + 0, &buffer_flags) != 0) { + slapi_entry_free(this_entry); + continue; + } + /* For each value of this attribute... */ + for (l = slapi_valueset_first_value(values, + &value); + l != -1; + l = slapi_valueset_next_value(values, l, + &value)) { + /* Pull out the value, which is a + * referred-to entry's DN. */ + dn = slapi_value_get_string(value); + if (dn == NULL) { + continue; + } + /* Add it to the list of entries which + * we'll examine this go-round. */ + format_add_sdn_list(&these_entries, dn); + } + slapi_vattr_values_free(&values, &actual_attr, + buffer_flags); + slapi_entry_free(this_entry); + } + /* Read the entries for the next stage. */ + for (k = 0; + (next_attrs[0] != NULL) && + (these_entries != NULL) && + (these_entries[k] != NULL); + k++) { + /* Read the linked-to DN from the named + * attribute in the entry. */ + values = NULL; + wrap_search_internal_get_entry(these_entries[k], + next_attrs, + &this_entry, + state->plugin_identity); + if (this_entry == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "failure reading entry " + "\"%s\"\n", + slapi_sdn_get_ndn(these_entries[k])); + continue; + } + if (slapi_vattr_values_get(this_entry, + next_attrs[0], + &values, + &disposition, + &actual_attr, + 0, &buffer_flags) != 0) { + slapi_entry_free(this_entry); + continue; + } + /* For each value of this attribute... */ + for (l = slapi_valueset_first_value(values, + &value); + l != -1; + l = slapi_valueset_next_value(values, l, + &value)) { + /* Pull out the value, which is a + * referred-to entry's DN. */ + dn = slapi_value_get_string(value); + if (dn == NULL) { + continue; + } + /* Add it to the list of entries which + * we'll examine next time. */ + format_add_sdn_list(&next_entries, dn); + } + slapi_vattr_values_free(&values, &actual_attr, + buffer_flags); + slapi_entry_free(this_entry); + } + /* Back up to process the list of predecessors, unless + * this was the last link, in which case it's become + * our list of candidates. */ + if (j > 0) { + format_free_sdn_list(these_entries); + these_entries = next_entries; + next_entries = NULL; + } + } + /* Walk the last list of entries and update any related + * entries in this map. */ + for (j = 0; + (these_entries != NULL) && (these_entries[j] != NULL); + j++) { + ndn = slapi_sdn_get_ndn(these_entries[j]); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "possible dependent entry: \"%s\"\n", + ndn); + if (!map_data_check_entry(state, group, set, ndn)) { + continue; + } + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "dependent entry: \"%s\"\n", + ndn); + backend_shr_set_config_entry_set_one_dn(state, + ndn, + set_data->self); + } + format_free_sdn_list(these_entries); + } + return TRUE; } diff --git a/src/format.c b/src/format.c index 01590d9..8da0a68 100644 --- a/src/format.c +++ b/src/format.c @@ -287,7 +287,9 @@ format_add_ref_attr_list(struct format_ref_attr_list ***list, if (format_find_ref_attr_list(*list, group, set, names) != NULL) { return *list; } - for (i = 0; (list != NULL) && (list[i] != NULL); i++) { + for (i = 0; + (list != NULL) && (*list != NULL) && ((*list)[i] != NULL); + i++) { continue; } ret = malloc((i + 2) * sizeof(struct format_ref_attr_list*)); @@ -1341,6 +1343,320 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, return 0; } +/* Add the name of this entry to the DN list in the cbdata. */ +struct format_note_entry_sdn_cbdata { + struct plugin_state *state; + Slapi_DN ***sdn_list; +}; + +static int +format_note_entry_sdn_cb(Slapi_Entry *e, void *cbdata_ptr) +{ + struct format_note_entry_sdn_cbdata *cbdata = cbdata_ptr; + slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, + "search matched entry \"%s\"\n", slapi_entry_get_dn(e)); + format_add_sdn_list(cbdata->sdn_list, slapi_entry_get_dn(e)); + return 0; +} + +/* For the first N-1 arguments, treat them as pairs, looking entries in the + * map named by the first part of the pair which refer to this entry using the + * attribute named by the second part in the pair, following links until we + * get to the last argument, at which point we return the value of the + * attribute named by the final argument. */ +static int +format_referredx(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, + const char *group, const char *set, + const char *args, const char *disallowed, + char *outbuf, int outbuf_len, + struct format_choice **outbuf_choices, + char ***ref_attrs, struct format_inref_attr ***inref_attrs, + struct format_ref_attr_list ***ref_attr_list, + struct format_ref_attr_list ***inref_attr_list) +{ + int i, j, k, ret, argc, attrs_list_length, disposition, buffer_flags; + Slapi_PBlock *local_pb; + Slapi_DN **these_bases, **next_bases, **these_entries, **next_entries; + Slapi_Entry *entry; + Slapi_ValueSet *values; + Slapi_Value *value; + struct berval **choices; + const struct berval *bval; + struct format_note_entry_sdn_cbdata note_cbdata; + struct format_ref_attr_list *list; + char **argv, *attrs[2], *filter, *tndn, *attr, *other_attr; + char *actual_attr; + char *other_set, *set_filter, **set_bases, *use_filter; + const char **attr_links, *ndn; + + ret = format_parse_args(state, args, &argc, &argv); + if (ret != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referredx: error parsing arguments\n"); + return -EINVAL; + } + if (argc < 3) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referredx: requires at least 3 arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + if ((argc % 2) != 1) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referredx: requires an odd number of " + "arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + if (outbuf_choices == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referredx: returns a list, but a list would " + "not be appropriate here\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + other_set = argv[0]; + other_attr = argv[1]; + attr = argv[2]; + + /* Build the list of attributes which we can use to select the list of + * references. */ + attrs_list_length = (argc + 1) / 2; + attr_links = malloc((attrs_list_length + 1) * sizeof(char *)); + if (attr_links == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referredx: out of memory\n"); + format_free_parsed_args(argv); + return -ENOMEM; + } + for (i = 0; i < attrs_list_length; i++) { + if (i < (attrs_list_length - 1)) { + attr_links[i] = argv[i * 2 + 1]; + } else { + attr_links[i] = argv[i * 2]; + } + } + attr_links[i] = NULL; + + /* Note this list of attributes. */ + format_add_ref_attr_list(inref_attr_list, group, set, attr_links); + list = format_find_ref_attr_list(*inref_attr_list, group, set, + attr_links); + free(attr_links); + + /* Set up to search for referrers. */ + local_pb = slapi_pblock_new(); + if (local_pb == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "referredx: out of memory\n"); + format_free_parsed_args(argv); + return -ENOMEM; + } + + /* Get the searching parameters for the set which contains the entry, + * and all of the referred-to sets, and save them for use at the last + * link in the chain. */ + backend_get_set_config(state, group, set, + &set_bases, &set_filter); + for (i = 0; (set_bases != NULL) && (set_bases[i] != NULL); i++) { + format_add_sdn_list(&(list->links[0].base_sdn_list), + set_bases[i]); + } + backend_free_set_config(set_bases, set_filter); + for (i = 0; i < list->n_links - 1; i++) { + backend_get_set_config(state, group, argv[i * 2], + &set_bases, &set_filter); + for (j = 0; + (set_bases != NULL) && (set_bases[j] != NULL); + j++) { + format_add_sdn_list(&(list->links[i + 1].base_sdn_list), + set_bases[j]); + } + backend_free_set_config(set_bases, set_filter); + } + + /* Walk the chain, searching for entries which refer to entries at + * this point in the chain. */ + these_entries = NULL; + format_add_sdn_list(&these_entries, slapi_entry_get_dn(e)); + next_entries = NULL; + attrs[0] = NULL; + for (i = 0; i < list->n_links - 1; i++) { + these_bases = list->links[i].base_sdn_list; + if (i < list->n_links - 1) { + next_bases = list->links[i + 1].base_sdn_list; + } else { + next_bases = NULL; + } + /* Perform the search for entries which refer to each entry we + * see here. */ + for (j = 0; + (these_entries != NULL) && (these_entries[j] != NULL); + j++) { + ndn = slapi_sdn_get_ndn(these_entries[j]); + tndn = format_escape_for_filter(ndn); + if (tndn == NULL) { + continue; + } + /* Walk the set of search bases for this link. */ + filter = malloc(strlen(list->links[i].attribute) + + strlen(tndn) + 4); + if (filter == NULL) { + free(tndn); + continue; + } + sprintf(filter, "(%s=%s)", + list->links[i].attribute, tndn); + for (k = 0; + (these_bases != NULL) && (these_bases[k] != NULL); + k++) { + ndn = slapi_sdn_get_dn(these_bases[k]); + /* Search for referrers under this tree. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "referredx: searching under %s " + "for \"%s\" (link=%d.1)\n", + ndn, filter, i); + slapi_search_internal_set_pb(local_pb, + ndn, + LDAP_SCOPE_SUBTREE, + filter, attrs, + FALSE, + NULL, NULL, + state->plugin_identity, + 0); + note_cbdata.state = state; + note_cbdata.sdn_list = &these_entries; + slapi_search_internal_callback_pb(local_pb, + ¬e_cbdata, + NULL, + format_note_entry_sdn_cb, + NULL); + } + free(filter); + /* Walk the set of search bases for the next link. */ + filter = malloc(strlen(list->links[i].attribute) + + strlen(tndn) + 4); + if (filter == NULL) { + free(tndn); + continue; + } + sprintf(filter, "(%s=%s)", + list->links[i].attribute, tndn); + for (k = 0; + (next_bases != NULL) && (next_bases[k] != NULL); + k++) { + ndn = slapi_sdn_get_dn(next_bases[k]); + /* Search for referrers under that tree. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "referredx: searching under %s " + "for \"%s\" (link=%d.2)\n", + ndn, filter, i); + slapi_search_internal_set_pb(local_pb, + ndn, + LDAP_SCOPE_SUBTREE, + filter, attrs, + FALSE, + NULL, NULL, + state->plugin_identity, + 0); + note_cbdata.state = state; + note_cbdata.sdn_list = &next_entries; + slapi_search_internal_callback_pb(local_pb, + ¬e_cbdata, + NULL, + format_note_entry_sdn_cb, + NULL); + } + free(filter); + free(tndn); + } + /* Set up for the next iteration. */ + format_free_sdn_list(these_entries); + these_entries = next_entries; + next_entries = NULL; + } + + /* Walk the list of entries at which we've finally arrived, and + * extract the last attribute's value. */ + attrs[0] = list->links[list->n_links - 1].attribute; + attrs[1] = NULL; + choices = NULL; + for (i = 0; + (these_entries != NULL) && (these_entries[i] != NULL); + i++) { + next_entries = list->links[list->n_links - 1].base_sdn_list; + ndn = slapi_sdn_get_ndn(these_entries[i]); + format_add_sdn_list(&next_entries, slapi_dn_parent(ndn)); + list->links[list->n_links - 1].base_sdn_list = next_entries; + /* Read the entry. */ + wrap_search_internal_get_entry(these_entries[i], attrs, &entry, + state->plugin_identity); + if (entry == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "referredx: error reading entry " + "\"%s\"\n", + slapi_sdn_get_dn(these_entries[i])); + continue; + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "referredx: reading \"%s\" from entry " + "\"%s\"\n", attrs[0], + slapi_sdn_get_dn(these_entries[i])); + } + /* Pull up the value set. */ + if (slapi_vattr_values_get(entry, attrs[0], &values, + &disposition, + &actual_attr, + 0, &buffer_flags) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "referredx: entry \"%s\" has no " + "values for \"%s\"\n", + slapi_sdn_get_dn(these_entries[i]), + attrs[0]); + slapi_entry_free(entry); + continue; + } + /* Walk the value set. */ + for (j = slapi_valueset_first_value(values, &value); + j != -1; + j = slapi_valueset_next_value(values, j, &value)){ + /* Get the value. */ + bval = slapi_value_get_berval(value); + /* If the value is empty, skip it. */ + if (bval->bv_len == 0) { + continue; + } + format_add_bv_list(&choices, bval); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "referredx: found value " + "\"%.*s\" in \"%s\"\n", + bval->bv_len, + bval->bv_val, + slapi_sdn_get_dn(these_entries[i])); + } + slapi_vattr_values_free(&values, &actual_attr, + buffer_flags); + slapi_entry_free(entry); + } + + /* Return any values we found. */ + if (choices != NULL) { + format_add_choice(outbuf_choices, outbuf, choices); + format_free_bv_list(choices); + } + + slapi_pblock_destroy(local_pb); + format_free_parsed_args(argv); + + return 0; +} + /* Evaluate each argument's list of results, after the first, in turn, and * merge them, using the first argument as a separator. */ static int @@ -1847,6 +2163,7 @@ format_lookup_fn(const char *fnname) {"deref", format_deref}, {"derefx", format_derefx}, {"referred", format_referred}, + {"referredx", format_referredx}, {"merge", format_merge}, {"match", format_match}, {"regmatch", format_regmatch}, |
