diff options
-rw-r--r-- | ldap/servers/slapd/entrywsi.c | 30 |
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); } } |