summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ldap/servers/slapd/entrywsi.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/ldap/servers/slapd/entrywsi.c b/ldap/servers/slapd/entrywsi.c
index 9923f57f..579d044d 100644
--- a/ldap/servers/slapd/entrywsi.c
+++ b/ldap/servers/slapd/entrywsi.c
@@ -46,7 +46,7 @@
#include "slap.h"
#include "slapi-plugin.h"
-static void resolve_attribute_state(Slapi_Entry *e, Slapi_Attr *a, int attribute_state);
+static void resolve_attribute_state(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority);
static int
entry_present_value_to_deleted_value(Slapi_Attr *a, Slapi_Value *v)
@@ -477,7 +477,7 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **b
* 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);
+ resolve_attribute_state(e, a, attr_state, 0);
retVal= LDAP_SUCCESS;
}
else
@@ -547,7 +547,7 @@ 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); /* ABSOLVED */
+ resolve_attribute_state(e, a, attr_state, 1 /* set delete priority */); /* ABSOLVED */
}
else
{
@@ -589,7 +589,7 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
* should free valuestodelete only (don't call valuearray_free)
* [622023] */
slapi_ch_free((void **)&valuestodelete);
- resolve_attribute_state(e, a, attr_state);
+ resolve_attribute_state(e, a, attr_state, 0);
retVal= LDAP_SUCCESS;
}
else
@@ -955,7 +955,7 @@ value_distinguished_at_csn(const Slapi_Entry *e, const Slapi_Attr *original_attr
}
static void
-resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state)
+resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority)
{
int i;
const CSN *adcsn= attr_get_deletion_csn(a);
@@ -976,7 +976,17 @@ resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribut
vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
deletedcsn= csn_max(vdcsn, adcsn);
- if(csn_compare(vucsn,deletedcsn)<0) /* check if the attribute or value was deleted after the value was last updated */
+
+ /* 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))
{
@@ -1000,7 +1010,9 @@ resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribut
vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
deletedcsn= csn_max(vdcsn, adcsn);
- if((csn_compare(vucsn,deletedcsn)>=0) || /* check if the attribute or value was deleted after the value was last updated */
+
+ /* check if the attribute or value was deleted after the value was last updated */
+ if((csn_compare(vucsn,deletedcsn)>0) ||
value_distinguished_at_csn(e, a, v, deletedcsn))
{
entry_deleted_value_to_present_value(a,v);
@@ -1178,7 +1190,7 @@ 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)
+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))
{
@@ -1186,6 +1198,6 @@ resolve_attribute_state(Slapi_Entry *e, Slapi_Attr *a, int attribute_state)
}
else
{
- resolve_attribute_state_multi_valued(e,a,attribute_state);
+ resolve_attribute_state_multi_valued(e,a,attribute_state, delete_priority);
}
}