From 338657055966f3273958243e7125d7605ac879bc Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Thu, 19 Jan 2012 07:15:40 -0500 Subject: - don't lean so hard on slapi_entry_diff(), when if we do it ourselves, the official mods list already narrows down the work needed to get the results we're interested in seeing --- src/back-shr.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 2 deletions(-) (limited to 'src/back-shr.c') diff --git a/src/back-shr.c b/src/back-shr.c index 3130d08..c553b12 100644 --- a/src/back-shr.c +++ b/src/back-shr.c @@ -829,7 +829,7 @@ backend_shr_mods_as_string(LDAPMod **mods) ret = NULL; for (i = 0, length = 0; (mods != NULL) && (mods[i] != NULL); i++) { - length += (strlen(mods[i]->mod_type) + 1); + length += (strlen(mods[i]->mod_type) + 1 + 8); } if (length > 0) { ret = malloc(length); @@ -839,6 +839,18 @@ backend_shr_mods_as_string(LDAPMod **mods) if (i > 0) { strcpy(ret + length++, ","); } + if (SLAPI_IS_MOD_ADD(mods[i]->mod_op)) { + strcpy(ret + length, "add:"); + length += 4; + } + if (SLAPI_IS_MOD_REPLACE(mods[i]->mod_op)) { + strcpy(ret + length, "replace:"); + length += 8; + } + if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op)) { + strcpy(ret + length, "delete:"); + length += 7; + } strcpy(ret + length, mods[i]->mod_type); length += strlen(mods[i]->mod_type); } @@ -1741,6 +1753,174 @@ backend_shr_modify_entry_cb(const char *group, const char *set, bool_t flag, return TRUE; } +static Slapi_Mod * +backend_shr_mod_as_smod(LDAPMod *mod) +{ + Slapi_Mod *ret; + ret = slapi_mod_new(); + slapi_mod_init_byval(ret, mod); + return ret; +} + +/* Walk the list of mods, picking out those which won't have an effect, and + * adding the rest to the "relevant" list. */ +static void +backend_shr_filter_mods(LDAPMod **mods, Slapi_Entry *pre, Slapi_Entry *post, + Slapi_Mods *relevant) +{ + LDAPMod *mod; + Slapi_ValueSet *values; + Slapi_Value *value, *mval; + const struct berval *mbv, *ebv; + struct berval msv; + char *actual_attr; + int i, j, k, result, disposition, buffer_flags; + + if (mods == NULL) { + return; + } + mval = slapi_value_new(); + for (i = 0; mods[i] != NULL; i++) { + mod = mods[i]; + if (slapi_vattr_values_get(pre, mod->mod_type, &values, + &disposition, &actual_attr, + 0, &buffer_flags) != 0) { + /* error of some kind, punt */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + continue; + } + if (SLAPI_IS_MOD_DELETE(mod->mod_op)) { + /* if the target entry has values, and one of the ones + * we're removing is in the entry, keep it */ + if (slapi_valueset_count(values) != 0) { + if (mod->mod_op & LDAP_MOD_BVALUES) { + if (mod->mod_vals.modv_bvals == NULL) { + /* request is to remove all values */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + } else + for (j = 0; mod->mod_vals.modv_bvals[j] != NULL; j++) { + mbv = mod->mod_vals.modv_bvals[j]; + mval = slapi_value_set_berval(mval, mbv); + if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) == 0) && + (result == 1)) { + /* request is to remove a value that is present */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + break; + } + } + } else { + if (mod->mod_vals.modv_strvals == NULL) { + /* request is to remove all values */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + } else + for (j = 0; mod->mod_vals.modv_strvals[j] != NULL; j++) { + msv.bv_val = mod->mod_vals.modv_strvals[j]; + msv.bv_len = strlen(msv.bv_val); + mval = slapi_value_set_berval(mval, &msv); + if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) == 0) && + (result == 1)) { + /* request is to remove a value that is present */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + break; + } + } + } + } + } else + if (SLAPI_IS_MOD_ADD(mod->mod_op)) { + /* if all of the provided values are already in the + * entry, then skip it */ + if (mod->mod_op & LDAP_MOD_BVALUES) { + if (mod->mod_vals.modv_bvals != NULL) { + for (j = 0; mod->mod_vals.modv_bvals[j] != NULL; j++) { + mbv = mod->mod_vals.modv_bvals[j]; + mval = slapi_value_set_berval(mval, mbv); + if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) != 0) || + (result != 1)) { + /* request is to add a value that is not present */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + break; + } + } + } + } else { + if (mod->mod_vals.modv_strvals != NULL) { + for (j = 0; mod->mod_vals.modv_strvals[j] != NULL; j++) { + msv.bv_val = mod->mod_vals.modv_strvals[j]; + msv.bv_len = strlen(msv.bv_val); + mval = slapi_value_set_berval(mval, &msv); + if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) != 0) || + (result != 1)) { + /* request is to add a value that is not present */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + break; + } + } + } + } + } else + if (SLAPI_IS_MOD_REPLACE(mod->mod_op)) { + /* if the value set is the same as the list we're + * given, then skip it */ + j = 0; + if (mod->mod_op & LDAP_MOD_BVALUES) { + if (mod->mod_vals.modv_bvals != NULL) { + for (j = 0; mod->mod_vals.modv_bvals[j] != NULL; j++) { + continue; + } + } + if (slapi_valueset_count(values) != j) { + /* different number of values */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + } else { + for (j = 0; + (mod->mod_vals.modv_bvals != NULL) && + (mod->mod_vals.modv_bvals[j] != NULL); + j++) { + mbv = mod->mod_vals.modv_bvals[j]; + mval = slapi_value_set_berval(mval, mbv); + if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) != 0) || + (result != 1)) { + /* request includes a value that is not present */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + break; + } + } + } + } else { + if (mod->mod_vals.modv_strvals != NULL) { + for (j = 0; mod->mod_vals.modv_strvals[j] != NULL; j++) { + continue; + } + } + if (slapi_valueset_count(values) != j) { + /* different number of values */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + } else { + for (j = 0; + (mod->mod_vals.modv_strvals != NULL) && + (mod->mod_vals.modv_strvals[j] != NULL); + j++) { + msv.bv_val = mod->mod_vals.modv_strvals[j]; + msv.bv_len = strlen(msv.bv_val); + mval = slapi_value_set_berval(mval, &msv); + if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) != 0) || + (result != 1)) { + /* request includes a value that is not present */ + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + break; + } + } + } + } + } else { + slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod)); + } + slapi_vattr_values_free(&values, &actual_attr, buffer_flags); + } + slapi_value_free(&mval); +} + static int backend_shr_modify_cb(Slapi_PBlock *pb) { @@ -1805,7 +1985,8 @@ backend_shr_modify_cb(Slapi_PBlock *pb) /* Don't do a lot of work for other plugins which initiated a no-op * modify. */ cbdata.real_mods = slapi_mods_new(); - slapi_entry_diff(cbdata.real_mods, cbdata.e_pre, cbdata.e_post, 0); + backend_shr_filter_mods(cbdata.mods, cbdata.e_pre, cbdata.e_post, + cbdata.real_mods); cbdata.mods = slapi_mods_get_ldapmods_byref(cbdata.real_mods); cbdata.ndn = slapi_entry_get_ndn(cbdata.e_pre); if (cbdata.mods == NULL) { @@ -1843,6 +2024,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb) cbdata.mods, cbdata.modlist); /* Done with the "real" mods. Put the fake ones back. */ slapi_mods_free(&cbdata.real_mods); + cbdata.real_mods = NULL; slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &cbdata.mods); /* If it's a map configuration entry, reconfigure, clear, and * repopulate the map. */ -- cgit