summaryrefslogtreecommitdiffstats
path: root/src/back-shr.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@dahyabhai.net>2012-01-06 15:42:33 -0500
committerNalin Dahyabhai <nalin@dahyabhai.net>2012-01-06 15:42:33 -0500
commit80c8021ef1dcf911c170dc7917b1de9087b0b8e0 (patch)
tree70a037e20a2093c5fc54d4c5335511954e16f126 /src/back-shr.c
parentd361fe8707d3558a9bad59c61b1f124d2de17772 (diff)
downloadslapi-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.c151
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;