ldap/servers/slapd/entry.c | 10
ldap/servers/slapd/entrywsi.c | 553 +++++++++++++++++++++++++---------------
ldap/servers/slapd/proto-slap.h | 1
ldap/servers/slapd/valueset.c | 9
4 files changed, 378 insertions(+), 195 deletions(-)
New commits:
commit c7f6f161f4967635d6f02b029be571d88ec61961
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Wed Mar 20 14:46:33 2013 +0100
Reduce replication meta data stored in entry, cf ticket 569
Reviewed by richm, thanks
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 01446ff..6ca4c72 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -1718,6 +1718,16 @@ entry2str_internal_put_attrlist( const Slapi_Attr *attrlist, int
attr_state, int
else
{
/* There were no present values on which to place the ADCSN, so we put it on the
first deleted value. */
+ if ( valueset_isempty(&a->a_deleted_values)) {
+ /* this means the entry is deleted and has no more attributes,
+ * when writing the attr to disk we would loose the AD-csn.
+ * Add an empty value to the set of deleted values. This will
+ * never be seen by any client. It will never be moved to the
+ * present values and is only used to preserve the AD-csn
+ */
+ valueset_add_string (&a->a_deleted_values, "",
CSN_TYPE_VALUE_DELETED, a->a_deletioncsn);
+ }
+
entry2str_internal_put_valueset(a->a_type, a->a_deletioncsn,
CSN_TYPE_ATTRIBUTE_DELETED, attr_state, &a->a_deleted_values, VALUE_DELETED, ecur,
typebuf, typebuf_len, entry2str_ctrl);
}
}
diff --git a/ldap/servers/slapd/entrywsi.c b/ldap/servers/slapd/entrywsi.c
index 578cb4f..c786b87 100644
--- a/ldap/servers/slapd/entrywsi.c
+++ b/ldap/servers/slapd/entrywsi.c
@@ -419,25 +419,129 @@ entry_add_present_attribute_wsi(Slapi_Entry *e, Slapi_Attr *a)
* Preserves LDAP Information Model constraints,
* returning an LDAP result code.
*/
+static void resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int
attribute_state);
+static void resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a,
Slapi_Value **valuestoupdate);
+static void resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a,
Slapi_Value **valuestoupdate);
+static void resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a,
Slapi_Value **valuestoupdate, int attribute_state);
+static int entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type,
struct berval **bervals, const CSN *csn, int urp, long flags);
+static int entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type,
struct berval **bervals, const CSN *csn, int urp, long flags);
static int
entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **bervals,
const CSN *csn, int urp, long flags)
{
+ int retVal = LDAP_SUCCESS;
+ Slapi_Attr *a= NULL;
+ int attr_state= entry_attr_find_wsi(e, type, &a);
+ if (ATTRIBUTE_NOTFOUND == attr_state)
+ {
+ /* Create a new attribute */
+ a = slapi_attr_new();
+ slapi_attr_init(a, type);
+ attrlist_add(&e->e_attrs, a);
+ }
+
+ if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
+ {
+ retVal = entry_add_present_values_wsi_single_valued( e, type, bervals, csn, urp, 0 );
+ }
+ else
+ {
+ retVal = entry_add_present_values_wsi_multi_valued( e, type, bervals, csn, urp, 0 );
+ }
+ return retVal;
+}
+static int
+entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct
berval **bervals, const CSN *csn, int urp, long flags)
+{
int retVal= LDAP_SUCCESS;
- Slapi_Value **valuestoadd = NULL;
- valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
+ Slapi_Value **valuestoadd = NULL;
+ valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
if(!valuearray_isempty(valuestoadd))
{
Slapi_Attr *a= NULL;
long a_flags_orig;
int attr_state= entry_attr_find_wsi(e, type, &a);
- if (ATTRIBUTE_NOTFOUND == attr_state)
+ a_flags_orig = a->a_flags;
+ a->a_flags |= flags;
+ /* Check if the type of the to-be-added values has DN syntax or not. */
+ if (slapi_attr_is_dn_syntax_attr(a)) {
+ valuearray_dn_normalize_value(valuestoadd);
+ a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
+ }
+ if(urp)
{
- /* Create a new attribute */
- a = slapi_attr_new();
- slapi_attr_init(a, type);
- attrlist_add(&e->e_attrs, a);
+ valueset_remove_valuearray (&a->a_present_values, a, valuestoadd,
+ SLAPI_VALUE_FLAG_IGNOREERROR |
+ SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
+ valueset_remove_valuearray (&a->a_deleted_values, a, valuestoadd,
+ SLAPI_VALUE_FLAG_IGNOREERROR |
+ SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
+ valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
+ valueset_add_valuearray_ext(&a->a_present_values, valuestoadd,
SLAPI_VALUE_FLAG_PASSIN);
+ slapi_ch_free ( (void **)&valuestoadd );
+
+ /*
+ * Now delete non-RDN values from a->a_present_values; and
+ * restore possible RDN values from a->a_deleted_values
+ */
+ resolve_attribute_state_single_valued(e, a, attr_state);
+ retVal= LDAP_SUCCESS;
}
- a_flags_orig = a->a_flags;
+ else
+ {
+ Slapi_Value **deletedvalues= NULL;
+ switch(attr_state)
+ {
+ case ATTRIBUTE_PRESENT:
+ /* The attribute is already on the present list */
+ break;
+ case ATTRIBUTE_DELETED:
+ /* Move the deleted attribute onto the present list */
+ entry_deleted_attribute_to_present_attribute(e, a);
+ break;
+ case ATTRIBUTE_NOTFOUND:
+ /* No-op - attribute was initialized & added to entry above */
+ break;
+ }
+ /* Check if any of the values to be added are on the deleted list */
+ valueset_remove_valuearray(&a->a_deleted_values,
+ a, valuestoadd,
+ SLAPI_VALUE_FLAG_IGNOREERROR|SLAPI_VALUE_FLAG_USENEWVALUE,
+ &deletedvalues); /* JCM Check return code */
+ if(deletedvalues!=NULL && deletedvalues[0]!=NULL)
+ {
+ /* Some of the values to be added were on the deleted list */
+ Slapi_Value **v= NULL;
+ Slapi_ValueSet vs;
+ /* Add each deleted value to the present list */
+ valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_UPDATED,csn);
+ valueset_add_valuearray_ext(&a->a_present_values, deletedvalues,
SLAPI_VALUE_FLAG_PASSIN);
+ /* Remove the deleted values from the values to add */
+ valueset_set_valuearray_passin(&vs,valuestoadd);
+ valueset_remove_valuearray(&vs, a, deletedvalues, SLAPI_VALUE_FLAG_IGNOREERROR,
&v);
+ valuestoadd= valueset_get_valuearray(&vs);
+ valuearray_free(&v);
+ slapi_ch_free((void **)&deletedvalues);
+ }
+ valuearray_update_csn(valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
+ retVal= attr_add_valuearray(a, valuestoadd, slapi_entry_get_dn_const(e));
+ valuearray_free(&valuestoadd);
+ }
+ a->a_flags = a_flags_orig;
+ }
+ return(retVal);
+}
+static int
+entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval
**bervals, const CSN *csn, int urp, long flags)
+{
+ int retVal= LDAP_SUCCESS;
+ Slapi_Value **valuestoadd = NULL;
+ valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
+ if(!valuearray_isempty(valuestoadd))
+ {
+ Slapi_Attr *a= NULL;
+ long a_flags_orig;
+ int attr_state= entry_attr_find_wsi(e, type, &a);
+ a_flags_orig = a->a_flags;
a->a_flags |= flags;
/* Check if the type of the to-be-added values has DN syntax or not. */
if (slapi_attr_is_dn_syntax_attr(a)) {
@@ -462,16 +566,14 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type,
struct berval **b
SLAPI_VALUE_FLAG_IGNOREERROR |
SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
- /* Append the pending values to a->a_present_values */
+ /* Now add the values in values to add to present or deleted
+ * values, depending on their csnset */
valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
- valueset_add_valuearray_ext(&a->a_present_values, valuestoadd,
SLAPI_VALUE_FLAG_PASSIN);
+
+ resolve_attribute_state_to_present_or_deleted(e, a, valuestoadd, attr_state);
+
slapi_ch_free ( (void **)&valuestoadd );
- /*
- * Now delete non-RDN values from a->a_present_values; and
- * restore possible RDN values from a->a_deleted_values
- */
- resolve_attribute_state(e, a, attr_state, 0);
retVal= LDAP_SUCCESS;
}
else
@@ -526,13 +628,155 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type,
struct berval **b
* returning an LDAP result code.
*/
static int
+entry_delete_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct
berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals);
+static int
+entry_delete_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct
berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals);
+static int
entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **vals,
const CSN *csn, int urp, int mod_op, struct berval **replacevals)
{
int retVal= LDAP_SUCCESS;
Slapi_Attr *a= NULL;
int attr_state= entry_attr_find_wsi(e, type, &a);
+
if(attr_state==ATTRIBUTE_PRESENT || (attr_state==ATTRIBUTE_DELETED && urp))
{
+ if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
+ retVal = entry_delete_present_values_wsi_single_valued(e, type, vals, csn, urp,
mod_op, replacevals);
+ else
+ retVal = entry_delete_present_values_wsi_multi_valued(e, type, vals, csn, urp, mod_op,
replacevals);
+ }
+ else if (attr_state==ATTRIBUTE_DELETED)
+ {
+#if defined(USE_OLD_UNHASHED)
+ if (is_type_forbidden(type)) {
+ retVal = LDAP_SUCCESS;
+ } else {
+ retVal= LDAP_NO_SUCH_ATTRIBUTE;
+ }
+#else
+ retVal= LDAP_NO_SUCH_ATTRIBUTE;
+#endif
+ }
+ else if (attr_state==ATTRIBUTE_NOTFOUND)
+ {
+#if defined(USE_OLD_UNHASHED)
+ if (is_type_protected(type) || is_type_forbidden(type))
+#else
+ if (is_type_protected(type))
+#endif
+ {
+ retVal = LDAP_SUCCESS;
+ } else {
+ if (!urp) {
+ LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
+ type);
+ }
+ retVal = LDAP_NO_SUCH_ATTRIBUTE;
+ }
+ if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
+ {
+ /* Create a new attribute and set the adcsn */
+ Slapi_Attr *a = slapi_attr_new();
+ slapi_attr_init(a, type);
+ attr_set_deletion_csn(a,csn);
+ entry_add_deleted_attribute_wsi(e, a);
+ }
+ }
+ return retVal;
+}
+static int
+entry_delete_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct
berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
+{
+ int retVal= LDAP_SUCCESS;
+ Slapi_Attr *a= NULL;
+ int attr_state= entry_attr_find_wsi(e, type, &a);
+ /* The attribute is on the present list, or the deleted list and we're doing URP */
+ if ( vals == NULL || vals[0] == NULL )
+ {
+ /* delete the entire attribute */
+ LDAPDebug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", type, 0, 0 );
+ attr_set_deletion_csn(a,csn);
+ if(urp)
+ {
+ resolve_attribute_state_single_valued(e, a, attr_state);
+ /* resolve attr state single valued */
+ /* keep_present =
check_attr_single_value_is_distingiuished(&a->a_present_values);
+ if ( !keep_present) {
+ slapi_valueset_done(&a->a_present_values);
+ entry_present_attribute_to_deleted_attribute(e, a);
+ }
+ */
+ }
+ else
+ {
+ slapi_valueset_done(&a->a_present_values);
+ entry_present_attribute_to_deleted_attribute(e, a);
+ }
+ retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present
*/
+ }
+ else
+ {
+ /* delete some specific values */
+ Slapi_Value **valuestodelete= NULL;
+ valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
+ /* Check if the type of the to-be-deleted values has DN syntax
+ * or not. */
+ if (slapi_attr_is_dn_syntax_attr(a)) {
+ valuearray_dn_normalize_value(valuestodelete);
+ a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
+ }
+ if(urp)
+ {
+ Slapi_Value **valuesupdated= NULL;
+ valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete,
CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
+ if( valuesupdated && *valuesupdated)
+ {
+ attr_set_deletion_csn(a,csn);
+ }
+ /* resolve attr state single valued */
+ valuearray_free(&valuesupdated);
+ valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete,
CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
+ valuearray_free(&valuesupdated);
+ valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
+ valueset_add_valuearray_ext(&a->a_deleted_values, valuestodelete,
SLAPI_VALUE_FLAG_PASSIN);
+ slapi_ch_free((void **)&valuestodelete);
+ resolve_attribute_state_single_valued(e, a, attr_state);
+ retVal= LDAP_SUCCESS;
+ }
+ else
+ {
+ Slapi_Value **deletedvalues= NULL;
+ retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0
/* Do Not Ignore Errors */,&deletedvalues);
+ if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
+ {
+ valuearray_free(&deletedvalues);
+ /* The attribute is single valued and the value was successful deleted */
+ entry_present_attribute_to_deleted_attribute(e, a);
+ }
+ else if (retVal != LDAP_SUCCESS)
+ {
+ /* Failed
+ * - Value not found
+ * - Operations error
+ */
+ if ( retVal==LDAP_OPERATIONS_ERROR )
+ {
+ LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
+ "value for attribute type %s found in "
+ "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
+ }
+ }
+ valuearray_free(&valuestodelete);
+ }
+ }
+ return( retVal );
+}
+static int
+entry_delete_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct
berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
+{
+ int retVal= LDAP_SUCCESS;
+ Slapi_Attr *a= NULL;
+ int attr_state= entry_attr_find_wsi(e, type, &a);
/* The attribute is on the present list, or the deleted list and we're doing URP
*/
if ( vals == NULL || vals[0] == NULL )
{
@@ -541,16 +785,19 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type,
struct berval
attr_set_deletion_csn(a,csn);
if(urp)
{
- resolve_attribute_state(e, a, attr_state, 1 /* set delete priority */); /* ABSOLVED
*/
+ /* there might be values added or specifically deleted later than
+ * the current attr delete operation. These values need to be
+ * preserved, all others can be removed, purging should o the job.
+ */
+ valueset_purge(&a->a_present_values, csn);
+ valueset_purge(&a->a_deleted_values, csn);
+ if(valueset_isempty(&a->a_present_values))
+ entry_present_attribute_to_deleted_attribute(e, a);
}
else
{
- if(!slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
- {
- /* We don't maintain a deleted value list for single valued attributes */
- valueset_add_valueset(&a->a_deleted_values, &a->a_present_values); /*
JCM Would be better to passin the valuestodelete */
- }
slapi_valueset_done(&a->a_present_values);
+ slapi_valueset_done(&a->a_deleted_values);
entry_present_attribute_to_deleted_attribute(e, a);
}
retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present
*/
@@ -558,8 +805,8 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type,
struct berval
else
{
/* delete some specific values */
- Slapi_Value **valuestodelete= NULL;
- valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
+ Slapi_Value **valuestodelete= NULL;
+ valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
/* Check if the type of the to-be-deleted values has DN syntax
* or not. */
if (slapi_attr_is_dn_syntax_attr(a)) {
@@ -568,47 +815,43 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type,
struct berval
}
if(urp)
{
+ /* check if values to delete are in present values
+ * if v in present values and VU-csn<csn and v not distinguished move to deleted
values
+ * if v not in present values, check deleted values and update csn, if distinguisehed
at csn
+ * move back to present values
+ */
+
+
Slapi_Value **valuesupdated= NULL;
- valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete,
CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
- /* if we removed the last value, we need to mark the attribute as deleted
- the resolve_attribute_state() code will "resurrect" the attribute if
- there are present values with a later CSN - otherwise, even though
- the value will be updated with a VDCSN which is later than the VUCSN,
- the attribute will not be deleted */
- if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE) && valuesupdated
&&
- *valuesupdated)
- {
- attr_set_deletion_csn(a,csn);
- }
+ valueset_update_csn_for_valuearray_ext(&a->a_present_values, a,
valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
+ resolve_attribute_state_present_to_deleted(e, a, valuesupdated);
valuearray_free(&valuesupdated);
- valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete,
CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
+
+ valueset_update_csn_for_valuearray_ext(&a->a_deleted_values, a,
valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
+ resolve_attribute_state_deleted_to_present(e, a, valuesupdated);
valuearray_free(&valuesupdated);
+
valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
valueset_add_valuearray_ext(&a->a_deleted_values, valuestodelete,
SLAPI_VALUE_FLAG_PASSIN);
/* all the elements in valuestodelete are passed;
* should free valuestodelete only (don't call valuearray_free)
* [622023] */
slapi_ch_free((void **)&valuestodelete);
- resolve_attribute_state(e, a, attr_state, 0);
retVal= LDAP_SUCCESS;
}
else
{
+ /* find the values to delete in present values,
+ * update the csns and add to the deleted values
+ */
Slapi_Value **deletedvalues= NULL;
retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0
/* Do Not Ignore Errors */,&deletedvalues);
if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
{
- if(!slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
- {
- /* We don't maintain a deleted value list for single valued attributes */
- /* Add each deleted value to the deleted set */
- valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_DELETED,csn);
- valueset_add_valuearray_ext(&a->a_deleted_values, deletedvalues,
SLAPI_VALUE_FLAG_PASSIN);
- slapi_ch_free((void **)&deletedvalues);
- }
- else {
- valuearray_free(&deletedvalues);
- }
+ /* Add each deleted value to the deleted set */
+ valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_DELETED,csn);
+ valueset_add_valuearray_ext(&a->a_deleted_values, deletedvalues,
SLAPI_VALUE_FLAG_PASSIN);
+ slapi_ch_free((void **)&deletedvalues);
if(valueset_isempty(&a->a_present_values))
{
/* There are no present values, so move the
@@ -619,7 +862,6 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type,
struct berval
else if (retVal != LDAP_SUCCESS)
{
/* Failed
- * - Duplicate value
* - Value not found
* - Operations error
*/
@@ -633,69 +875,6 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type,
struct berval
valuearray_free(&valuestodelete);
}
}
- }
- else if (attr_state==ATTRIBUTE_DELETED)
- {
- /* If the type is in the forbidden attr list (e.g., unhashed password),
- * we don't return the reason of the failure to the clients. */
-#if defined(USE_OLD_UNHASHED)
- if (is_type_forbidden(type)) {
- retVal = LDAP_SUCCESS;
- } else {
- retVal= LDAP_NO_SUCH_ATTRIBUTE;
- }
-#else
- retVal= LDAP_NO_SUCH_ATTRIBUTE;
-#endif
- }
- else if (attr_state==ATTRIBUTE_NOTFOUND)
- {
- /*
- * If type is in the protected_attrs_all list, we could ignore the
- * failure, as the attribute could only exist in the entry in the
- * memory when the add/mod operation is done, while the retried entry
- * from the db does not contain the attribute.
- * So is in the forbidden_attrs list. We don't return the reason
- * of the failure.
- */
-#if defined(USE_OLD_UNHASHED)
- if (is_type_protected(type) || is_type_forbidden(type))
-#else
- if (is_type_protected(type))
-#endif
- {
- retVal = LDAP_SUCCESS;
- } else {
- if (!urp) {
- /* Only warn if not urping */
- LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
- type);
- }
- retVal = LDAP_NO_SUCH_ATTRIBUTE;
- }
- /* NOTE: LDAP says that a MOD REPLACE with no vals of a non-existent
- attribute is a no-op - MOD REPLACE with some vals will add the attribute */
- /* if we are doing a replace with actual values, meaning the result
- of the mod is that the attribute will have some values, we need to create
- a dummy attribute for entry_add_present_values_wsi to use, and set
- the deletion csn to the csn of the current operation */
- /* note that if LDAP_MOD_REPLACE == mod_op then vals is NULL -
- see entry_replace_present_values_wsi */
- if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
- {
- /* Create a new attribute and set the adcsn */
- Slapi_Attr *a = slapi_attr_new();
- slapi_attr_init(a, type);
- attr_set_deletion_csn(a,csn);
- /* mark the attribute as deleted - it does not really
- exist yet - the code in entry_add_present_values_wsi
- will add it back to the present list in the non urp case,
- or determine if the attribute needs to be added
- or not in the urp case
- */
- entry_add_deleted_attribute_wsi(e, a);
- }
- }
return( retVal );
}
@@ -825,7 +1004,7 @@ entry_apply_mods_wsi(Slapi_Entry *e, Slapi_Mods *smods, const CSN
*csn, int urp)
and the csn doesn't already have a subsequence
if the csn already has a subsequence, assume it was generated
on another replica in the correct order */
- if (urp && (csn_get_subseqnum(csn) == 0)) {
+ if (csn_get_subseqnum(csn) == 0) {
csn_increment_subsequence(&localcsn);
}
}
@@ -1043,87 +1222,54 @@ value_distinguished_at_csn(const Slapi_Entry *e, const Slapi_Attr
*original_attr
return r;
}
+/* This call ensures that the value does not contain a deletion_csn which is before the
presence_csn or distinguished_csn of the value. */
static void
-resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state,
int delete_priority)
+resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value
**valuestoupdate)
{
- int i;
+ const CSN *vdcsn;
+ const CSN *vucsn;
+ const CSN *deletedcsn;
const CSN *adcsn= attr_get_deletion_csn(a);
- Slapi_ValueSet *vs= valueset_dup(&a->a_present_values); /* JCM This is slow...
but otherwise we end up iterating through a changing array */
- Slapi_Value *v;
-
- /* Loop over the present attribute values */
- i= slapi_valueset_first_value( vs, &v );
- while(v!=NULL)
- {
- const CSN *vdcsn;
- const CSN *vucsn;
- const CSN *deletedcsn;
- /* This call ensures that the value does not contain a deletion_csn
- * which is before the presence_csn or distinguished_csn of the value.
- */
- purge_attribute_state_multi_valued(a, v);
- vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
- vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
- deletedcsn= csn_max(vdcsn, adcsn);
-
- /* Check if the attribute or value was deleted after the value was
- * last updated. If the value update CSN and the deleted CSN are
- * the same (meaning they are separate mods from the same exact
- * operation), we should only delete the value if delete priority
- * is set. Delete priority should only be set when we are deleting
- * all value of an attribute. This prevents us from leaving a value
- * that was added as a previous mod in the same exact modify
- * operation as the subsequent delete.*/
- if((csn_compare(vucsn,deletedcsn)<0) ||
- (delete_priority && (csn_compare(vucsn,deletedcsn) == 0)))
- {
- if(!value_distinguished_at_csn(e, a, v, deletedcsn))
+ int i;
+ if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
+ for (i=0;valuestoupdate[i]!=NULL;++i) {
+ purge_attribute_state_multi_valued(a, valuestoupdate[i]);
+ vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
+ vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
+ deletedcsn= csn_max(vdcsn, adcsn);
+ if((csn_compare(vucsn,deletedcsn)>=0) ||
+ value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
{
- entry_present_value_to_deleted_value(a,v);
+ entry_deleted_value_to_present_value(a,valuestoupdate[i]);
}
+ valuestoupdate[i]->v_csnset = NULL;
}
- i= slapi_valueset_next_value( vs, i, &v );
}
- slapi_valueset_free(vs);
-
- /* Loop over the deleted attribute values */
- vs= valueset_dup(&a->a_deleted_values); /* JCM This is slow... but otherwise we
end up iterating through a changing array */
- i= slapi_valueset_first_value( vs, &v );
- while(v!=NULL)
- {
- const CSN *vdcsn;
- const CSN *vucsn;
- const CSN *deletedcsn;
- /* This call ensures that the value does not contain a deletion_csn which is before
the presence_csn or distinguished_csn of the value. */
- purge_attribute_state_multi_valued(a, v);
- vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
- vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
- deletedcsn= csn_max(vdcsn, adcsn);
+}
- /* check if the attribute or value was deleted after the value was last updated */
- /* When a replace operation happens, the entry_replace_present_values_wsi() function
- * first calls entry_delete_present_values_wsi with vals == NULL to essentially delete
- * the attribute and set the deletion csn. If the urp flag is set (urp in this case
- * meaning the operation is a replicated op), entry_delete_present_values_wsi will
- * call this function which will move the present values to the deleted values
- * (see above - delete_priority will be 1) then the below code will move the
- * attribute to the deleted list.
- * next, entry_replace_present_values_wsi will call entry_add_present_values_wsi
- * to add the values provided in the replace operation. We need to be able to
- * "resurrect" these deleted values and resurrect the deleted attribute. In
the
- * replace case, the deletedcsn will be the same as the vucsn of the values that
- * should be present values.
- */
- if((csn_compare(vucsn,deletedcsn)>0) ||
- ((delete_priority == 0) && (csn_compare(vucsn,deletedcsn)==0)) ||
- value_distinguished_at_csn(e, a, v, deletedcsn))
- {
- entry_deleted_value_to_present_value(a,v);
+static void
+resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value
**valuestoupdate, int attribute_state)
+{
+ const CSN *vdcsn;
+ const CSN *vucsn;
+ const CSN *deletedcsn;
+ const CSN *adcsn= attr_get_deletion_csn(a);
+ int i;
+ if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
+ for (i=0;valuestoupdate[i]!=NULL;++i) {
+ purge_attribute_state_multi_valued(a, valuestoupdate[i]);
+ vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
+ vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
+ deletedcsn= csn_max(vdcsn, adcsn);
+ if((csn_compare(vucsn,deletedcsn)>=0) ||
+ value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
+ {
+ slapi_valueset_add_value_ext(&a->a_present_values, valuestoupdate[i],
SLAPI_VALUE_FLAG_PASSIN);
+ } else {
+ slapi_valueset_add_value_ext(&a->a_deleted_values, valuestoupdate[i],
SLAPI_VALUE_FLAG_PASSIN);
+ }
}
- i= slapi_valueset_next_value( vs, i, &v );
}
- slapi_valueset_free(vs);
-
if(valueset_isempty(&a->a_present_values))
{
if(attribute_state==ATTRIBUTE_PRESENT)
@@ -1141,6 +1287,35 @@ resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a,
int attribut
}
static void
+resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value
**valuestoupdate)
+{
+ const CSN *vdcsn;
+ const CSN *vucsn;
+ const CSN *deletedcsn;
+ const CSN *adcsn= attr_get_deletion_csn(a);
+ int i;
+ if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
+ for (i=0;valuestoupdate[i]!=NULL;++i) {
+ /* This call ensures that the value does not contain a deletion_csn
+ * which is before the presence_csn or distinguished_csn of the value.
+ */
+ purge_attribute_state_multi_valued(a, valuestoupdate[i]);
+ vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
+ vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
+ deletedcsn= csn_max(vdcsn, adcsn);
+ if(csn_compare(vucsn,deletedcsn)<0)
+ {
+ if(!value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
+ {
+ entry_present_value_to_deleted_value(a,valuestoupdate[i]);
+ }
+ }
+ valuestoupdate[i]->v_csnset = NULL;
+ }
+ }
+}
+
+static void
resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int
attribute_state)
{
Slapi_Value *current_value= NULL;
@@ -1292,15 +1467,3 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr
*a, int attribu
}
}
-static void
-resolve_attribute_state(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int
delete_priority)
-{
- if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
- {
- resolve_attribute_state_single_valued(e,a,attribute_state);
- }
- else
- {
- resolve_attribute_state_multi_valued(e,a,attribute_state, delete_priority);
- }
-}
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 2f16618..9b0072b 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -195,6 +195,7 @@ Slapi_ValueSet *valueset_dup(const Slapi_ValueSet *dupee);
void valueset_remove_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s);
int valueset_replace(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **vals);
void valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a,
Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated);
+void valueset_update_csn_for_valuearray_ext(Slapi_ValueSet *vs, const Slapi_Attr *a,
Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated, int
csnref_updated);
void valueset_set_valuearray_byval(Slapi_ValueSet *vs, Slapi_Value **addvals);
void valueset_set_valuearray_passin(Slapi_ValueSet *vs, Slapi_Value **addvals);
int valuearray_subtract_bvalues(Slapi_Value **va, struct berval **bvals);
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
index 6bc3ffa..c041714 100644
--- a/ldap/servers/slapd/valueset.c
+++ b/ldap/servers/slapd/valueset.c
@@ -1428,6 +1428,11 @@ valueset_replace(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value
**valstoreplace)
void
valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value
**valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated)
{
+ valueset_update_csn_for_valuearray_ext(vs, a, valuestoupdate, t, csn, valuesupdated,
0);
+}
+void
+valueset_update_csn_for_valuearray_ext(Slapi_ValueSet *vs, const Slapi_Attr *a,
Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated, int
csnref_updated)
+{
if(!valuearray_isempty(valuestoupdate) &&
!valuearray_isempty(vs->va))
{
@@ -1450,6 +1455,8 @@ valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const
Slapi_Attr *a, Slap
if(rc==LDAP_SUCCESS)
{
value_update_csn(vs->va[index],t,csn);
+ if (csnref_updated)
+ valuestoupdate[i]->v_csnset = value_get_csnset(vs->va[index]);
valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
valuestoupdate[i] = NULL;
}
@@ -1465,6 +1472,8 @@ valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const
Slapi_Attr *a, Slap
if(index!=-1)
{
value_update_csn(vs->va[index],t,csn);
+ if (csnref_updated)
+ valuestoupdate[i]->v_csnset = value_get_csnset(vs->va[index]);
valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
valuestoupdate[i]= NULL;
}