diff options
author | Nalin Dahyabhai <nalin@dahyabhai.net> | 2012-01-06 15:42:33 -0500 |
---|---|---|
committer | Nalin Dahyabhai <nalin@dahyabhai.net> | 2012-01-06 15:42:33 -0500 |
commit | 80c8021ef1dcf911c170dc7917b1de9087b0b8e0 (patch) | |
tree | 70a037e20a2093c5fc54d4c5335511954e16f126 /src/back-shr.c | |
parent | d361fe8707d3558a9bad59c61b1f124d2de17772 (diff) | |
download | slapi-nis-80c8021ef1dcf911c170dc7917b1de9087b0b8e0.tar.gz slapi-nis-80c8021ef1dcf911c170dc7917b1de9087b0b8e0.tar.xz slapi-nis-80c8021ef1dcf911c170dc7917b1de9087b0b8e0.zip |
- Make a note of which attributes we read from any entry when evaluating data, and when we're later called for a modify request which doesn't modify any of those attributes, skip recalculating the entry contents (should make a dent in #771493).
Diffstat (limited to 'src/back-shr.c')
-rw-r--r-- | src/back-shr.c | 151 |
1 files changed, 145 insertions, 6 deletions
diff --git a/src/back-shr.c b/src/back-shr.c index 180fb33..c9f46a6 100644 --- a/src/back-shr.c +++ b/src/back-shr.c @@ -1,5 +1,5 @@ /* - * Copyright 2008,2010,2011 Red Hat, Inc. + * Copyright 2008,2010,2011,2012 Red Hat, Inc. * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -119,6 +119,45 @@ backend_shr_read_server_name(struct plugin_state *state, char **master) return (*master != NULL) ? 0 : -1; } +/* Cache the list of relevant attributes, updating if needed, and return its + * value. Mainly used for logging. */ +static const char * +backend_shr_get_rel_attr_list(struct backend_shr_set_data *data) +{ + int i, length; + + if (data->rel_attrs_list == data->rel_attrs) { + return data->rel_attr_list; + } else { + free(data->rel_attr_list); + if (data->rel_attrs == NULL) { + data->rel_attr_list = NULL; + } else { + for (i = 0, length = 0; + data->rel_attrs[i] != NULL; + i++) { + length += (strlen(data->rel_attrs[i]) + 1); + } + if (length > 0) { + data->rel_attr_list = malloc(length); + for (i = 0, length = 0; + (data->rel_attrs[i] != NULL); + i++) { + if (i > 0) { + strcpy(data->rel_attr_list + length++, ","); + } + strcpy(data->rel_attr_list + length, data->rel_attrs[i]); + length += strlen(data->rel_attrs[i]); + } + } else { + data->rel_attr_list = NULL; + } + } + data->rel_attrs_list = data->rel_attrs; + } + return data->rel_attr_list; +} + /* Manipulate string lists. */ void backend_shr_free_strlist(char **strlist) @@ -768,11 +807,39 @@ backend_shr_note_entry_sdn_cb(Slapi_Entry *e, void *cbdata_ptr) return 0; } +/* Build a string representation of the list of attributes being modified by + * this list of mods, typically for logging purposes. */ +static char * +backend_shr_mods_as_string(LDAPMod **mods) +{ + char *ret; + int i, length; + + ret = NULL; + for (i = 0, length = 0; (mods != NULL) && (mods[i] != NULL); i++) { + length += (strlen(mods[i]->mod_type) + 1); + } + if (length > 0) { + ret = malloc(length); + for (i = 0, length = 0; + (mods != NULL) && (mods[i] != NULL); + i++) { + if (i > 0) { + strcpy(ret + length++, ","); + } + strcpy(ret + length, mods[i]->mod_type); + length += strlen(mods[i]->mod_type); + } + } + return ret; +} + /* 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; + LDAPMod **mods; }; static bool_t @@ -800,12 +867,44 @@ backend_shr_update_references_cb(const char *group, const char *set, 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; + char *modlist; int i, j, k, l, disposition, buffer_flags, n_ref_attrs, scope; set_data = backend_data; cbdata = cbdata_ptr; state = set_data->state; + /* If the entry didn't change any attributes which are at all relevant + * to this map, then we don't need to recompute anything. */ + if ((cbdata->mods != NULL) && (set_data->rel_attrs != NULL)) { + for (i = 0; cbdata->mods[i] != NULL; i++) { + for (j = 0; set_data->rel_attrs[j] != NULL; j++) { + if (slapi_attr_types_equivalent(cbdata->mods[i]->mod_type, + set_data->rel_attrs[j])) { + break; + } + } + if (set_data->rel_attrs[j] != NULL) { + break; + } + } + if (cbdata->mods[i] == NULL) { + modlist = backend_shr_mods_as_string(cbdata->mods); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "no interesting reference-based " + "changes for \"%s\"/\"%s\" " + "made in \"%s\" (%s not in %s)\n", + set_data->group, + set_data->set, + slapi_entry_get_ndn(cbdata->e), + modlist, + backend_shr_get_rel_attr_list(set_data)); + free(modlist); + return TRUE; + } + } + /* For every entry in this set which refers to this entry using * a DN stored in an attribute, update that entry. */ @@ -1304,11 +1403,13 @@ backend_shr_update_references_cb(const char *group, const char *set, } void -backend_shr_update_references(struct plugin_state *state, Slapi_Entry *e) +backend_shr_update_references(struct plugin_state *state, Slapi_Entry *e, + LDAPMod **mods) { struct backend_shr_update_references_cbdata cbdata; cbdata.e = e; cbdata.pb = slapi_pblock_new(); + cbdata.mods = mods; if (!map_data_foreach_map(state, NULL, backend_shr_update_references_cb, &cbdata)) { slapi_log_error(SLAPI_LOG_PLUGIN, @@ -1411,7 +1512,7 @@ backend_shr_add_cb(Slapi_PBlock *pb) } /* Update entries in maps which are affected by this entry. */ - backend_shr_update_references(cbdata.state, cbdata.e); + backend_shr_update_references(cbdata.state, cbdata.e, NULL); map_unlock(); wrap_dec_call_level(); @@ -1424,6 +1525,7 @@ struct backend_shr_modify_entry_cbdata { LDAPMod **mods; Slapi_Entry *e_pre, *e_post; char *ndn; + char *modlist; }; static bool_t @@ -1432,10 +1534,44 @@ backend_shr_modify_entry_cb(const char *group, const char *set, bool_t flag, { struct backend_shr_set_data *set_data; struct backend_shr_modify_entry_cbdata *cbdata; + int i, j; set_data = backend_data; cbdata = cbdata_ptr; + /* If the entry didn't change any attributes which are at all relevant + * to the map, and it both was and is still is in the map, then we + * don't need to recompute anything. */ + if ((cbdata->mods != NULL) && (set_data->rel_attrs != NULL)) { + for (i = 0; cbdata->mods[i] != NULL; i++) { + for (j = 0; set_data->rel_attrs[j] != NULL; j++) { + if (slapi_attr_types_equivalent(cbdata->mods[i]->mod_type, + set_data->rel_attrs[j])) { + break; + } + } + if (set_data->rel_attrs[j] != NULL) { + break; + } + } + if ((cbdata->mods[i] == NULL) && + backend_shr_entry_matches_set(set_data, cbdata->pb, + cbdata->e_pre) && + backend_shr_entry_matches_set(set_data, cbdata->pb, + cbdata->e_post)) { + slapi_log_error(SLAPI_LOG_PLUGIN, + cbdata->state->plugin_desc->spd_id, + "no interesting changes for " + "\"%s\"/\"%s\" made in (\"%s\") " + "(%s not in %s)\n", + set_data->group, + set_data->set, + cbdata->ndn, + cbdata->modlist, + backend_shr_get_rel_attr_list(set_data)); + return TRUE; + } + } /* If the entry used to match the map, remove it. */ if (backend_shr_entry_matches_set(set_data, cbdata->pb, cbdata->e_pre)) { @@ -1484,6 +1620,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb) slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e_post); cbdata.ndn = slapi_entry_get_ndn(cbdata.e_pre); cbdata.pb = pb; + cbdata.modlist = NULL; slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id, "modified \"%s\"\n", cbdata.ndn); /* Check for NULL entries, indicative of a failure elsewhere (?). */ @@ -1499,6 +1636,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb) "post-modify entry is NULL\n"); return 0; } + cbdata.modlist = backend_shr_mods_as_string(cbdata.mods); /* Modify map entries which corresponded to this directory server * entry. */ wrap_inc_call_level(); @@ -1512,10 +1650,10 @@ backend_shr_modify_cb(Slapi_PBlock *pb) } /* 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); + backend_shr_update_references(cbdata.state, cbdata.e_pre, cbdata.mods); /* 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); + backend_shr_update_references(cbdata.state, cbdata.e_post, cbdata.mods); /* If it's a map configuration entry, reconfigure, clear, and * repopulate the map. */ if (backend_shr_entry_is_a_set(cbdata.state, pb, cbdata.e_pre)) { @@ -1545,6 +1683,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb) } map_unlock(); wrap_dec_call_level(); + free(cbdata.modlist); return 0; } @@ -1746,7 +1885,7 @@ backend_shr_delete_cb(Slapi_PBlock *pb) } /* 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); + backend_shr_update_references(cbdata.state, cbdata.e, NULL); map_unlock(); wrap_dec_call_level(); return 0; |