From eff0d28a00c8b5088c365b9b40303be14784eff2 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Fri, 10 Jun 2011 10:25:31 +0000
Subject: [PATCH] Partial fix for OPENDJ-194: Minor improvements to change log content and configuration
---
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java | 75 ++++
opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java | 11
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java | 183 +++++++-----
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java | 19
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java | 17
opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java | 1
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java | 16
opendj-sdk/opends/src/admin/messages/ExternalChangelogDomainCfgDefn.properties | 6
opendj-sdk/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java | 8
opendj-sdk/opends/src/server/org/opends/server/replication/server/DataServerHandler.java | 4
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ExternalChangelogDomainConfiguration.xml | 41 ++
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java | 7
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ExternalChangelogDomainFakeCfg.java | 41 +-
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java | 59 ++-
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java | 10
opendj-sdk/opends/src/server/org/opends/server/replication/common/DSInfo.java | 74 +++-
opendj-sdk/opends/src/server/org/opends/server/types/Entry.java | 50 ---
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java | 32 +
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ExternalChangelogDomain.java | 32 -
opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java | 203 +++++++++----
opendj-sdk/opends/resource/schema/02-config.ldif | 6
21 files changed, 544 insertions(+), 351 deletions(-)
diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 13f4a63..d934216 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/opends/resource/schema/02-config.ldif
@@ -2446,6 +2446,10 @@
NAME 'ds-cfg-ecl-include'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.7
+ NAME 'ds-cfg-ecl-include-for-deletes'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.603
NAME 'ds-cfg-weight'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
@@ -4262,7 +4266,7 @@
STRUCTURAL
MUST ( cn $
ds-cfg-enabled )
- MAY ( ds-cfg-ecl-include )
+ MAY ( ds-cfg-ecl-include $ ds-cfg-ecl-include-for-deletes )
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.235
NAME 'ds-cfg-collective-attribute-subentries-virtual-attribute'
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ExternalChangelogDomainConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ExternalChangelogDomainConfiguration.xml
index deac4c2..3738977 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ExternalChangelogDomainConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ExternalChangelogDomainConfiguration.xml
@@ -24,6 +24,7 @@
!
!
! Copyright 2009 Sun Microsystems, Inc.
+ ! Portions copyright 2011 ForgeRock AS
! -->
<adm:managed-object name="external-changelog-domain"
plural-name="external-changelog-domains"
@@ -59,17 +60,25 @@
</adm:property>
<adm:property name="ecl-include" multi-valued="true" mandatory="false">
<adm:synopsis>
- Allows to include some target entry attributes in the external changelog.
+ Specifies a list of attributes which should be published with every
+ change log entry, regardless of whether or not the attribute itself
+ has changed.
</adm:synopsis>
<adm:description>
- Specifies an attribute that will be included in every External Change Log
- entry related to this replication domain.
+ The list of attributes may include wild cards such as "*" and "+" as
+ well as object class references prefixed with an ampersand, for
+ example "@person".
+ The included attributes will be published using the "includedAttributes"
+ operational attribute as a single LDIF value rather like the
+ "changes" attribute. For modify and modifyDN operations the included
+ attributes will be taken from the entry before any changes were applied.
</adm:description>
<adm:default-behavior>
<adm:undefined/>
</adm:default-behavior>
<adm:syntax>
- <adm:attribute-type />
+ <!-- FIXME: can we constrain this with a regex? -->
+ <adm:string />
</adm:syntax>
<adm:profile name="ldap">
<ldap:attribute>
@@ -77,4 +86,28 @@
</ldap:attribute>
</adm:profile>
</adm:property>
+ <adm:property name="ecl-include-for-deletes" multi-valued="true" mandatory="false">
+ <adm:synopsis>
+ Specifies a list of attributes which should be published with every
+ delete operation change log entry, in addition to those specified by the
+ "ecl-include" property.
+ </adm:synopsis>
+ <adm:description>
+ This property provides a means for applications to archive entries after
+ they have been deleted. See the description of the "ecl-include" property
+ for further information about how the included attributes are published.
+ </adm:description>
+ <adm:default-behavior>
+ <adm:undefined/>
+ </adm:default-behavior>
+ <adm:syntax>
+ <!-- FIXME: can we constrain this with a regex? -->
+ <adm:string />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:name>ds-cfg-ecl-include-for-deletes</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
</adm:managed-object>
diff --git a/opendj-sdk/opends/src/admin/messages/ExternalChangelogDomainCfgDefn.properties b/opendj-sdk/opends/src/admin/messages/ExternalChangelogDomainCfgDefn.properties
index 9352278..bcacf73 100644
--- a/opendj-sdk/opends/src/admin/messages/ExternalChangelogDomainCfgDefn.properties
+++ b/opendj-sdk/opends/src/admin/messages/ExternalChangelogDomainCfgDefn.properties
@@ -1,6 +1,8 @@
user-friendly-name=External Changelog Domain
user-friendly-plural-name=External Changelog Domains
synopsis=The External Changelog Domain provides configuration of the external changelog for the replication domain.
-property.ecl-include.synopsis=Allows to include some target entry attributes in the external changelog.
-property.ecl-include.description=Specifies an attribute that will be included in every External Change Log entry related to this replication domain.
+property.ecl-include.synopsis=Specifies a list of attributes which should be published with every change log entry, regardless of whether or not the attribute itself has changed.
+property.ecl-include.description=The list of attributes may include wild cards such as "*" and "+" as well as object class references prefixed with an ampersand, for example "@person". The included attributes will be published using the "includedAttributes" operational attribute as a single LDIF value rather like the "changes" attribute. For modify and modifyDN operations the included attributes will be taken from the entry before any changes were applied.
+property.ecl-include-for-deletes.synopsis=Specifies a list of attributes which should be published with every delete operation change log entry, in addition to those specified by the "ecl-include" property.
+property.ecl-include-for-deletes.description=This property provides a means for applications to archive entries after they have been deleted. See the description of the "ecl-include" property for further information about how the included attributes are published.
property.enabled.synopsis=Indicates whether the External Changelog Domain is enabled.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/common/DSInfo.java b/opendj-sdk/opends/src/server/org/opends/server/replication/common/DSInfo.java
index 636eb8b..ebbdf86 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/common/DSInfo.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/common/DSInfo.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.common;
@@ -63,27 +64,44 @@
private Set<String> eclIncludes = new HashSet<String>();
+ private Set<String> eclIncludesForDeletes = new HashSet<String>();
+
+
+
/**
* Creates a new instance of DSInfo with every given info.
*
- * @param dsId The DS id
- * @param rsId The RS id the DS is connected to
- * @param generationId The generation id the DS is using
- * @param status The DS status
- * @param assuredFlag DS assured replication enabled or not
- * @param assuredMode DS assured mode
- * @param safeDataLevel DS safe data level
- * @param groupId DS group id
- * @param refUrls DS exported referrals URLs
- * @param eclIncludes The list of entry attributes to include in the ECL.
- * @param protocolVersion Protocol version supported by this server.
+ * @param dsId
+ * The DS id
+ * @param rsId
+ * The RS id the DS is connected to
+ * @param generationId
+ * The generation id the DS is using
+ * @param status
+ * The DS status
+ * @param assuredFlag
+ * DS assured replication enabled or not
+ * @param assuredMode
+ * DS assured mode
+ * @param safeDataLevel
+ * DS safe data level
+ * @param groupId
+ * DS group id
+ * @param refUrls
+ * DS exported referrals URLs
+ * @param eclIncludes
+ * The list of entry attributes to include in the ECL.
+ * @param eclIncludesForDeletes
+ * The list of entry attributes to include in the ECL for deletes.
+ * @param protocolVersion
+ * Protocol version supported by this server.
*/
- public DSInfo(int dsId, int rsId, long generationId, ServerStatus status,
- boolean assuredFlag, AssuredMode assuredMode, byte safeDataLevel,
- byte groupId, List<String> refUrls, Set<String> eclIncludes,
- short protocolVersion)
+ public DSInfo(int dsId, int rsId, long generationId,
+ ServerStatus status, boolean assuredFlag,
+ AssuredMode assuredMode, byte safeDataLevel, byte groupId,
+ List<String> refUrls, Set<String> eclIncludes,
+ Set<String> eclIncludesForDeletes, short protocolVersion)
{
-
this.dsId = dsId;
this.rsId = rsId;
this.generationId = generationId;
@@ -94,6 +112,7 @@
this.groupId = groupId;
this.refUrls = refUrls;
this.eclIncludes = eclIncludes;
+ this.eclIncludesForDeletes = eclIncludesForDeletes;
this.protocolVersion = protocolVersion;
}
@@ -188,6 +207,15 @@
}
/**
+ * Get the entry attributes to be included in the ECL for delete operations.
+ * @return The entry attributes to be included in the ECL.
+ */
+ public Set<String> getEclIncludesForDeletes()
+ {
+ return eclIncludesForDeletes;
+ }
+
+ /**
* Get the protocol version supported by this server.
* Returns -1 when the protocol version is not known (too old version).
* @return The protocol version.
@@ -222,9 +250,13 @@
(groupId == dsInfo.getGroupId()) &&
(protocolVersion == dsInfo.getProtocolVersion()) &&
(refUrls.equals(dsInfo.getRefUrls())) &&
- (((eclIncludes == null) && (dsInfo.getEclIncludes() == null)) ||
- ((eclIncludes != null) &&
- (eclIncludes.equals(dsInfo.getEclIncludes())))));
+ (((eclIncludes == null) && (dsInfo.getEclIncludes() == null)) ||
+ ((eclIncludes != null) &&
+ (eclIncludes.equals(dsInfo.getEclIncludes())))) &&
+ (((eclIncludesForDeletes == null)
+ && (dsInfo.getEclIncludesForDeletes() == null)) ||
+ ((eclIncludesForDeletes != null) &&
+ (eclIncludesForDeletes.equals(dsInfo.getEclIncludesForDeletes())))));
} else
{
return false;
@@ -249,6 +281,8 @@
hash = 73 * hash + this.safeDataLevel;
hash = 73 * hash + (this.refUrls != null ? this.refUrls.hashCode() : 0);
hash = 73 * hash + (this.eclIncludes != null ? eclIncludes.hashCode() : 0);
+ hash = 73 * hash + (this.eclIncludesForDeletes != null ?
+ eclIncludesForDeletes.hashCode() : 0);
hash = 73 * hash + this.groupId;
hash = 73 * hash + this.protocolVersion;
return hash;
@@ -284,6 +318,8 @@
sb.append(refUrls);
sb.append(" ; ECL Include: ");
sb.append(eclIncludes);
+ sb.append(" ; ECL Include for Deletes: ");
+ sb.append(eclIncludesForDeletes);
return sb.toString();
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ExternalChangelogDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ExternalChangelogDomain.java
index b8a0d94..46db8f4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ExternalChangelogDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ExternalChangelogDomain.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.plugin;
@@ -33,11 +34,9 @@
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ConfigurationDeleteListener;
import org.opends.server.admin.std.server.ExternalChangelogDomainCfg;
-import org.opends.server.types.AttributeType;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.ResultCode;
-import java.util.HashSet;
/**
* This class specifies the external changelog feature for a replication
@@ -49,8 +48,8 @@
ConfigurationChangeListener<ExternalChangelogDomainCfg>
{
- LDAPReplicationDomain domain;
- boolean isEnabled;
+ private LDAPReplicationDomain domain;
+ private boolean isEnabled;
/**
* Constructor from a provided LDAPReplicationDomain.
@@ -60,16 +59,12 @@
public ExternalChangelogDomain(LDAPReplicationDomain domain,
ExternalChangelogDomainCfg configuration)
{
- this.domain =domain;
+ this.domain = domain;
this.isEnabled = configuration.isEnabled();
configuration.addChangeListener(this);
- if (configuration.getECLInclude() != null)
- {
- HashSet<String> attrNames = new HashSet<String>(0);
- for (AttributeType eclIncludeAttribute : configuration.getECLInclude())
- attrNames.add(eclIncludeAttribute.getNormalizedPrimaryName());
- domain.setEclInclude(domain.getServerId(), attrNames);
- }
+ domain.setEclIncludes(domain.getServerId(),
+ configuration.getECLInclude(),
+ configuration.getECLIncludeForDeletes());
}
@@ -95,10 +90,9 @@
}
this.isEnabled = configuration.isEnabled();
- HashSet<String> attrNames = new HashSet<String>(0);
- for (AttributeType eclInclude : configuration.getECLInclude())
- attrNames.add(eclInclude.getNormalizedPrimaryName());
- domain.setEclInclude(domain.getServerId(), attrNames);
+ domain.setEclIncludes(domain.getServerId(),
+ configuration.getECLInclude(),
+ configuration.getECLIncludeForDeletes());
return new ConfigChangeResult(ResultCode.SUCCESS, false);
}
@@ -126,10 +120,8 @@
}
this.isEnabled = configuration.isEnabled();
- HashSet<String> attrNames = new HashSet<String>(0);
- for (AttributeType eclInclude : configuration.getECLInclude())
- attrNames.add(eclInclude.getNormalizedPrimaryName());
- domain.changeConfig(attrNames);
+ domain.changeConfig(configuration.getECLInclude(),
+ configuration.getECLIncludeForDeletes());
return new ConfigChangeResult(ResultCode.SUCCESS, false);
}
catch (Exception e)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
index f6b68bc..0b72925 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -39,27 +39,14 @@
import static org.opends.server.util.StaticUtils.createEntry;
import static org.opends.server.util.StaticUtils.getFileForPath;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+import static org.opends.server.util.StaticUtils.toLowerCase;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.StringTokenizer;
-import java.util.TreeMap;
+import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -5104,91 +5091,133 @@
* @param op
* @throws DirectoryException
*/
- private void addEntryAttributesForCL(UpdateMsg msg,PostOperationOperation op)
- throws DirectoryException
+ private void addEntryAttributesForCL(UpdateMsg msg,
+ PostOperationOperation op) throws DirectoryException
{
- String[] entryAttributeNames =
- getEclInclude().toArray(new String[0]);
- ArrayList<Attribute> newattrs = new ArrayList<Attribute>();
-
if (op instanceof PostOperationDeleteOperation)
{
- Entry entry = null;
- PostOperationDeleteOperation delOp = (PostOperationDeleteOperation)op;
- entry = delOp.getEntryToDelete();
- for (String name : entryAttributeNames)
- {
- AttributeType atype = DirectoryServer.getAttributeType(name);
- List<Attribute> attrs = entry.getAttribute(atype);
- if (attrs != null)
- for (Attribute a : attrs)
- newattrs.add(a);
- }
- ((DeleteMsg)msg).setEclIncludes(newattrs);
+ Set<String> names = getEclIncludesForDeletes();
+ PostOperationDeleteOperation delOp = (PostOperationDeleteOperation) op;
+ Entry entry = delOp.getEntryToDelete();
+ ((DeleteMsg) msg).setEclIncludes(getIncludedAttributes(entry, names));
// For delete only, add the Authorized DN since it's required in the
// ECL entry but is not part of rest of the message.
DN deleterDN = delOp.getAuthorizationDN();
if (deleterDN != null)
{
- ((DeleteMsg)msg).setInitiatorsName(deleterDN.toString());
+ ((DeleteMsg) msg).setInitiatorsName(deleterDN.toString());
}
-
}
else if (op instanceof PostOperationModifyOperation)
{
- Entry entry = null;
- PostOperationModifyOperation modOp = (PostOperationModifyOperation)op;
- entry = modOp.getCurrentEntry();
- for (String name : entryAttributeNames)
- {
- AttributeType atype = DirectoryServer.getAttributeType(name);
- List<Attribute> attrs = entry.getAttribute(atype);
- if (attrs != null)
- for (Attribute a : attrs)
- newattrs.add(a);
- }
- ((ModifyMsg)msg).setEclIncludes(newattrs);
+ Set<String> names = getEclIncludes();
+ PostOperationModifyOperation modOp = (PostOperationModifyOperation) op;
+ Entry entry = modOp.getCurrentEntry();
+ ((ModifyMsg) msg).setEclIncludes(getIncludedAttributes(entry, names));
}
else if (op instanceof PostOperationModifyDNOperation)
{
- Entry entry = null;
+ Set<String> names = getEclIncludes();
PostOperationModifyDNOperation modDNOp =
- (PostOperationModifyDNOperation)op;
- entry = modDNOp.getOriginalEntry();
- for (String name : entryAttributeNames)
- {
- AttributeType atype = DirectoryServer.getAttributeType(name);
- List<Attribute> attrs = entry.getAttribute(atype);
- if (attrs != null)
- for (Attribute a : attrs)
- newattrs.add(a);
- }
- ((ModifyDNMsg)msg).setEclIncludes(newattrs);
+ (PostOperationModifyDNOperation) op;
+ Entry entry = modDNOp.getOriginalEntry();
+ ((ModifyDNMsg) msg).setEclIncludes(getIncludedAttributes(entry, names));
}
else if (op instanceof PostOperationAddOperation)
{
- Entry entry = null;
- PostOperationAddOperation addOp = (PostOperationAddOperation)op;
- entry = addOp.getEntryToAdd();
- for (String name : entryAttributeNames)
- {
- AttributeType atype = DirectoryServer.getAttributeType(name);
- List<Attribute> attrs = entry.getAttribute(atype);
- if (attrs != null)
- {
- for (Attribute a : attrs)
- newattrs.add(a);
- }
- else
- {
- // FIXME:ECL
- }
- }
- ((AddMsg)msg).setEclIncludes(newattrs);
+ Set<String> names = getEclIncludes();
+ PostOperationAddOperation addOp = (PostOperationAddOperation) op;
+ Entry entry = addOp.getEntryToAdd();
+ ((AddMsg) msg).setEclIncludes(getIncludedAttributes(entry, names));
}
}
+
+
+ private Collection<Attribute> getIncludedAttributes(Entry entry,
+ Set<String> names)
+ {
+ if (names.isEmpty())
+ {
+ // Fast-path.
+ return Collections.emptySet();
+ }
+ else if (names.size() == 1 && names.contains("*"))
+ {
+ // Potential fast-path for delete operations.
+ LinkedList<Attribute> attributes = new LinkedList<Attribute>();
+ for (List<Attribute> alist : entry.getUserAttributes().values())
+ {
+ attributes.addAll(alist);
+ }
+ Attribute ocattr = entry.getObjectClassAttribute();
+ if (ocattr != null)
+ {
+ attributes.add(ocattr);
+ }
+ return attributes;
+ }
+ else
+ {
+ // Expand @objectclass references in attribute list if needed. We
+ // do this now in order to take into account dynamic schema changes.
+
+ // Only rebuild the attribute set if necessary.
+ boolean needsExpanding = false;
+ for (String name : names)
+ {
+ if (name.startsWith("@"))
+ {
+ needsExpanding = true;
+ break;
+ }
+ }
+
+ Set<String> expandedNames;
+ if (needsExpanding)
+ {
+ expandedNames = new HashSet<String>(names.size());
+ for (String name : names)
+ {
+ if (name.startsWith("@"))
+ {
+ String ocName = name.substring(1);
+ ObjectClass objectClass = DirectoryServer
+ .getObjectClass(toLowerCase(ocName));
+ if (objectClass != null)
+ {
+ for (AttributeType at : objectClass
+ .getRequiredAttributeChain())
+ {
+ expandedNames.add(at.getNameOrOID());
+ }
+ for (AttributeType at : objectClass
+ .getOptionalAttributeChain())
+ {
+ expandedNames.add(at.getNameOrOID());
+ }
+ }
+ }
+ else
+ {
+ expandedNames.add(name);
+ }
+ }
+ }
+ else
+ {
+ expandedNames = names;
+ }
+
+ Entry filteredEntry = entry.filterEntry(expandedNames, false,
+ false, false);
+ return filteredEntry.getAttributes();
+ }
+ }
+
+
+
/**
* Gets the fractional configuration of this domain.
* @return The fractional configuration of this domain.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java
index 00feb7c..b6e75c3 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java
@@ -23,12 +23,13 @@
*
*
* Copyright 2006-2009 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.protocol;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
import java.util.zip.DataFormatException;
import org.opends.server.protocols.asn1.ASN1;
@@ -424,7 +425,7 @@
/**
* Encode a list of attributes.
*/
- static private byte[] encodeAttributes(List<Attribute> attributes)
+ static private byte[] encodeAttributes(Collection<Attribute> attributes)
{
if (attributes==null)
return new byte[0];
@@ -606,7 +607,7 @@
* Set a provided list of entry attributes.
* @param entryAttrs The provided list of entry attributes.
*/
- public void setEclIncludes(List<Attribute> entryAttrs)
+ public void setEclIncludes(Collection<Attribute> entryAttrs)
{
this.encodedEclIncludes = encodeAttributes(entryAttrs);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java
index 3f22529..39aa36e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008-2009 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.protocol;
@@ -73,6 +74,8 @@
private Set<String> eclIncludes = new HashSet<String>();
+ private Set<String> eclIncludesForDeletes = new HashSet<String>();
+
/**
* The protocolVersion that should be used when serializing this message.
*/
@@ -95,7 +98,7 @@
}
else
{
- decode_V4(in);
+ decode_V4(in, version);
}
}
@@ -188,7 +191,7 @@
}
else
{
- return getBytes_V4();
+ return getBytes_V4(protocolVersion);
}
}
@@ -205,11 +208,11 @@
}
else
{
- return getBytes_V4();
+ return getBytes_V4(reqProtocolVersion);
}
}
- private byte[] getBytes_V4()
+ private byte[] getBytes_V4(short version)
{
try
{
@@ -229,14 +232,23 @@
writer.writeStartSequence();
for (String attrDef : eclIncludes)
+ {
writer.writeOctetString(attrDef);
+ }
+ writer.writeEndSequence();
+
+ writer.writeStartSequence();
+ for (String attrDef : eclIncludesForDeletes)
+ {
+ writer.writeOctetString(attrDef);
+ }
writer.writeEndSequence();
return byteBuilder.toByteArray();
}
catch (Exception e)
{
- return null;
+ throw new RuntimeException(e);
}
}
@@ -290,7 +302,7 @@
// Msg decoding
// ============
- private void decode_V4(byte[] in)
+ private void decode_V4(byte[] in, short version)
throws DataFormatException
{
ByteSequenceReader reader = ByteString.wrap(in).asReader();
@@ -328,6 +340,14 @@
this.eclIncludes.add(s);
}
asn1Reader.readEndSequence();
+
+ asn1Reader.readStartSequence();
+ while (asn1Reader.hasNextElement())
+ {
+ String s = asn1Reader.readOctetStringAsString();
+ this.eclIncludesForDeletes.add(s);
+ }
+ asn1Reader.readEndSequence();
}
catch (Exception e)
{
@@ -428,7 +448,8 @@
"\nassuredMode: " + assuredMode +
"\nsafeDataLevel: " + safeDataLevel +
"\nreferralsURLs: " + urls +
- "\nEclIncludes: " + eclIncludes);
+ "\nEclIncludes " + eclIncludes +
+ "\nEclIncludeForDeletes: " + eclIncludesForDeletes);
}
/**
@@ -459,22 +480,48 @@
}
/**
- * Set the list of entry attributes to include in the ECL.
- * @param eclIncludes The list of attributes.
+ * Set the attributes configured on a server to be included in the ECL.
+ *
+ * @param includeAttributes
+ * attributes to be included with all change records.
+ * @param includeAttributesForDeletes
+ * additional attributes to be included with delete change records.
*/
- public void setEclIncludes(Set<String> eclIncludes)
+ public void setEclIncludes(
+ Set<String> includeAttributes,
+ Set<String> includeAttributesForDeletes)
{
- if (eclIncludes != null)
- this.eclIncludes = eclIncludes;
+ if (includeAttributes != null)
+ {
+ eclIncludes = includeAttributes;
+ }
+
+ if (includeAttributesForDeletes != null)
+ {
+ eclIncludesForDeletes = includeAttributesForDeletes;
+ }
}
/**
- * Get the list of entry attributes to include in the ECL..
- * @return The list of entry attributes to include in the ECL.
+ * Get the attributes to include in each change for the ECL.
+ *
+ * @return The attributes to include in each change for the ECL.
*/
public Set<String> getEclIncludes()
{
return eclIncludes;
}
+
+
+ /**
+ * Get the attributes to include in each delete change for the ECL.
+ *
+ * @return The attributes to include in each delete change for the ECL.
+ */
+ public Set<String> getEclIncludesForDeletes()
+ {
+ return eclIncludesForDeletes;
+ }
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java
index 2fdf43b..4288497 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java
@@ -151,15 +151,14 @@
}
Set<String> attrs = new HashSet<String>();
+ Set<String> delattrs = new HashSet<String>();
short protocolVersion = -1;
- if (version>=ProtocolVersion.REPLICATION_PROTOCOL_V4)
+ if (version >= ProtocolVersion.REPLICATION_PROTOCOL_V4)
{
byte nAttrs = in[pos++];
nRead = 0;
/* Read attrs until expected number read */
- while ((nRead != nAttrs) &&
- (pos < in.length) //security
- )
+ while ((nRead != nAttrs) && (pos < in.length))
{
length = getNextLength(in, pos);
String attr = new String(in, pos, length, "UTF-8");
@@ -167,6 +166,19 @@
pos += length + 1;
nRead++;
}
+
+ nAttrs = in[pos++];
+ nRead = 0;
+ /* Read attrs until expected number read */
+ while ((nRead != nAttrs) && (pos < in.length))
+ {
+ length = getNextLength(in, pos);
+ String attr = new String(in, pos, length, "UTF-8");
+ delattrs.add(attr);
+ pos += length + 1;
+ nRead++;
+ }
+
/* Read Protocol version */
protocolVersion = Short.valueOf(in[pos++]);
}
@@ -175,7 +187,7 @@
DSInfo dsInfo = new DSInfo(dsId, rsId, generationId, status,
assuredFlag, assuredMode, safeDataLevel, groupId, refUrls, attrs,
- protocolVersion);
+ delattrs, protocolVersion);
dsList.add(dsInfo);
nDsInfo--;
@@ -347,9 +359,17 @@
oStream.write(attr.getBytes("UTF-8"));
oStream.write(0);
}
+
+ Set<String> delattrs = dsInfo.getEclIncludesForDeletes();
+ oStream.write(delattrs.size());
+ for (String attr : delattrs)
+ {
+ oStream.write(attr.getBytes("UTF-8"));
+ oStream.write(0);
+ }
+
oStream.write(dsInfo.getProtocolVersion());
}
-
}
// Put number of following RS info entries
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DataServerHandler.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DataServerHandler.java
index c0f67f9..4848f37 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DataServerHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DataServerHandler.java
@@ -77,6 +77,7 @@
// DS safe data level (relevant if assured mode is safe data)
private byte safeDataLevel = (byte) -1;
private Set<String> eclIncludes = new HashSet<String>();
+ private Set<String> eclIncludesForDeletes = new HashSet<String>();
/**
* Creates a new data server handler.
@@ -651,7 +652,7 @@
{
DSInfo dsInfo = new DSInfo(serverId, replicationServerId, generationId,
status, assuredFlag, assuredMode, safeDataLevel, groupId, refUrls,
- eclIncludes, protocolVersion);
+ eclIncludes, eclIncludesForDeletes, protocolVersion);
return dsInfo;
}
@@ -727,6 +728,7 @@
this.assuredMode = startSessionMsg.getAssuredMode();
this.safeDataLevel = startSessionMsg.getSafeDataLevel();
this.eclIncludes = startSessionMsg.getEclIncludes();
+ this.eclIncludesForDeletes = startSessionMsg.getEclIncludesForDeletes();
/*
* If we have already a generationID set for the domain
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java
index 9bb878d..26bcd5f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java
@@ -91,6 +91,7 @@
private short protocolVersion = -1;
private Set<String> eclInclude = new HashSet<String>();
+ private Set<String> eclIncludeForDeletes = new HashSet<String>();
/**
* Creates a new LighweightServerHandler with the provided serverid, connected
@@ -109,13 +110,15 @@
* @param assuredMode The assured mode of the remote DS
* @param safeDataLevel The safe data level of the remote DS
* @param eclInclude The list of entry attributes to be added to the ECL.
+ * @param eclIncludeForDeletes The list of entry attributes to be added to
+ * the ECL.
* @param protocolVersion The protocol version supported by the remote DS.
*/
public LightweightServerHandler(ReplicationServerHandler replServerHandler,
int replicationServerId, int serverId, long generationId, byte groupId,
ServerStatus status, List<String> refUrls, boolean assuredFlag,
AssuredMode assuredMode, byte safeDataLevel, Set<String> eclInclude,
- short protocolVersion)
+ Set<String> eclIncludeForDeletes, short protocolVersion)
{
this.replServerHandler = replServerHandler;
this.rsDomain = replServerHandler.getDomain();
@@ -129,6 +132,7 @@
this.assuredMode = assuredMode;
this.safeDataLevel = safeDataLevel;
this.eclInclude = eclInclude;
+ this.eclIncludeForDeletes = eclIncludeForDeletes;
this.protocolVersion = protocolVersion;
if (debugEnabled())
@@ -148,7 +152,7 @@
{
DSInfo dsInfo = new DSInfo(serverId, replicationServerId, generationId,
status, assuredFlag, assuredMode, safeDataLevel, groupId, refUrls,
- eclInclude, protocolVersion);
+ eclInclude, eclIncludeForDeletes, protocolVersion);
return dsInfo;
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java
index 320aacd..9d7a650b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java
@@ -721,6 +721,7 @@
dsInfo.isAssured(), dsInfo.getAssuredMode(),
dsInfo.getSafeDataLevel(),
dsInfo.getEclIncludes(),
+ dsInfo.getEclIncludesForDeletes(),
dsInfo.getProtocolVersion());
lsh.startHandler();
remoteDirectoryServers.put(lsh.getServerId(), lsh);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java b/opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java
index 9559252..af7bbf0 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java
@@ -1406,8 +1406,10 @@
domain.getAssuredMode(),
domain.getAssuredSdLevel());
startSessionMsg.setEclIncludes(
- domain.getEclInclude(domain.getServerId()));
- } else
+ domain.getEclIncludes(domain.getServerId()),
+ domain.getEclIncludesForDeletes(domain.getServerId()));
+ }
+ else
{
startSessionMsg =
new StartSessionMsg(initStatus, new ArrayList<String>());
@@ -2908,7 +2910,10 @@
if (domain != null)
{
for (DSInfo info : dsList)
- domain.setEclInclude(info.getDsId(), info.getEclIncludes());
+ {
+ domain.setEclIncludes(info.getDsId(), info.getEclIncludes(),
+ info.getEclIncludesForDeletes());
+ }
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java
index 6165758..e2be1e3 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java
@@ -38,17 +38,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketTimeoutException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.*;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -305,9 +295,15 @@
*/
private final ChangeNumberGenerator generator;
- private final Map<Integer, Set<String>> eclIncludeByServer =
- new ConcurrentHashMap<Integer, Set<String>>();
- Set<String> crossServersECLIncludes = new HashSet<String>();
+ private final Object eclIncludesLock = new Object();
+ private final Map<Integer, Set<String>> eclIncludesByServer =
+ new HashMap<Integer, Set<String>>();
+ private Set<String> eclIncludesAllServers = Collections.emptySet();
+
+ private final Map<Integer, Set<String>> eclIncludesForDeletesByServer =
+ new HashMap<Integer, Set<String>>();
+ private Set<String> eclIncludesForDeletesAllServers = Collections
+ .emptySet();
/**
* An object used to protect the initialization of the underlying broker
@@ -3174,37 +3170,23 @@
}
}
+
+
/**
- * Change some ReplicationDomain parameters : the ECL include attribute.
+ * Applies a configuration change to the attributes which should be be
+ * included in the ECL.
*
- * @param newECLInclude The new ECL attribute.
+ * @param includeAttributes
+ * attributes to be included with all change records.
+ * @param includeAttributesForDeletes
+ * additional attributes to be included with delete change records.
*/
- public void changeConfig(Set<String> newECLInclude)
+ public void changeConfig(Set<String> includeAttributes,
+ Set<String> includeAttributesForDeletes)
{
- boolean configECLIncludeChanged = false;
- Set<String> currentECLInclude = this.getEclInclude(serverID);
-
- if (newECLInclude.size() != currentECLInclude.size())
+ if (setEclIncludes(serverID, includeAttributes,
+ includeAttributesForDeletes))
{
- configECLIncludeChanged = true;
- }
- else
- {
- // compare current config and new config
- for (String attr : currentECLInclude)
- {
- if (!newECLInclude.contains(attr))
- {
- configECLIncludeChanged = true;
- break;
- }
- }
- }
-
- if (configECLIncludeChanged)
- {
- // set new config
- this.setEclInclude(this.serverID, newECLInclude);
if (broker != null)
{
disableService();
@@ -3213,6 +3195,8 @@
}
}
+
+
/**
* This method should trigger an export of the replicated data.
* to the provided outputStream.
@@ -3633,50 +3617,137 @@
return 0;
}
+
+
/**
- * Set the attributes configured on a server to be included in the ECL.
- * @param serverId server where these attributes are configured.
- * @param attributes the configured attributes.
+ * Set the attributes configured on a server to be included in the ECL.
+ *
+ * @param serverId
+ * Server where these attributes are configured.
+ * @param includeAttributes
+ * Attributes to be included with all change records, may include
+ * wild-cards.
+ * @param includeAttributesForDeletes
+ * Additional attributes to be included with delete change records,
+ * may include wild-cards.
+ * @return {@code true} if the set of attributes was modified.
*/
- public void setEclInclude(int serverId, Set<String> attributes)
+ public boolean setEclIncludes(int serverId,
+ Set<String> includeAttributes,
+ Set<String> includeAttributesForDeletes)
{
- synchronized(eclIncludeByServer)
+ boolean configurationChanged = false;
+
+ synchronized (eclIncludesLock)
{
- eclIncludeByServer.put(serverId, attributes);
+ Set<String> s1 = new HashSet<String>(includeAttributes);
+
+ // Combine all+delete attributes.
+ Set<String> s2 = new HashSet<String>(s1);
+ s2.addAll(includeAttributesForDeletes);
+
+ Set<String> s = eclIncludesByServer.get(serverId);
+ if (!s1.equals(s))
+ {
+ configurationChanged = true;
+ eclIncludesByServer.put(serverId, Collections.unmodifiableSet(s1));
+ }
+
+ s = eclIncludesForDeletesByServer.get(serverId);
+ if (!s2.equals(s))
+ {
+ configurationChanged = true;
+ eclIncludesForDeletesByServer.put(serverId,
+ Collections.unmodifiableSet(s2));
+ }
// and rebuild the global list to be ready for usage
- crossServersECLIncludes.clear();
- for (Set<String> attributesByServer : eclIncludeByServer.values())
- for (String attribute : attributesByServer)
- crossServersECLIncludes.add(attribute);
+ s = new HashSet<String>();
+ for (Set<String> attributes : eclIncludesByServer.values())
+ {
+ s.addAll(attributes);
+ }
+ eclIncludesAllServers = Collections.unmodifiableSet(s);
+
+ s = new HashSet<String>();
+ for (Set<String> attributes : eclIncludesForDeletesByServer.values())
+ {
+ s.addAll(attributes);
+ }
+ eclIncludesForDeletesAllServers = Collections.unmodifiableSet(s);
}
+
+ return configurationChanged;
}
+
+
/**
* Get the attributes to include in each change for the ECL.
- * It's a set : an attribute appears once even if configured on more than one
- * server.
+ *
* @return The attributes to include in each change for the ECL.
*/
- public Set<String> getEclInclude()
+ public Set<String> getEclIncludes()
{
- return crossServersECLIncludes;
- }
-
- /**
- * Get the attributes to include in each change for the ECL
- * for a given serverId.
- * @param serverId The serverId for which we want the include attributes.
- * @return The attributes.
- */
- public Set<String> getEclInclude(int serverId)
- {
- synchronized(eclIncludeByServer)
+ synchronized (eclIncludesLock)
{
- return eclIncludeByServer.get(serverId);
+ return eclIncludesAllServers;
}
}
+
+
+ /**
+ * Get the attributes to include in each delete change for the ECL.
+ *
+ * @return The attributes to include in each delete change for the ECL.
+ */
+ public Set<String> getEclIncludesForDeletes()
+ {
+ synchronized (eclIncludesLock)
+ {
+ return eclIncludesForDeletesAllServers;
+ }
+ }
+
+
+
+ /**
+ * Get the attributes to include in each change for the ECL for a given
+ * serverId.
+ *
+ * @param serverId
+ * The serverId for which we want the include attributes.
+ * @return The attributes.
+ */
+ public Set<String> getEclIncludes(int serverId)
+ {
+ synchronized (eclIncludesLock)
+ {
+ return eclIncludesByServer.get(serverId);
+ }
+ }
+
+
+
+ /**
+ * Get the attributes to include in each change for the ECL for a given
+ * serverId.
+ *
+ * @param serverId
+ * The serverId for which we want the include attributes.
+ * @return The attributes.
+ */
+ public Set<String> getEclIncludesForDeletes(int serverId)
+ {
+ synchronized (eclIncludesLock)
+ {
+ return eclIncludesForDeletesByServer.get(serverId);
+ }
+ }
+
+
+
/**
* Returns the ChangeNUmber of the last Change that was fully processed
* by this ReplicationDomain.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/Entry.java b/opendj-sdk/opends/src/server/org/opends/server/types/Entry.java
index 7f24093..0782a5f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/Entry.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/types/Entry.java
@@ -5062,9 +5062,7 @@
@Override
public String toString()
{
- StringBuilder buffer = new StringBuilder();
- toString(buffer);
- return buffer.toString();
+ return toLDIFString();
}
@@ -5078,51 +5076,7 @@
*/
public void toString(StringBuilder buffer)
{
- buffer.append("Entry(dn=\"");
- dn.toString(buffer);
-
- buffer.append("\", objectClasses={");
- if (! objectClasses.isEmpty())
- {
- Iterator<String> ocNames = objectClasses.values().iterator();
- buffer.append(ocNames.next());
-
- while (ocNames.hasNext())
- {
- buffer.append(",");
- buffer.append(ocNames.next());
- }
- }
-
- buffer.append("}, userAttrs={");
- if (! userAttributes.isEmpty())
- {
- Iterator<AttributeType> attrs =
- userAttributes.keySet().iterator();
- buffer.append(attrs.next().getNameOrOID());
-
- while (attrs.hasNext())
- {
- buffer.append(",");
- buffer.append(attrs.next().getNameOrOID());
- }
- }
-
- buffer.append("}, operationalAttrs={");
- if (! operationalAttributes.isEmpty())
- {
- Iterator<AttributeType> attrs =
- operationalAttributes.keySet().iterator();
- buffer.append(attrs.next().getNameOrOID());
-
- while (attrs.hasNext())
- {
- buffer.append(",");
- buffer.append(attrs.next().getNameOrOID());
- }
- }
-
- buffer.append("})");
+ buffer.append(toString());
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
index 0267b11..cc96e44 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
@@ -48,16 +48,7 @@
import java.io.StringReader;
import java.net.ServerSocket;
import java.net.Socket;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
+import java.util.*;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.Backend;
@@ -117,7 +108,6 @@
import org.opends.server.types.AbstractOperation;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeBuilder;
-import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.Attributes;
import org.opends.server.types.ByteString;
@@ -693,7 +683,7 @@
DomainFakeCfg domainConf =
new DomainFakeCfg(baseDn2, 1602, replServers);
ExternalChangelogDomainFakeCfg eclCfg =
- new ExternalChangelogDomainFakeCfg(true, null);
+ new ExternalChangelogDomainFakeCfg(true, null, null);
domainConf.setExternalChangelogDomain(eclCfg);
LDAPReplicationDomain domain2 =
MultimasterReplication.createNewDomain(domainConf);
@@ -753,7 +743,7 @@
}
eclCfg =
- new ExternalChangelogDomainFakeCfg(false, null);
+ new ExternalChangelogDomainFakeCfg(false, null, null);
domainConf.setExternalChangelogDomain(eclCfg);
domain2.applyConfigurationChange(domainConf);
@@ -4008,11 +3998,11 @@
new DomainFakeCfg(baseDn2, 1702, replServers);
// on o=test2,sid=1702 include attrs set to : 'sn'
- SortedSet<AttributeType> eclInclude = new TreeSet<AttributeType>();
- eclInclude.add(DirectoryServer.getAttributeType("sn"));
- eclInclude.add(DirectoryServer.getAttributeType("roomnumber"));
+ SortedSet<String> eclInclude = new TreeSet<String>();
+ eclInclude.add("sn");
+ eclInclude.add("roomnumber");
ExternalChangelogDomainFakeCfg eclCfg =
- new ExternalChangelogDomainFakeCfg(true, eclInclude);
+ new ExternalChangelogDomainFakeCfg(true, eclInclude, eclInclude);
domainConf.setExternalChangelogDomain(eclCfg);
// Set a Changetime heartbeat interval low enough (less than default
// value that is 1000 ms) for the test to be sure to consider all changes
@@ -4028,10 +4018,13 @@
new DomainFakeCfg(baseDn3, 1703, replServers);
// on o=test3,sid=1703 include attrs set to : 'objectclass'
- eclInclude = new TreeSet<AttributeType>();
- eclInclude.add(DirectoryServer.getAttributeType("objectclass"));
- eclCfg =
- new ExternalChangelogDomainFakeCfg(true, eclInclude);
+ eclInclude = new TreeSet<String>();
+ eclInclude.add("objectclass");
+
+ TreeSet<String> eclIncludeForDeletes = new TreeSet<String>();
+ eclIncludeForDeletes.add("*");
+
+ eclCfg = new ExternalChangelogDomainFakeCfg(true, eclInclude, eclIncludeForDeletes);
domainConf.setExternalChangelogDomain(eclCfg);
// Set a Changetime heartbeat interval low enough (less than default
// value that is 1000 ms) for the test to be sure to consider all changes
@@ -4043,10 +4036,11 @@
// on o=test2,sid=1704 include attrs set to : 'cn'
domainConf =
new DomainFakeCfg(baseDn2, 1704, replServers);
- eclInclude = new TreeSet<AttributeType>();
- eclInclude.add(DirectoryServer.getAttributeType("cn"));
+ eclInclude = new TreeSet<String>();
+ eclInclude.add("cn");
+
eclCfg =
- new ExternalChangelogDomainFakeCfg(true, eclInclude);
+ new ExternalChangelogDomainFakeCfg(true, eclInclude, eclInclude);
domainConf.setExternalChangelogDomain(eclCfg);
// Set a Changetime heartbeat interval low enough (less than default
// value that is 1000 ms) for the test to be sure to consider all changes
@@ -4185,8 +4179,23 @@
HashSet<String> eoc = new HashSet<String>();
eoc.add("person");eoc.add("inetOrgPerson");eoc.add("organizationalPerson");eoc.add("top");
- assertEquals(targetEntry.getAttributes().size(), 0); // objectClass is handled separately
checkValues(targetEntry,"objectclass",eoc);
+
+ String changeType = getAttributeValue(resultEntry,
+ "changetype");
+ if (changeType.equals("delete"))
+ {
+ // We are using "*" for deletes so should get back 4 attributes.
+ assertEquals(targetEntry.getAttributes().size(), 4);
+ checkValue(targetEntry, "uid", "robert");
+ checkValue(targetEntry, "cn", "Robert Hue2");
+ checkValue(targetEntry, "telephonenumber", "555555");
+ checkValue(targetEntry, "sn", "Robby");
+ }
+ else
+ {
+ assertEquals(targetEntry.getAttributes().size(), 0);
+ }
}
if (targetdn.endsWith("cn=fiona jensen,o=test2"))
{
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java
index e00d04c..22f8ab3 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2007-2010 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.plugin;
@@ -78,9 +79,8 @@
private SortedSet<String> fractionalExcludes = new TreeSet<String>();
private SortedSet<String> fractionalIncludes = new TreeSet<String>();
- private SortedSet<String> eclIncludes = new TreeSet<String>();
private ExternalChangelogDomainCfg eclCfg =
- new ExternalChangelogDomainFakeCfg(true, new TreeSet<AttributeType>());
+ new ExternalChangelogDomainFakeCfg(true, null, null);
/**
* Creates a new Domain with the provided information
@@ -380,16 +380,6 @@
return true;
}
- public void setEclIncludes(SortedSet<String> attrs)
- {
- this.eclIncludes = attrs;
- }
-
- public SortedSet<String> getECLInclude()
- {
- return this.eclIncludes;
- }
-
public long getInitializationHeartbeatInterval()
{
return 180;
@@ -492,7 +482,7 @@
{
return true;
}
-
+
/**
* Gets the "conflicts-historical-purge-delay" property.
* <p>
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ExternalChangelogDomainFakeCfg.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ExternalChangelogDomainFakeCfg.java
index 7ad58c9..c976d46 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ExternalChangelogDomainFakeCfg.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ExternalChangelogDomainFakeCfg.java
@@ -23,41 +23,47 @@
*
*
* Copyright 2007-2009 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.plugin;
import java.util.SortedSet;
+import java.util.TreeSet;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.ExternalChangelogDomainCfg;
-import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
/**
* This class implement a configuration object for the ExternalChangelog domain
* that can be used in unit tests to instantiate ExternalChangelogDomain.
*/
-public class ExternalChangelogDomainFakeCfg
+public class ExternalChangelogDomainFakeCfg
implements ExternalChangelogDomainCfg
{
// The value of the "ecl-include" property.
- private SortedSet<AttributeType> pECLInclude;
+ private SortedSet<String> pECLInclude;
+
+ // The value of the "ecl-include-for-deletes" property.
+ private SortedSet<String> pECLIncludeForDeletes;
// The value of the "enabled" property.
private boolean pEnabled;
private DN pDN;
-
+
/**
* Creates a new Domain with the provided information
* (assured mode disabled, default group id)
*/
public ExternalChangelogDomainFakeCfg(boolean isEnabled,
- SortedSet<AttributeType> eCLInclude)
+ SortedSet<String> eclInclude,
+ SortedSet<String> eclIncludeForDeletes)
{
this.pEnabled = isEnabled;
- this.pECLInclude = eCLInclude;
+ this.pECLInclude = eclInclude != null ? eclInclude : new TreeSet<String>();
+ this.pECLIncludeForDeletes = eclIncludeForDeletes != null ? eclIncludeForDeletes : new TreeSet<String>();
}
/**
@@ -92,29 +98,14 @@
- /**
- * Gets the "ecl-include" property.
- * <p>
- * Allows to include some target entry attributes in the external
- * changelog.
- * <p>
- * Specifies an attribute that will be included in every External
- * Change Log entry related to this replication domain.
- *
- * @return Returns an unmodifiable set containing the values of the "ecl-include" property.
- */
- public SortedSet<AttributeType> getECLInclude()
+ public SortedSet<String> getECLInclude()
{
return this.pECLInclude;
}
- /**
- * Set eclInclude.
- * @param eclInclude the attribute to include.
- */
- public void setECLInclude(SortedSet<AttributeType> eclInclude)
+ public SortedSet<String> getECLIncludeForDeletes()
{
- this.pECLInclude = eclInclude;
+ return this.pECLIncludeForDeletes;
}
@@ -140,7 +131,7 @@
{
return this.pEnabled;
}
-
+
public DN dn()
{
return pDN;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java
index 70d7e07..735f221 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java
@@ -23,12 +23,11 @@
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.plugin;
import java.net.UnknownHostException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import static org.opends.server.TestCaseUtils.TEST_ROOT_DN_STRING;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
@@ -922,7 +921,7 @@
}
return new DSInfo(dsId, rsId, TEST_DN_WITH_ROOT_ENTRY_GENID, status, assuredFlag, assMode,
- (byte)assuredSdLevel, groupId, urls, eclIncludes, protocolVersion);
+ (byte)assuredSdLevel, groupId, urls, eclIncludes, eclIncludes, protocolVersion);
}
/**
@@ -1122,10 +1121,11 @@
byte safeDataLevel = rd.getAssuredSdLevel();
byte groupId = rd.getGroupId();
List<String> refUrls = rd.getRefUrls();
- Set<String> eclInclude = rd.getEclInclude();
+ Set<String> eclInclude = rd.getEclIncludes();
+ Set<String> eclIncludeForDeletes = rd.getEclIncludesForDeletes();
short protocolVersion = 4;
DSInfo dsInfo = new DSInfo(dsId, rsId, TEST_DN_WITH_ROOT_ENTRY_GENID, status, assuredFlag, assuredMode,
- safeDataLevel, groupId, refUrls, eclInclude, protocolVersion);
+ safeDataLevel, groupId, refUrls, eclInclude, eclIncludeForDeletes, protocolVersion);
dsList.add(dsInfo);
TopoView dsTopoView = new TopoView(dsList, rd.getRsList());
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java
index 09b1561..9e17bc9 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.protocol;
@@ -1069,16 +1070,16 @@
urls4.add("ldaps://host:port/dc=foobar2??sub?(sn=Another Entry 2)");
DSInfo dsInfo1 = new DSInfo(13, 26, (long)154631, ServerStatus.FULL_UPDATE_STATUS,
- false, AssuredMode.SAFE_DATA_MODE, (byte)12, (byte)132, urls1, new HashSet<String>(), (short)-1);
+ false, AssuredMode.SAFE_DATA_MODE, (byte)12, (byte)132, urls1, new HashSet<String>(), new HashSet<String>(), (short)-1);
DSInfo dsInfo2 = new DSInfo(-436, 493, (long)-227896, ServerStatus.DEGRADED_STATUS,
- true, AssuredMode.SAFE_READ_MODE, (byte)-7, (byte)-265, urls2, new HashSet<String>(), (short)-1);
+ true, AssuredMode.SAFE_READ_MODE, (byte)-7, (byte)-265, urls2, new HashSet<String>(), new HashSet<String>(), (short)-1);
DSInfo dsInfo3 = new DSInfo(2436, 591, (long)0, ServerStatus.NORMAL_STATUS,
- false, AssuredMode.SAFE_READ_MODE, (byte)17, (byte)0, urls3, new HashSet<String>(), (short)-1);
+ false, AssuredMode.SAFE_READ_MODE, (byte)17, (byte)0, urls3, new HashSet<String>(), new HashSet<String>(), (short)-1);
DSInfo dsInfo4 = new DSInfo(415, 146, (long)0, ServerStatus.BAD_GEN_ID_STATUS,
- true, AssuredMode.SAFE_DATA_MODE, (byte)2, (byte)15, urls4, new HashSet<String>(), (short)-1);
+ true, AssuredMode.SAFE_DATA_MODE, (byte)2, (byte)15, urls4, new HashSet<String>(), new HashSet<String>(), (short)-1);
List<DSInfo> dsList1 = new ArrayList<DSInfo>();
dsList1.add(dsInfo1);
@@ -1261,7 +1262,7 @@
* using protocol VLAST and V3 are working.
*/
@Test(enabled=true, dataProvider="createInitializationRequestMsgData")
- public void initializationRequestMsgTestVLASTV3(int sender, int dest,
+ public void initializationRequestMsgTestVLASTV3(int sender, int dest,
String baseDn, int initWindow)
throws Exception
{
@@ -1305,7 +1306,7 @@
String baseDn = "dc=whatever";
int entryCount = 56;
int initWindow = 22;
- Object[] set1 = new Object[] {sender, dest, initiator, baseDn,
+ Object[] set1 = new Object[] {sender, dest, initiator, baseDn,
entryCount, initWindow };
return new Object [][] { set1};
}
@@ -1315,7 +1316,7 @@
* using protocol VLAST and V3 are working.
*/
@Test(enabled=true, dataProvider="createInitializeTargetMsgData")
- public void initializeTargetMsgTestVLASTV3(int sender, int dest,
+ public void initializeTargetMsgTestVLASTV3(int sender, int dest,
int initiator, String baseDn, int entryCount, int initWindow)
throws Exception
{
@@ -1354,7 +1355,7 @@
assertEquals(msg.getInitiatorID(), vlastMsg.getInitiatorID());
assertEquals(msg.getInitWindow(), vlastMsg.getInitWindow());
}
-
+
@DataProvider(name = "createEntryMsgV3")
public Object[][] createEntryMsgV3()
{
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
index ef8fa71..53f1a71 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
+ * Portions copyright 2011 ForgeRock AS
*/
package org.opends.server.replication.protocol;
@@ -380,7 +381,7 @@
i++;
}
}
-
+
Operation generatedOperation = generatedMsg.createOperation(connection);
assertEquals(generatedOperation.getClass(), DeleteOperationBasis.class);
@@ -1006,19 +1007,19 @@
Set<String> a4 = new HashSet<String>();
DSInfo dsInfo1 = new DSInfo(13, 26, (long)154631, ServerStatus.FULL_UPDATE_STATUS,
- false, AssuredMode.SAFE_DATA_MODE, (byte)12, (byte)132, urls1, a1, (short)1);
+ false, AssuredMode.SAFE_DATA_MODE, (byte)12, (byte)132, urls1, a1, a1, (short)1);
DSInfo dsInfo2 = new DSInfo(-436, 493, (long)-227896, ServerStatus.DEGRADED_STATUS,
- true, AssuredMode.SAFE_READ_MODE, (byte)-7, (byte)-265, urls2, a2, (short)2);
+ true, AssuredMode.SAFE_READ_MODE, (byte)-7, (byte)-265, urls2, a2, a2, (short)2);
DSInfo dsInfo3 = new DSInfo(2436, 591, (long)0, ServerStatus.NORMAL_STATUS,
- false, AssuredMode.SAFE_READ_MODE, (byte)17, (byte)0, urls3, a3, (short)3);
+ false, AssuredMode.SAFE_READ_MODE, (byte)17, (byte)0, urls3, a3, a3, (short)3);
DSInfo dsInfo4 = new DSInfo(415, 146, (long)0, ServerStatus.BAD_GEN_ID_STATUS,
- true, AssuredMode.SAFE_DATA_MODE, (byte)2, (byte)15, urls4, a4, (short)4);
+ true, AssuredMode.SAFE_DATA_MODE, (byte)2, (byte)15, urls4, a4, a4, (short)4);
DSInfo dsInfo5 = new DSInfo(452436, 45591, (long)0, ServerStatus.NORMAL_STATUS,
- false, AssuredMode.SAFE_READ_MODE, (byte)17, (byte)0, urls3, a1, (short)5);
+ false, AssuredMode.SAFE_READ_MODE, (byte)17, (byte)0, urls3, a1, a1, (short)5);
List<DSInfo> dsList1 = new ArrayList<DSInfo>();
dsList1.add(dsInfo1);
@@ -1138,7 +1139,7 @@
{
StartSessionMsg msg = new StartSessionMsg(status, refUrls, assuredFlag,
assuredMode, safedataLevel);
- msg.setEclIncludes(attrs);
+ msg.setEclIncludes(attrs, attrs);
StartSessionMsg newMsg =
new StartSessionMsg(msg.getBytes(),ProtocolVersion.getCurrentVersion());
assertEquals(msg.getStatus(), newMsg.getStatus());
@@ -1146,8 +1147,8 @@
assertEquals(msg.getAssuredMode(), newMsg.getAssuredMode());
assertTrue(msg.getSafeDataLevel() == newMsg.getSafeDataLevel());
assertEquals(msg.getReferralsURLs(), newMsg.getReferralsURLs());
- Set<String> newAttrs = newMsg.getEclIncludes();
- assertTrue(attrs.size() == newAttrs.size());
+ assertTrue(attrs.equals(newMsg.getEclIncludes()));
+ assertTrue(attrs.equals(newMsg.getEclIncludesForDeletes()));
}
/**
--
Gitblit v1.10.0