diff options
author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-09-08 18:50:59 -0400 |
---|---|---|
committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-09-08 18:50:59 -0400 |
commit | 918c63983b2475d6519450e201a3927fd473ab7f (patch) | |
tree | e9b4526100f78a555f886d773ffc03ef28cb586b | |
parent | 83bb73c94b07f3ded16d6348e75ecd9de732068c (diff) | |
download | slapi-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.c | 213 |
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; |