summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-10-24 13:54:46 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-10-24 13:54:46 -0400
commit316ece9f122d3ee63e84734cf4b790c691963e04 (patch)
tree9f06d9ff8e13a68220d6d2e012d07338f7a005ca /src
parentaf009c9d84d37ab5880f575efcddbae782fe64d1 (diff)
- add referredx, as derefx
Diffstat (limited to 'src')
-rw-r--r--src/back-shr.c187
-rw-r--r--src/format.c319
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,
+ &note_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,
+ &note_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},