ldap/schema/01core389.ldif | 3
ldap/servers/plugins/replication/repl5.h | 7
ldap/servers/plugins/replication/repl5_agmt.c | 143 +++++++++++++++++-
ldap/servers/plugins/replication/repl5_agmtlist.c | 32 +++-
ldap/servers/plugins/replication/repl5_tot_protocol.c | 2
ldap/servers/plugins/replication/repl_globals.c | 1
6 files changed, 179 insertions(+), 9 deletions(-)
New commits:
commit 0157534faae43bc95adda09edd7cd3f19dd32e50
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Fri Sep 16 10:01:08 2011 -0700
Bug 739172 - Allow separate fractional attrs for incremental and total protocols
This patch adds the ability to have a separate fractional attribute
list for the incremental and total update replication protocols.
A new nsDS5ReplicatedAttributeListTotal attribute can be added to a
replication agreement to list the attributes to exclude from the
total update protocol. This has the same format as the existing
nsDS5ReplicatedAttributeList attribute. If a separate total update
attribute list is not specified, the nsDS5ReplicatedAttributeList
value will be used for both incremental and total update. To use
a total update attribute list, an incremental list must be specified
as well.
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index 90ca5cb..91bdb44 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -79,6 +79,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.582 NAME
'nsDS5ReplicaCredentials' DESC
attributeTypes: ( 2.16.840.1.113730.3.1.583 NAME 'nsDS5ReplicaBindMethod' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.584 NAME 'nsDS5ReplicaRoot' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.585 NAME 'nsDS5ReplicatedAttributeList'
DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.594 NAME
'nsDS5ReplicatedAttributeListTotal' DESC 'Netscape defined attribute type'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.586 NAME 'nsDS5ReplicaUpdateSchedule'
DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.587 NAME 'nsds50ruv' DESC 'Netscape
defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape
Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2027 NAME 'nsruvReplicaLastModified' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN
'Netscape Directory Server' )
@@ -138,7 +139,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.110 NAME
'nsMappingTree' DESC 'Netscape d
objectClasses: ( 2.16.840.1.113730.3.2.104 NAME 'nsContainer' DESC 'Netscape
defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server'
)
objectClasses: ( 2.16.840.1.113730.3.2.108 NAME 'nsDS5Replica' DESC 'Netscape
defined objectclass' SUP top MUST ( nsDS5ReplicaRoot $ nsDS5ReplicaId ) MAY (cn $
nsDS5ReplicaType $ nsDS5ReplicaBindDN $ nsState $ nsDS5ReplicaName $ nsDS5Flags $
nsDS5Task $ nsDS5ReplicaReferral $ nsDS5ReplicaAutoReferral $ nsds5ReplicaPurgeDelay $
nsds5ReplicaTombstonePurgeInterval $ nsds5ReplicaChangeCount $ nsds5ReplicaLegacyConsumer)
X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.113 NAME 'nsTombstone' DESC 'Netscape
defined objectclass' SUP top MAY ( nsParentUniqueId $ nscpEntryDN ) X-ORIGIN
'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC
'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $
nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $
nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $
nsDS5ReplicatedAttributeList $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $
description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $
nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $
nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress
$ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $
nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime )
X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC
'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $
nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $
nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $
nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $
nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $
nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $
nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $
nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $
nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $
nsds5replicaSessionPauseTime ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.39 NAME 'nsslapdConfig' DESC 'Netscape
defined objectclass' SUP top MAY ( cn ) X-ORIGIN 'Netscape Directory Server'
)
objectClasses: ( 2.16.840.1.113730.3.2.317 NAME 'nsSaslMapping' DESC
'Netscape defined objectclass' SUP top MUST ( cn $ nsSaslMapRegexString $
nsSaslMapBaseDNTemplate $ nsSaslMapFilterTemplate ) X-ORIGIN 'Netscape Directory
Server' )
objectClasses: ( 2.16.840.1.113730.3.2.43 NAME 'nsSNMP' DESC 'Netscape
defined objectclass' SUP top MUST ( cn $ nsSNMPEnabled ) MAY ( nsSNMPOrganization $
nsSNMPLocation $ nsSNMPContact $ nsSNMPDescription $ nsSNMPName $ nsSNMPMasterHost $
nsSNMPMasterPort ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/plugins/replication/repl5.h
b/ldap/servers/plugins/replication/repl5.h
index 79abb7a..79465e4 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -143,6 +143,7 @@ extern const char *type_nsds5ReplicaCredentials;
extern const char *type_nsds5ReplicaBindMethod;
extern const char *type_nsds5ReplicaRoot;
extern const char *type_nsds5ReplicatedAttributeList;
+extern const char *type_nsds5ReplicatedAttributeListTotal;
extern const char *type_nsds5ReplicaUpdateSchedule;
extern const char *type_nsds5ReplicaInitialize;
extern const char *type_nsds5ReplicaTimeout;
@@ -298,6 +299,7 @@ int agmt_get_bindmethod(const Repl_Agmt *ra);
Slapi_DN *agmt_get_replarea(const Repl_Agmt *ra);
int agmt_is_fractional(const Repl_Agmt *ra);
int agmt_is_fractional_attr(const Repl_Agmt *ra, const char *attrname);
+int agmt_is_fractional_attr_total(const Repl_Agmt *ra, const char *attrname);
int agmt_is_50_mm_protocol(const Repl_Agmt *ra);
int agmt_matches_name(const Repl_Agmt *ra, const Slapi_DN *name);
int agmt_replarea_matches(const Repl_Agmt *ra, const Slapi_DN *name);
@@ -332,9 +334,12 @@ void agmt_set_last_init_status (Repl_Agmt *ra, int ldaprc, int
replrc, const cha
void agmt_inc_last_update_changecount (Repl_Agmt *ra, ReplicaId rid, int skipped);
void agmt_get_changecount_string (Repl_Agmt *ra, char *buf, int bufsize);
int agmt_set_replicated_attributes_from_entry(Repl_Agmt *ra, const Slapi_Entry *e);
+int agmt_set_replicated_attributes_total_from_entry(Repl_Agmt *ra, const Slapi_Entry
*e);
int agmt_set_replicated_attributes_from_attr(Repl_Agmt *ra, Slapi_Attr *sattr);
+int agmt_set_replicated_attributes_total_from_attr(Repl_Agmt *ra, Slapi_Attr *sattr);
char **agmt_get_fractional_attrs(const Repl_Agmt *ra);
-char **agmt_validate_replicated_attributes(Repl_Agmt *ra);
+char **agmt_get_fractional_attrs_total(const Repl_Agmt *ra);
+char **agmt_validate_replicated_attributes(Repl_Agmt *ra, int total);
void* agmt_get_priv (const Repl_Agmt *agmt);
void agmt_set_priv (Repl_Agmt *agmt, void* priv);
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c
b/ldap/servers/plugins/replication/repl5_agmt.c
index b5e66ee..61aa9ba 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -104,6 +104,7 @@ typedef struct repl5agmt {
int bindmethod; /* Bind method - simple, SSL */
Slapi_DN *replarea; /* DN of replicated area */
char **frac_attrs; /* list of fractional attributes to be replicated */
+ char **frac_attrs_total; /* list of fractional attributes to be replicated for total
update protocol */
Schedule *schedule; /* Scheduling information */
int auto_initialize; /* 1 = automatically re-initialize replica */
const Slapi_DN *dn; /* DN of replication agreement entry */
@@ -159,7 +160,8 @@ nsds5ReplicaBindDN
nsds5ReplicaCredentials
nsds5ReplicaBindMethod - "SIMPLE" or "SSLCLIENTAUTH".
nsds5ReplicaRoot - Replicated suffix
-nsds5ReplicatedAttributeList - Unused so far (meant for fractional repl).
+nsds5ReplicatedAttributeList - Fractional attrs for incremental update protocol (and
total if not separately defined)
+nsds5ReplicatedAttributeListTotal - Fractional attrs for total update protocol
nsds5ReplicaUpdateSchedule
nsds5ReplicaTimeout - Outbound repl operations timeout
nsds50ruv - consumer's RUV
@@ -402,7 +404,7 @@ agmt_new_from_entry(Slapi_Entry *e)
agmt_get_long_name(ra));
}
/* Check that there are no verboten attributes in the exclude list */
- denied_attrs = agmt_validate_replicated_attributes(ra);
+ denied_attrs = agmt_validate_replicated_attributes(ra, 0 /* incremental */);
if (denied_attrs)
{
/* Report the error to the client */
@@ -414,6 +416,28 @@ agmt_new_from_entry(Slapi_Entry *e)
goto loser;
}
+ /* Total update fractional attributes */
+ slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeListTotal, &sattr);
+ if (sattr && agmt_set_replicated_attributes_total_from_attr(ra, sattr) != 0)
+ {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "agmtlist_add_callback: failed to parse total "
+ "update replicated attributes for agreement %s\n",
+ agmt_get_long_name(ra));
+ }
+ /* Check that there are no verboten attributes in the exclude list */
+ denied_attrs = agmt_validate_replicated_attributes(ra, 1 /* total */);
+ if (denied_attrs)
+ {
+ /* Report the error to the client */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "WARNING: Attempt to exclude illegal attributes "
+ "from a fractional agreement for total update protocol\n");
+ /* Free the list */
+ slapi_ch_array_free(denied_attrs);
+ goto loser;
+ }
+
if (!agmt_is_valid(ra))
{
goto loser;
@@ -440,7 +464,6 @@ loser:
}
-
Repl_Agmt *
agmt_new_from_pblock(Slapi_PBlock *pb)
{
@@ -492,6 +515,7 @@ agmt_delete(void **rap)
slapi_ch_free((void **)&(ra->binddn));
slapi_ch_array_free(ra->frac_attrs);
+ slapi_ch_array_free(ra->frac_attrs_total);
if (NULL != ra->creds)
{
@@ -790,6 +814,23 @@ agmt_get_fractional_attrs(const Repl_Agmt *ra)
PR_Unlock(ra->lock);
return return_value;
}
+
+/* Returns a COPY of the attr list, remember to free it */
+char **
+agmt_get_fractional_attrs_total(const Repl_Agmt *ra)
+{
+ char ** return_value = NULL;
+ PR_ASSERT(NULL != ra);
+ if (NULL == ra->frac_attrs_total)
+ {
+ return agmt_get_fractional_attrs(ra);
+ }
+ PR_Lock(ra->lock);
+ return_value = charray_dup(ra->frac_attrs_total);
+ PR_Unlock(ra->lock);
+ return return_value;
+}
+
int
agmt_is_fractional_attr(const Repl_Agmt *ra, const char *attrname)
{
@@ -806,6 +847,21 @@ agmt_is_fractional_attr(const Repl_Agmt *ra, const char *attrname)
return return_value;
}
+int agmt_is_fractional_attr_total(const Repl_Agmt *ra, const char *attrname)
+{
+ int return_value;
+ PR_ASSERT(NULL != ra);
+ if (NULL == ra->frac_attrs_total)
+ {
+ return agmt_is_fractional_attr(ra, attrname);
+ }
+ PR_Lock(ra->lock);
+ /* Scan the list looking for a match */
+ return_value = charray_inlist(ra->frac_attrs_total,(char*)attrname);
+ PR_Unlock(ra->lock);
+ return return_value;
+}
+
int
agmt_get_auto_initialize(const Repl_Agmt *ra)
{
@@ -1258,6 +1314,40 @@ agmt_set_replicated_attributes_from_entry(Repl_Agmt *ra, const
Slapi_Entry *e)
}
/*
+ * Set or reset the set of total update replicated attributes.
+ *
+ * Returns 0 if DN set, or -1 if an error occurred.
+ */
+int
+agmt_set_replicated_attributes_total_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
+{
+ Slapi_Attr *sattr = NULL;
+ int return_value = 0;
+
+ PR_ASSERT(NULL != ra);
+ slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeListTotal, &sattr);
+ PR_Lock(ra->lock);
+ if (ra->frac_attrs_total)
+ {
+ slapi_ch_array_free(ra->frac_attrs_total);
+ ra->frac_attrs_total = NULL;
+ }
+ if (NULL != sattr)
+ {
+ Slapi_Value *sval = NULL;
+ slapi_attr_first_value(sattr, &sval);
+ if (NULL != sval)
+ {
+ const char *val = slapi_value_get_string(sval);
+ return_value =
agmt_parse_excluded_attrs_config_attr(val,&(ra->frac_attrs_total));
+ }
+ }
+ PR_Unlock(ra->lock);
+ prot_notify_agmt_changed(ra->protocol, ra->long_name);
+ return return_value;
+}
+
+/*
* Set or reset the set of replicated attributes.
*
* Returns 0 if DN set, or -1 if an error occurred.
@@ -1289,8 +1379,39 @@ agmt_set_replicated_attributes_from_attr(Repl_Agmt *ra, Slapi_Attr
*sattr)
return return_value;
}
+/*
+ * Set or reset the set of total update replicated attributes.
+ *
+ * Returns 0 if DN set, or -1 if an error occurred.
+ */
+int
+agmt_set_replicated_attributes_total_from_attr(Repl_Agmt *ra, Slapi_Attr *sattr)
+{
+ int return_value = 0;
+
+ PR_ASSERT(NULL != ra);
+ PR_Lock(ra->lock);
+ if (ra->frac_attrs_total)
+ {
+ slapi_ch_array_free(ra->frac_attrs_total);
+ ra->frac_attrs_total = NULL;
+ }
+ if (NULL != sattr)
+ {
+ Slapi_Value *sval = NULL;
+ slapi_attr_first_value(sattr, &sval);
+ if (NULL != sval)
+ {
+ const char *val = slapi_value_get_string(sval);
+ return_value =
agmt_parse_excluded_attrs_config_attr(val,&(ra->frac_attrs_total));
+ }
+ }
+ PR_Unlock(ra->lock);
+ return return_value;
+}
+
char **
-agmt_validate_replicated_attributes(Repl_Agmt *ra)
+agmt_validate_replicated_attributes(Repl_Agmt *ra, int total)
{
static char* verbotten_attrs[] = {
@@ -1302,7 +1423,19 @@ agmt_validate_replicated_attributes(Repl_Agmt *ra)
};
char **retval = NULL;
- char **frac_attrs = ra->frac_attrs;
+ char **frac_attrs = NULL;
+
+ /* If checking for total update, use the total attr list
+ * if it exists. If oen is not set, use the incremental
+ * attr list. */
+ if (total && ra->frac_attrs_total)
+ {
+ frac_attrs = ra->frac_attrs_total;
+ }
+ else
+ {
+ frac_attrs = ra->frac_attrs;
+ }
/* Iterate over the frac attrs */
if (frac_attrs)
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c
b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 34da6d0..8cc2cc3 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -425,7 +425,7 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore,
Slapi_Entry
rc = SLAPI_DSE_CALLBACK_ERROR;
}
/* Check that there are no verboten attributes in the exclude list */
- denied_attrs = agmt_validate_replicated_attributes(agmt);
+ denied_attrs = agmt_validate_replicated_attributes(agmt, 0 /* incremental */);
if (denied_attrs)
{
/* Report the error to the client */
@@ -441,6 +441,36 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore,
Slapi_Entry
}
}
else if (slapi_attr_types_equivalent(mods[i]->mod_type,
+ type_nsds5ReplicatedAttributeListTotal))
+ {
+ char **denied_attrs = NULL;
+ /* New set of excluded attributes */
+ if (agmt_set_replicated_attributes_total_from_entry(agmt, e) != 0)
+ {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback:
"
+ "failed to update total update replicated attributes for agreement
%s\n",
+ agmt_get_long_name(agmt));
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rc = SLAPI_DSE_CALLBACK_ERROR;
+ }
+ /* Check that there are no verboten attributes in the exclude list */
+ denied_attrs = agmt_validate_replicated_attributes(agmt, 1 /* total */);
+ if (denied_attrs)
+ {
+ /* Report the error to the client */
+ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "attempt to exclude an
illegal total update "
+ "attribute in a fractional agreement");
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback:
"
+ "attempt to exclude an illegal total update attribute in a fractional
agreement\n");
+
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ rc = SLAPI_DSE_CALLBACK_ERROR;
+ /* Free the deny list if we got one */
+ slapi_ch_array_free(denied_attrs);
+ break;
+ }
+ }
+ else if (slapi_attr_types_equivalent(mods[i]->mod_type,
"nsds5debugreplicatimeout"))
{
char *val = slapi_entry_attr_get_charptr(e, "nsds5debugreplicatimeout");
diff --git a/ldap/servers/plugins/replication/repl5_tot_protocol.c
b/ldap/servers/plugins/replication/repl5_tot_protocol.c
index ca151bf..5eeef5d 100644
--- a/ldap/servers/plugins/replication/repl5_tot_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_tot_protocol.c
@@ -673,7 +673,7 @@ int send_entry (Slapi_Entry *e, void *cb_data)
if (agmt_is_fractional(prp->agmt))
{
- frac_excluded_attrs = agmt_get_fractional_attrs(prp->agmt);
+ frac_excluded_attrs = agmt_get_fractional_attrs_total(prp->agmt);
}
/* convert the entry to the on the wire format */
diff --git a/ldap/servers/plugins/replication/repl_globals.c
b/ldap/servers/plugins/replication/repl_globals.c
index f409be6..f0aea12 100644
--- a/ldap/servers/plugins/replication/repl_globals.c
+++ b/ldap/servers/plugins/replication/repl_globals.c
@@ -120,6 +120,7 @@ const char *type_nsds5ReplicaCredentials =
"nsds5ReplicaCredentials";
const char *type_nsds5ReplicaBindMethod = "nsds5ReplicaBindMethod";
const char *type_nsds5ReplicaRoot = "nsds5ReplicaRoot";
const char *type_nsds5ReplicatedAttributeList =
"nsds5ReplicatedAttributeList";
+const char *type_nsds5ReplicatedAttributeListTotal =
"nsds5ReplicatedAttributeListTotal";
const char *type_nsds5ReplicaUpdateSchedule = "nsds5ReplicaUpdateSchedule";
const char *type_nsds5ReplicaInitialize = "nsds5BeginReplicaRefresh";
const char *type_nsds5ReplicaTimeout = "nsds5ReplicaTimeout";