summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-09-08 18:50:59 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-09-08 18:50:59 -0400
commit918c63983b2475d6519450e201a3927fd473ab7f (patch)
treee9b4526100f78a555f886d773ffc03ef28cb586b
parent83bb73c94b07f3ded16d6348e75ecd9de732068c (diff)
downloadslapi-nis-918c63983b2475d6519450e201a3927fd473ab7f.tar.gz
slapi-nis-918c63983b2475d6519450e201a3927fd473ab7f.tar.xz
slapi-nis-918c63983b2475d6519450e201a3927fd473ab7f.zip
- update references as noted by the derefx function
-rw-r--r--src/back-shr.c213
1 files changed, 156 insertions, 57 deletions
diff --git a/src/back-shr.c b/src/back-shr.c
index 605d939..e4e3f6b 100644
--- a/src/back-shr.c
+++ b/src/back-shr.c
@@ -683,14 +683,73 @@ backend_shr_entry_is_a_set(struct plugin_state *state,
backend_entry_get_set_config_entry_filter());
}
-/* Update any entries to which the passed-in entry in the passed-in map refers
- * to, if the referred-to entry is in this map. Everybody got that? */
+/* Update any entries in the map for which the passed-in entry will affect the
+ * values which are derived. */
struct backend_shr_update_references_cbdata {
Slapi_PBlock *pb;
Slapi_Entry *e;
};
-bool_t
+/* Build a filter which includes the basic_filter, if given, and ANDs that
+ * with an OR of the elements of attrs exactly matching the entry's DN. */
+static char *
+backend_build_filter(struct plugin_state *state, Slapi_DN *entry_dn,
+ const char *basic_filter, char **attrs)
+{
+ char *filter, *tndn;
+ int filter_size, i;
+ if (basic_filter == NULL) {
+ basic_filter = "";
+ }
+ filter_size = strlen("(&(|))") + strlen(basic_filter) + 1;
+ tndn = format_escape_for_filter(slapi_sdn_get_ndn(entry_dn));
+ if (tndn == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "error building filter for "
+ "updating entries\n");
+ return NULL;
+ }
+ for (i = 0; (attrs != NULL) && (attrs[i] != NULL); i++) {
+ filter_size += (strlen("(=)") +
+ strlen(attrs[i]) +
+ strlen(tndn));
+ }
+ filter = malloc(filter_size);
+ if (filter == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "error building filter for "
+ "updating entries\n");
+ free(tndn);
+ return NULL;
+ }
+ if (strlen(basic_filter) > 0) {
+ sprintf(filter, "(&%s(|", basic_filter);
+ } else {
+ sprintf(filter, "(|");
+ }
+ for (i = 0; (attrs != NULL) && (attrs[i] != NULL); i++) {
+ sprintf(filter + strlen(filter),
+ "(%s=%s)", attrs[i], tndn);
+ }
+ free(tndn);
+ if (strlen(basic_filter) > 0) {
+ strcat(filter, "))");
+ } else {
+ strcat(filter, ")");
+ }
+ return filter;
+}
+
+static int
+backend_shr_note_entry_sdn_cb(Slapi_Entry *e, void *cbdata)
+{
+ Slapi_DN ***sdn_list = cbdata;
+ format_add_sdn_list(sdn_list, slapi_entry_get_dn(e));
+ return 0;
+}
+
+static bool_t
backend_shr_update_references_cb(const char *group, const char *set,
bool_t flag,
void *backend_data, void *cbdata_ptr)
@@ -698,13 +757,15 @@ backend_shr_update_references_cb(const char *group, const char *set,
struct plugin_state *state;
struct backend_shr_set_data *set_data;
struct backend_shr_update_references_cbdata *cbdata;
- Slapi_DN *referred_to_sdn;
+ Slapi_DN *referred_to_sdn, **these_entries, **prev_entries;
+ Slapi_DN **ref_bases;
Slapi_ValueSet *values;
Slapi_Value *value;
- char **ref_attrs, *actual_attr, *filter, *tndn, **set_bases;
+ char **ref_attrs, *actual_attr, *filter, **set_bases, *attrs[2];
struct format_inref_attr **inref_attrs;
- const char *ndn, *dn;
- int i, j, disposition, buffer_flags, filter_size, n_ref_attrs;
+ struct format_ref_attr_list **ref_attr_list, *ref_attr;
+ const char *ndn, *dn, *map_filter;
+ int i, j, k, l, disposition, buffer_flags, n_ref_attrs;
set_data = backend_data;
cbdata = cbdata_ptr;
@@ -720,46 +781,11 @@ backend_shr_update_references_cb(const char *group, const char *set,
}
n_ref_attrs = i;
if (n_ref_attrs > 0) {
- filter_size = strlen("(&(|))") +
- strlen(set_data->entry_filter) +
- 1;
- ndn = slapi_entry_get_ndn(cbdata->e);
- tndn = format_escape_for_filter(ndn);
- if (tndn == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "error building filter for "
- "updating entries\n");
- return TRUE;
- }
- for (i = 0;
- (ref_attrs != NULL) && (ref_attrs[i] != NULL);
- i++) {
- filter_size += (strlen("(=)") +
- strlen(ref_attrs[i]) +
- strlen(ndn));
- }
- filter = malloc(filter_size);
- if (filter == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "error building filter for "
- "updating entries\n");
- free(tndn);
- return TRUE;
- }
- sprintf(filter, "(&%s(|", set_data->entry_filter);
- for (i = 0;
- (ref_attrs != NULL) && (ref_attrs[i] != NULL);
- i++) {
- sprintf(filter + strlen(filter),
- "(%s=%s)", ref_attrs[i], tndn);
- }
- strcat(filter, "))");
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
- "searching for referrers using filter \"%s\"\n",
- filter);
- free(tndn);
+ /* Build the search filter. */
+ filter = backend_build_filter(state,
+ slapi_entry_get_sdn(cbdata->e),
+ set_data->entry_filter,
+ ref_attrs);
/* Update any matching entry. */
set_bases = set_data->bases;
for (i = 0;
@@ -782,6 +808,9 @@ backend_shr_update_references_cb(const char *group, const char *set,
free(filter);
}
+ /* For every directory entry to which this directory entry refers and
+ * which also has a corresponding entry in this map, update it. */
+
/* Allocate the DN we'll use to hold values for comparison. */
referred_to_sdn = slapi_sdn_new();
if (referred_to_sdn == NULL) {
@@ -792,8 +821,6 @@ backend_shr_update_references_cb(const char *group, const char *set,
return TRUE;
}
- /* For every directory entry to which this directory entry refers and
- * which also has a corresponding entry in this map, update it. */
inref_attrs = set_data->inref_attrs;
for (i = 0; (inref_attrs != NULL) && (inref_attrs[i] != NULL); i++) {
/* We're only processing inref attributes for this map. */
@@ -835,6 +862,79 @@ backend_shr_update_references_cb(const char *group, const char *set,
buffer_flags);
}
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. */
+ ref_attr_list = set_data->ref_attr_list;
+ for (i = 0;
+ (ref_attr_list != NULL) && (ref_attr_list[i] != NULL);
+ i++) {
+ ref_attr = ref_attr_list[i];
+ these_entries = NULL;
+ prev_entries = NULL;
+ format_add_sdn_list(&these_entries,
+ slapi_entry_get_dn(cbdata->e));
+ for (j = ref_attr->n_links - 1;
+ (j >= 0) && (these_entries != NULL);
+ j--) {
+ /* If it's the first attribute, we can use the map's
+ * filter to narrow the result set, too. */
+ if (j == 0) {
+ /* Search the map's locations using its filter
+ * to narrow things down. */
+ map_filter = set_data->entry_filter;
+ ref_bases = format_make_sdn_list(set_data->bases);
+ } else {
+ /* Search the recorded parent locations. */
+ map_filter = NULL;
+ ref_bases = ref_attr->links[j].base_sdn_list;
+ }
+ attrs[0] = ref_attr->links[j].attribute;
+ attrs[1] = NULL;
+ /* Search for entries which would be predecessors in
+ * the path to this entry. */
+ for (k = 0; these_entries[k] != 0; k++) {
+ /* Build the search filter. */
+ filter = backend_build_filter(state,
+ these_entries[k],
+ map_filter,
+ attrs);
+ /* Walk the set of places to search for the
+ * predecessors and look for predecessors. */
+ for (l = 0;
+ (ref_bases != NULL) &&
+ (ref_bases[l] != NULL);
+ l++) {
+ slapi_search_internal_set_pb(cbdata->pb,
+ slapi_sdn_get_ndn(ref_bases[l]),
+ LDAP_SCOPE_SUBTREE,
+ filter,
+ NULL,
+ FALSE,
+ NULL,
+ NULL,
+ state->plugin_identity,
+ 0);
+ slapi_search_internal_callback_pb(cbdata->pb,
+ &prev_entries,
+ NULL,
+ backend_shr_note_entry_sdn_cb,
+ NULL);
+ }
+ }
+ /* Back up to process the list of predecessors. */
+ format_free_sdn_list(these_entries);
+ these_entries = prev_entries;
+ prev_entries = NULL;
+ /* Clean up the temporary SDN list, if we used one. */
+ if (j == 0) {
+ format_free_sdn_list(ref_bases);
+ }
+ }
+ /* In case we somehow got predecessors by mistake, clean up
+ * that list. */
+ format_free_sdn_list(these_entries);
+ }
return TRUE;
}
@@ -934,8 +1034,7 @@ backend_shr_add_cb(Slapi_PBlock *pb)
backend_set_config_entry_add_cb(cbdata.e, cbdata.state);
}
- /* Update entries which need to be updated in case this new entry
- * refers to them. */
+ /* Update entries in maps which are affected by this entry. */
backend_shr_update_references(cbdata.state, cbdata.e);
map_unlock();
@@ -1022,11 +1121,11 @@ backend_shr_modify_cb(Slapi_PBlock *pb)
"error modifying set entries corresponding to "
"\"%s\"\n", cbdata.ndn);
}
- /* Update entries which need to be updated in case this entry
- * no longer refers to them. */
+ /* Update entries which need to be updated in case they are no longer
+ * affected by this entry. */
backend_shr_update_references(cbdata.state, cbdata.e_pre);
- /* Update entries which need to be updated in case this entry
- * now refers to them. */
+ /* Update entries which need to be updated in case they are now
+ * affected by this entry. */
backend_shr_update_references(cbdata.state, cbdata.e_post);
/* If it's a map configuration entry, reconfigure, clear, and
* repopulate the map. */
@@ -1229,8 +1328,8 @@ backend_shr_delete_cb(Slapi_PBlock *pb)
"deleted entry \"%s\" is a set\n", cbdata.ndn);
backend_set_config_entry_delete_cb(cbdata.e, cbdata.state);
}
- /* Update entries which need to be updated in case this entry no longer
- * refers to them. */
+ /* Update entries which need to be updated in case they are no longer
+ * affected by this entry. */
backend_shr_update_references(cbdata.state, cbdata.e);
map_unlock();
return 0;