|
|
dc8c34 |
From 3aac2e421bb6c2543b2ff2795664ba50a7ceeec9 Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Rich Megginson <rmeggins@redhat.com>
|
|
|
dc8c34 |
Date: Wed, 17 Jul 2013 17:51:36 -0600
|
|
|
dc8c34 |
Subject: [PATCH 80/99] Ticket #47424 - Replication problem with add-delete
|
|
|
dc8c34 |
requests on single-valued attributes
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/47424
|
|
|
dc8c34 |
Reviewed by: lkrispenz (Thanks!)
|
|
|
dc8c34 |
Branch: 389-ds-base-1.2.11
|
|
|
dc8c34 |
Fix Description: Change the single master resolve attr code to handle the
|
|
|
dc8c34 |
specific case of doing
|
|
|
dc8c34 |
add: newvalue
|
|
|
dc8c34 |
delete: oldvalue
|
|
|
dc8c34 |
Had to add a new API function - csn_compare_ext - to be able to compare CSNs
|
|
|
dc8c34 |
without the subsequence number.
|
|
|
dc8c34 |
Platforms tested: RHEL6 x86_64
|
|
|
dc8c34 |
Flag Day: no
|
|
|
dc8c34 |
Doc impact: no
|
|
|
dc8c34 |
(cherry picked from commit bf53a29af973648c520b005ad37f7a83db4b905b)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
ldap/servers/slapd/csn.c | 12 +++-
|
|
|
dc8c34 |
ldap/servers/slapd/entrywsi.c | 122 +++++++++++++++++++++----------------
|
|
|
dc8c34 |
ldap/servers/slapd/slapi-private.h | 2 +
|
|
|
dc8c34 |
3 files changed, 83 insertions(+), 53 deletions(-)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/csn.c b/ldap/servers/slapd/csn.c
|
|
|
dc8c34 |
index 9fb5b4a..5c31689 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/csn.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/csn.c
|
|
|
dc8c34 |
@@ -298,7 +298,7 @@ csn_as_attr_option_string(CSNType t,const CSN *csn,char *ss)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
-csn_compare(const CSN *csn1, const CSN *csn2)
|
|
|
dc8c34 |
+csn_compare_ext(const CSN *csn1, const CSN *csn2, unsigned int flags)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
PRInt32 retVal;
|
|
|
dc8c34 |
if(csn1!=NULL && csn2!=NULL)
|
|
|
dc8c34 |
@@ -321,7 +321,7 @@ csn_compare(const CSN *csn1, const CSN *csn2)
|
|
|
dc8c34 |
retVal = -1;
|
|
|
dc8c34 |
else if (csn1->rid > csn2->rid)
|
|
|
dc8c34 |
retVal = 1;
|
|
|
dc8c34 |
- else
|
|
|
dc8c34 |
+ else if (!(flags & CSN_COMPARE_SKIP_SUBSEQ))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
if (csn1->subseqnum < csn2->subseqnum)
|
|
|
dc8c34 |
retVal = -1;
|
|
|
dc8c34 |
@@ -330,6 +330,8 @@ csn_compare(const CSN *csn1, const CSN *csn2)
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
retVal = 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ else
|
|
|
dc8c34 |
+ retVal = 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -350,6 +352,12 @@ csn_compare(const CSN *csn1, const CSN *csn2)
|
|
|
dc8c34 |
return(retVal);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+csn_compare(const CSN *csn1, const CSN *csn2)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ return csn_compare_ext(csn1, csn2, 0);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
time_t csn_time_difference(const CSN *csn1, const CSN *csn2)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
return csn_get_time(csn1) - csn_get_time(csn2);
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/entrywsi.c b/ldap/servers/slapd/entrywsi.c
|
|
|
dc8c34 |
index 971e9e3..6c37f45 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/entrywsi.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/entrywsi.c
|
|
|
dc8c34 |
@@ -423,8 +423,8 @@ static int
|
|
|
dc8c34 |
entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
int retVal= LDAP_SUCCESS;
|
|
|
dc8c34 |
- Slapi_Value **valuestoadd = NULL;
|
|
|
dc8c34 |
- valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
|
|
|
dc8c34 |
+ Slapi_Value **valuestoadd = NULL;
|
|
|
dc8c34 |
+ valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
|
|
|
dc8c34 |
if(!valuearray_isempty(valuestoadd))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Slapi_Attr *a= NULL;
|
|
|
dc8c34 |
@@ -437,7 +437,7 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **b
|
|
|
dc8c34 |
slapi_attr_init(a, type);
|
|
|
dc8c34 |
attrlist_add(&e->e_attrs, a);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- a_flags_orig = a->a_flags;
|
|
|
dc8c34 |
+ a_flags_orig = a->a_flags;
|
|
|
dc8c34 |
a->a_flags |= flags;
|
|
|
dc8c34 |
/* Check if the type of the to-be-added values has DN syntax or not. */
|
|
|
dc8c34 |
if (slapi_attr_is_dn_syntax_attr(a)) {
|
|
|
dc8c34 |
@@ -558,8 +558,8 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* delete some specific values */
|
|
|
dc8c34 |
- Slapi_Value **valuestodelete= NULL;
|
|
|
dc8c34 |
- valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
|
|
|
dc8c34 |
+ Slapi_Value **valuestodelete= NULL;
|
|
|
dc8c34 |
+ valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
|
|
|
dc8c34 |
/* Check if the type of the to-be-deleted values has DN syntax
|
|
|
dc8c34 |
* or not. */
|
|
|
dc8c34 |
if (slapi_attr_is_dn_syntax_attr(a)) {
|
|
|
dc8c34 |
@@ -575,8 +575,7 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
|
|
|
dc8c34 |
there are present values with a later CSN - otherwise, even though
|
|
|
dc8c34 |
the value will be updated with a VDCSN which is later than the VUCSN,
|
|
|
dc8c34 |
the attribute will not be deleted */
|
|
|
dc8c34 |
- if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE) && valuesupdated &&
|
|
|
dc8c34 |
- *valuesupdated)
|
|
|
dc8c34 |
+ if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE) && valueset_isempty(&a->a_present_values))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
attr_set_deletion_csn(a,csn);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -626,8 +625,8 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
|
|
|
dc8c34 |
if ( retVal==LDAP_OPERATIONS_ERROR )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
|
|
|
dc8c34 |
- "value for attribute type %s found in "
|
|
|
dc8c34 |
- "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
|
|
|
dc8c34 |
+ "value for attribute type %s found in "
|
|
|
dc8c34 |
+ "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
valuearray_free(&valuestodelete);
|
|
|
dc8c34 |
@@ -683,7 +682,7 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
|
|
|
dc8c34 |
will add it back to the present list in the non urp case,
|
|
|
dc8c34 |
or determine if the attribute needs to be added
|
|
|
dc8c34 |
or not in the urp case
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
entry_add_deleted_attribute_wsi(e, a);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1103,6 +1102,7 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu
|
|
|
dc8c34 |
Slapi_Value *new_value= NULL;
|
|
|
dc8c34 |
const CSN *current_value_vucsn;
|
|
|
dc8c34 |
const CSN *pending_value_vucsn;
|
|
|
dc8c34 |
+ const CSN *pending_value_vdcsn;
|
|
|
dc8c34 |
const CSN *adcsn;
|
|
|
dc8c34 |
int i;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1116,27 +1116,47 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu
|
|
|
dc8c34 |
slapi_attr_next_value(a,i,&new_value);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
attr_first_deleted_value(a,&pending_value);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
/* purge_attribute_state_single_valued */
|
|
|
dc8c34 |
adcsn= attr_get_deletion_csn(a);
|
|
|
dc8c34 |
current_value_vucsn= value_get_csn(current_value, CSN_TYPE_VALUE_UPDATED);
|
|
|
dc8c34 |
pending_value_vucsn= value_get_csn(pending_value, CSN_TYPE_VALUE_UPDATED);
|
|
|
dc8c34 |
- if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
|
|
|
dc8c34 |
- (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
|
|
|
dc8c34 |
+ pending_value_vdcsn= value_get_csn(pending_value, CSN_TYPE_VALUE_DELETED);
|
|
|
dc8c34 |
+ if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
|
|
|
dc8c34 |
+ (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
attr_set_deletion_csn(a,NULL);
|
|
|
dc8c34 |
adcsn= NULL;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if(new_value==NULL)
|
|
|
dc8c34 |
+ /* in the case of the following:
|
|
|
dc8c34 |
+ * add: value2
|
|
|
dc8c34 |
+ * delete: value1
|
|
|
dc8c34 |
+ * we will have current_value with VUCSN CSN1
|
|
|
dc8c34 |
+ * and pending_value with VDCSN CSN2
|
|
|
dc8c34 |
+ * and new_value == NULL
|
|
|
dc8c34 |
+ * current_value != pending_value
|
|
|
dc8c34 |
+ * and
|
|
|
dc8c34 |
+ * VUCSN == VDCSN (ignoring subseq)
|
|
|
dc8c34 |
+ * even though value1.VDCSN > value2.VUCSN
|
|
|
dc8c34 |
+ * value2 should still win because the value is _different_
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if (current_value && pending_value && !new_value && !adcsn &&
|
|
|
dc8c34 |
+ (0 != slapi_value_compare(a, current_value, pending_value)) &&
|
|
|
dc8c34 |
+ (0 == csn_compare_ext(current_value_vucsn, pending_value_vdcsn, CSN_COMPARE_SKIP_SUBSEQ)))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- /* check if the pending value should become the current value */
|
|
|
dc8c34 |
- if(pending_value!=NULL)
|
|
|
dc8c34 |
+ /* just remove the deleted value */
|
|
|
dc8c34 |
+ entry_deleted_value_to_zapped_value(a,pending_value);
|
|
|
dc8c34 |
+ pending_value = NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ else if(new_value==NULL)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ /* check if the pending value should become the current value */
|
|
|
dc8c34 |
+ if(pending_value!=NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
if(!value_distinguished_at_csn(e,a,current_value,pending_value_vucsn))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- /* attribute.current_value = attribute.pending_value; */
|
|
|
dc8c34 |
- /* attribute.pending_value = NULL; */
|
|
|
dc8c34 |
+ /* attribute.current_value = attribute.pending_value; */
|
|
|
dc8c34 |
+ /* attribute.pending_value = NULL; */
|
|
|
dc8c34 |
entry_present_value_to_zapped_value(a,current_value);
|
|
|
dc8c34 |
entry_deleted_value_to_present_value(a,pending_value);
|
|
|
dc8c34 |
current_value= pending_value;
|
|
|
dc8c34 |
@@ -1145,12 +1165,12 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu
|
|
|
dc8c34 |
pending_value_vucsn= NULL;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- /* check if the current value should be deleted */
|
|
|
dc8c34 |
- if(current_value!=NULL)
|
|
|
dc8c34 |
+ /* check if the current value should be deleted */
|
|
|
dc8c34 |
+ if(current_value!=NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
if(csn_compare(adcsn,current_value_vucsn)>0) /* check if the attribute was deleted after the value was last updated */
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- if(!value_distinguished_at_csn(e,a,current_value,current_value_vucsn))
|
|
|
dc8c34 |
+ if(!value_distinguished_at_csn(e,a,current_value,current_value_vucsn))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
entry_present_value_to_zapped_value(a,current_value);
|
|
|
dc8c34 |
current_value= NULL;
|
|
|
dc8c34 |
@@ -1162,17 +1182,17 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu
|
|
|
dc8c34 |
else /* addition of a new value */
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
const CSN *new_value_vucsn= value_get_csn(new_value,CSN_TYPE_VALUE_UPDATED);
|
|
|
dc8c34 |
- if(csn_compare(new_value_vucsn,current_value_vucsn)<0)
|
|
|
dc8c34 |
+ if(csn_compare(new_value_vucsn,current_value_vucsn)<0)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- /*
|
|
|
dc8c34 |
- * if the new value was distinguished at the time the current value was added
|
|
|
dc8c34 |
- * then the new value should become current
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
- if(value_distinguished_at_csn(e,a,new_value,current_value_vucsn))
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * if the new value was distinguished at the time the current value was added
|
|
|
dc8c34 |
+ * then the new value should become current
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if(value_distinguished_at_csn(e,a,new_value,current_value_vucsn))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- /* attribute.pending_value = attribute.current_value */
|
|
|
dc8c34 |
- /* attribute.current_value = new_value */
|
|
|
dc8c34 |
- if(pending_value==NULL)
|
|
|
dc8c34 |
+ /* attribute.pending_value = attribute.current_value */
|
|
|
dc8c34 |
+ /* attribute.current_value = new_value */
|
|
|
dc8c34 |
+ if(pending_value==NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
entry_present_value_to_deleted_value(a,current_value);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1188,63 +1208,63 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- /* new_value= NULL */
|
|
|
dc8c34 |
+ /* new_value= NULL */
|
|
|
dc8c34 |
entry_present_value_to_zapped_value(a, new_value);
|
|
|
dc8c34 |
new_value= NULL;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- else /* new value is after the current value */
|
|
|
dc8c34 |
+ else /* new value is after the current value */
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn))
|
|
|
dc8c34 |
+ if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- /* attribute.current_value = new_value */
|
|
|
dc8c34 |
+ /* attribute.current_value = new_value */
|
|
|
dc8c34 |
entry_present_value_to_zapped_value(a, current_value);
|
|
|
dc8c34 |
current_value= new_value;
|
|
|
dc8c34 |
new_value= NULL;
|
|
|
dc8c34 |
current_value_vucsn= new_value_vucsn;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- else /* value is distinguished - check if we should replace the current pending value */
|
|
|
dc8c34 |
+ else /* value is distinguished - check if we should replace the current pending value */
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- if(csn_compare(new_value_vucsn, pending_value_vucsn)>0)
|
|
|
dc8c34 |
+ if(csn_compare(new_value_vucsn, pending_value_vucsn)>0)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- /* attribute.pending_value = new_value */
|
|
|
dc8c34 |
+ /* attribute.pending_value = new_value */
|
|
|
dc8c34 |
entry_deleted_value_to_zapped_value(a,pending_value);
|
|
|
dc8c34 |
entry_present_value_to_deleted_value(a,new_value);
|
|
|
dc8c34 |
pending_value= new_value;
|
|
|
dc8c34 |
new_value= NULL;
|
|
|
dc8c34 |
pending_value_vucsn= new_value_vucsn;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- /*
|
|
|
dc8c34 |
- * This call ensures that the attribute does not have a pending_value
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * This call ensures that the attribute does not have a pending_value
|
|
|
dc8c34 |
* or a deletion_csn that is earlier than the current_value.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
/* purge_attribute_state_single_valued */
|
|
|
dc8c34 |
- if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
|
|
|
dc8c34 |
- (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
|
|
|
dc8c34 |
+ if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
|
|
|
dc8c34 |
+ (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
attr_set_deletion_csn(a,NULL);
|
|
|
dc8c34 |
adcsn= NULL;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- /* set attribute state */
|
|
|
dc8c34 |
- if(current_value==NULL)
|
|
|
dc8c34 |
+ /* set attribute state */
|
|
|
dc8c34 |
+ if(current_value==NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
if(attribute_state==ATTRIBUTE_PRESENT)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
entry_present_attribute_to_deleted_attribute(e, a);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- else
|
|
|
dc8c34 |
+ else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
if(attribute_state==ATTRIBUTE_DELETED)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
entry_deleted_attribute_to_present_attribute(e, a);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
static void
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
index ddeac62..1efbc8b 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
@@ -196,6 +196,8 @@ PRUint16 csn_get_seqnum(const CSN *csn);
|
|
|
dc8c34 |
PRUint16 csn_get_subseqnum(const CSN *csn);
|
|
|
dc8c34 |
char *csn_as_string(const CSN *csn, PRBool replicaIdOrder, char *ss); /* WARNING: ss must be CSN_STRSIZE bytes, or NULL. */
|
|
|
dc8c34 |
int csn_compare(const CSN *csn1, const CSN *csn2);
|
|
|
dc8c34 |
+int csn_compare_ext(const CSN *csn1, const CSN *csn2, unsigned int flags);
|
|
|
dc8c34 |
+#define CSN_COMPARE_SKIP_SUBSEQ 0x1
|
|
|
dc8c34 |
time_t csn_time_difference(const CSN *csn1, const CSN *csn2);
|
|
|
dc8c34 |
size_t csn_string_size();
|
|
|
dc8c34 |
char *csn_as_attr_option_string(CSNType t,const CSN *csn,char *ss);
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
1.8.1.4
|
|
|
dc8c34 |
|