From 76ebd1ad82e2a1fc421519f09c62b948e9376e8a Mon Sep 17 00:00:00 2001
From: pgamba <pgamba@localhost>
Date: Tue, 06 Oct 2009 12:34:32 +0000
Subject: [PATCH] Entry attributes for ECL - Protocol V4
---
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java | 320 +++-
opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java | 399 ++++-
opends/src/admin/defn/org/opends/server/admin/std/ReplicationDomainConfiguration.xml | 43
opends/src/server/org/opends/server/replication/common/DSInfo.java | 25
opends/src/server/org/opends/server/replication/protocol/ReplicationMsg.java | 4
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java | 538 ++++++
opends/src/server/org/opends/server/replication/service/ReplicationBroker.java | 20
opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java | 5
opends/resource/schema/02-config.ldif | 7
opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java | 3
opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java | 374 ++++-
opends/src/server/org/opends/server/types/RawAttribute.java | 2
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java | 51
opends/src/server/org/opends/server/replication/protocol/AddMsg.java | 486 ++++--
opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java | 284 ++-
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java | 24
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java | 15
opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java | 217 ++
opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java | 13
opends/src/server/org/opends/server/replication/server/ServerReader.java | 29
opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java | 493 ++++--
opends/src/server/org/opends/server/replication/service/ReplicationDomain.java | 32
opends/src/server/org/opends/server/replication/protocol/ProtocolVersion.java | 11
opends/src/server/org/opends/server/replication/server/DataServerHandler.java | 7
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java | 2
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java | 337 ++++
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java | 47
opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java | 135 -
opends/src/server/org/opends/server/replication/protocol/ModifyCommonMsg.java | 69
opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java | 89 +
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java | 111 +
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/FakeReplicationDomain.java | 4
32 files changed, 3,097 insertions(+), 1,099 deletions(-)
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index d1010ec..8f0c851 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -2449,6 +2449,10 @@
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE
X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.601
+ NAME 'ds-cfg-ecl-include'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler'
SUP top
@@ -3011,7 +3015,8 @@
ds-cfg-fractional-exclude $
ds-cfg-fractional-include $
ds-cfg-solve-conflicts $
- ds-cfg-changetime-heartbeat-interval)
+ ds-cfg-changetime-heartbeat-interval $
+ ds-cfg-ecl-include )
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.58
NAME 'ds-cfg-length-based-password-validator'
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/ReplicationDomainConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/ReplicationDomainConfiguration.xml
index a8439b5..154fd70 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/ReplicationDomainConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/ReplicationDomainConfiguration.xml
@@ -487,4 +487,47 @@
</ldap:attribute>
</adm:profile>
</adm:property>
+ <adm:property name="ecl-include" multi-valued="true" mandatory="false">
+ <adm:synopsis>
+ Allows to include some target entry attributes in the ECL.
+ </adm:synopsis>
+ <adm:description>
+ Specifies an attribute that will be included in every External Change Log
+ entry related to this replication domain.
+ </adm:description>
+ <adm:default-behavior>
+ <adm:undefined/>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:string>
+ <adm:pattern>
+ <!-- This java regex is mostly derived from keystring BNF definition
+ that can be found in RFC 2252, section "4.1. Common Encoding Aspects".
+ This can be read as: (oid|\*):oid(,oid)*+
+ -->
+ <adm:regex>^((([a-zA-Z]([a-zA-Z]|[0-9]|-|;)*+)|(0|([1-9]([0-9])*+))(\\.(0|([1-9]([0-9])*+)))*+)|\\*):(([a-zA-Z]([a-zA-Z]|[0-9]|-|;)*+)|(0|([1-9]([0-9])*+))(\\.(0|([1-9]([0-9])*+)))*+)(,(([a-zA-Z]([a-zA-Z]|[0-9]|-|;)*+)|(0|([1-9]([0-9])*+))(\\.(0|([1-9]([0-9])*+)))*+))*+$</adm:regex>
+ <adm:usage>Syntax:
+ className:attributeName[,attributeName]
+ or
+ *:attributeName[,attributeName].
+ Note that any class (className) or attribute (attributeName) definition can be replaced with its OID definition.
+ Examples:
+ inetOrgPerson:photo,jpegPhoto : 'photo' and 'jpegPhoto' attributes of any entry of type 'inetOrgPerson' class.
+ This can also be 2.16.840.1.113730.3.2.2:0.9.2342.19200300.100.1.7,0.9.2342.19200300.100.1.60 or a mix.
+ *:jpegPhoto : the 'jpegPhoto' attribute of any entry that has this attribute.
+ This can also be *:0.9.2342.19200300.100.1.60
+ </adm:usage>
+ <adm:synopsis>
+ Defines attribute(s) of one particular class or of all possible
+ classes, to exclude from the replication.
+ </adm:synopsis>
+ </adm:pattern>
+ </adm:string>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:name>ds-cfg-ecl-include</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
</adm:managed-object>
diff --git a/opends/src/server/org/opends/server/replication/common/DSInfo.java b/opends/src/server/org/opends/server/replication/common/DSInfo.java
index ffda986..32e00f7 100644
--- a/opends/src/server/org/opends/server/replication/common/DSInfo.java
+++ b/opends/src/server/org/opends/server/replication/common/DSInfo.java
@@ -22,12 +22,14 @@
* CDDL HEADER END
*
*
- * Copyright 2008 Sun Microsystems, Inc.
+ * Copyright 2008-2009 Sun Microsystems, Inc.
*/
package org.opends.server.replication.common;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* This class holds information about a DS connected to the topology. This
@@ -57,6 +59,8 @@
// Group id
private byte groupId = (byte) -1;
+ private Set<String> eclIncludes = new HashSet<String>();
+
/**
* Creates a new instance of DSInfo with every given info.
*
@@ -69,10 +73,11 @@
* @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.
*/
public DSInfo(short dsId, short rsId, long generationId, ServerStatus status,
boolean assuredFlag, AssuredMode assuredMode, byte safeDataLevel,
- byte groupId, List<String> refUrls)
+ byte groupId, List<String> refUrls, Set<String> eclIncludes)
{
this.dsId = dsId;
@@ -84,6 +89,7 @@
this.safeDataLevel = safeDataLevel;
this.groupId = groupId;
this.refUrls = refUrls;
+ this.eclIncludes = eclIncludes;
}
/**
@@ -168,6 +174,15 @@
}
/**
+ * Get the entry attributes to be included in the ECL.
+ * @return a.
+ */
+ public Set<String> getEclIncludes()
+ {
+ return eclIncludes;
+ }
+
+ /**
* Test if the passed object is equal to this one.
* @param obj The object to test
* @return True if both objects are equal
@@ -190,7 +205,8 @@
(assuredMode == dsInfo.getAssuredMode()) &&
(safeDataLevel == dsInfo.getSafeDataLevel()) &&
(groupId == dsInfo.getGroupId()) &&
- (refUrls.equals(dsInfo.getRefUrls())));
+ (refUrls.equals(dsInfo.getRefUrls())) &&
+ (eclIncludes.equals(dsInfo.getEclIncludes())));
} else
{
return false;
@@ -214,6 +230,7 @@
73 * hash + (this.assuredMode != null ? this.assuredMode.hashCode() : 0);
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.groupId;
return hash;
}
@@ -244,6 +261,8 @@
sb.append(groupId);
sb.append("\nReferral URLs: ");
sb.append(refUrls);
+ sb.append("\nECL Include: ");
+ sb.append(eclIncludes);
return sb.toString();
}
diff --git a/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java b/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
index 7a4a8d4..f1270e2 100644
--- a/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
+++ b/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -38,19 +38,12 @@
import static org.opends.server.util.StaticUtils.getFileForPath;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
-import org.opends.server.replication.protocol.LDAPUpdateMsg;
-
-import org.opends.server.replication.service.ReplicationMonitor;
-
-import java.util.Collection;
-
-import org.opends.server.types.Attributes;
-
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -99,7 +92,6 @@
import org.opends.server.protocols.ldap.LDAPAttribute;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.protocols.ldap.LDAPModification;
-import org.opends.server.replication.service.ReplicationDomain;
import org.opends.server.replication.common.AssuredMode;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ChangeNumberGenerator;
@@ -109,6 +101,8 @@
import org.opends.server.replication.protocol.AddContext;
import org.opends.server.replication.protocol.AddMsg;
import org.opends.server.replication.protocol.DeleteContext;
+import org.opends.server.replication.protocol.DeleteMsg;
+import org.opends.server.replication.protocol.LDAPUpdateMsg;
import org.opends.server.replication.protocol.ModifyContext;
import org.opends.server.replication.protocol.ModifyDNMsg;
import org.opends.server.replication.protocol.ModifyDnContext;
@@ -117,6 +111,8 @@
import org.opends.server.replication.protocol.ProtocolSession;
import org.opends.server.replication.protocol.RoutableMsg;
import org.opends.server.replication.protocol.UpdateMsg;
+import org.opends.server.replication.service.ReplicationDomain;
+import org.opends.server.replication.service.ReplicationMonitor;
import org.opends.server.tasks.TaskUtils;
import org.opends.server.types.AbstractOperation;
import org.opends.server.types.Attribute;
@@ -124,10 +120,12 @@
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.AttributeValues;
+import org.opends.server.types.Attributes;
import org.opends.server.types.ByteString;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.Control;
import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DereferencePolicy;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
@@ -149,6 +147,10 @@
import org.opends.server.types.SearchScope;
import org.opends.server.types.SynchronizationProviderResult;
import org.opends.server.types.operation.PluginOperation;
+import org.opends.server.types.operation.PostOperationAddOperation;
+import org.opends.server.types.operation.PostOperationDeleteOperation;
+import org.opends.server.types.operation.PostOperationModifyDNOperation;
+import org.opends.server.types.operation.PostOperationModifyOperation;
import org.opends.server.types.operation.PostOperationOperation;
import org.opends.server.types.operation.PreOperationAddOperation;
import org.opends.server.types.operation.PreOperationDeleteOperation;
@@ -346,6 +348,7 @@
// The operation should become a no-op
private static final int FRACTIONAL_BECOME_NO_OP = 3;
+
/**
* The thread that periodically saves the ServerState of this
* LDAPReplicationDomain in the database.
@@ -428,6 +431,8 @@
setGroupId((byte)configuration.getGroupId());
setURLs(configuration.getReferralsUrl());
+ setCfgEclInclude(configuration.getEclInclude());
+
/*
* Modify conflicts are solved for all suffixes but the schema suffix
* because we don't want to store extra information in the schema
@@ -2200,6 +2205,14 @@
}
else
{
+ try
+ {
+ addEntryAttributesForCL(msg,op);
+ }
+ catch(Exception e)
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
// If assured replication is configured, this will prepare blocking
// mechanism. If assured replication is disabled, this returns
// immediately
@@ -4498,6 +4511,86 @@
}
/**
+ * Called by synchronize post op plugin in order to add the entry historized
+ * attributes to the UpdateMsg.
+ * @param msg
+ * @param 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);
+ for (Attribute a : attrs)
+ newattrs.add(a);
+ }
+ ((DeleteMsg)msg).setEclIncludes(newattrs);
+ }
+ 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);
+ for (Attribute a : attrs)
+ newattrs.add(a);
+ }
+ ((ModifyMsg)msg).setEclIncludes(newattrs);
+ }
+ else if (op instanceof PostOperationModifyDNOperation)
+ {
+ Entry entry = null;
+ PostOperationModifyDNOperation modDNOp =
+ (PostOperationModifyDNOperation)op;
+ entry = modDNOp.getOriginalEntry();
+ for (String name : entryAttributeNames)
+ {
+ AttributeType atype = DirectoryServer.getAttributeType(name);
+ List<Attribute> attrs = entry.getAttribute(atype);
+ for (Attribute a : attrs)
+ newattrs.add(a);
+ }
+ ((ModifyDNMsg)msg).setEclIncludes(newattrs);
+ }
+ 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);
+ }
+ }
+
+ /**
* Gets the fractional configuration of this domain.
* @return The fractional configuration of this domain.
*/
diff --git a/opends/src/server/org/opends/server/replication/protocol/AddMsg.java b/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
index eb9384e..83defc1 100644
--- a/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
@@ -41,7 +41,6 @@
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.asn1.ASN1;
import org.opends.server.protocols.asn1.ASN1Exception;
-import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.types.*;
import org.opends.server.types.operation.PostOperationAddOperation;
@@ -55,7 +54,10 @@
*/
public class AddMsg extends LDAPUpdateMsg
{
+ // Attributes are managed encoded
private byte[] encodedAttributes;
+
+ // Parent is managed decoded
private String parentUniqueId;
/**
@@ -68,12 +70,248 @@
op.getRawEntryDN().toString());
AddContext ctx = (AddContext) op.getAttachment(SYNCHROCONTEXT);
+
+ // Stores parentUniqueID not encoded
this.parentUniqueId = ctx.getParentUid();
- this.encodedAttributes =
- encodeAttributes(op.getObjectClasses(),
- op.getUserAttributes(),
- op.getOperationalAttributes());
+ // Stores attributes encoded
+ this.encodedAttributes = encodeAttributes(op.getObjectClasses(),
+ op.getUserAttributes(), op.getOperationalAttributes());
+ }
+
+ /**
+ * Creates a new AddMessage.
+ *
+ * @param cn ChangeNumber of the add.
+ * @param dn DN of the added entry.
+ * @param uniqueId The Unique identifier of the added entry.
+ * @param parentId The unique Id of the parent of the added
+ * entry.
+ * @param objectClasses objectclass of the added entry.
+ * @param userAttributes user attributes of the added entry.
+ * @param operationalAttributes operational attributes of the added entry.
+ */
+ public AddMsg(ChangeNumber cn,
+ String dn,
+ String uniqueId,
+ String parentId,
+ Map<ObjectClass, String> objectClasses,
+ Map<AttributeType,List<Attribute>> userAttributes,
+ Map<AttributeType,List<Attribute>> operationalAttributes)
+ {
+ super (cn, uniqueId, dn);
+
+ // Stores parentUniqueID not encoded
+ this.parentUniqueId = parentId;
+
+ // Stores attributes encoded
+ this.encodedAttributes = encodeAttributes(objectClasses, userAttributes,
+ operationalAttributes);
+ }
+
+
+ /**
+ * Creates a new AddMessage.
+ *
+ * @param cn ChangeNumber of the add.
+ * @param dn DN of the added entry.
+ * @param uniqueId The Unique identifier of the added entry.
+ * @param parentId The unique Id of the parent of the added entry.
+ * @param objectClass objectclass of the added entry.
+ * @param userAttributes user attributes of the added entry.
+ * @param operationalAttributes operational attributes of the added entry.
+ */
+ public AddMsg(ChangeNumber cn,
+ String dn,
+ String uniqueId,
+ String parentId,
+ Attribute objectClass,
+ Collection<Attribute> userAttributes,
+ Collection<Attribute> operationalAttributes)
+ {
+ super (cn, uniqueId, dn);
+
+ // Stores parentUniqueID not encoded
+ this.parentUniqueId = parentId;
+
+ // Stores attributes encoded
+ this.encodedAttributes = encodeAttributes(objectClass, userAttributes,
+ operationalAttributes);
+ }
+
+ /**
+ * Creates a new Add message from a byte[].
+ *
+ * @param in The byte[] from which the operation must be read.
+ * @throws DataFormatException The input byte[] is not a valid AddMsg
+ * @throws UnsupportedEncodingException If UTF8 is not supported by the jvm
+ */
+ public AddMsg(byte[] in) throws DataFormatException,
+ UnsupportedEncodingException
+ {
+ byte[] allowedPduTypes = new byte[2];
+ allowedPduTypes[0] = MSG_TYPE_ADD;
+ allowedPduTypes[1] = MSG_TYPE_ADD_V1;
+ int pos = decodeHeader(allowedPduTypes, in);
+
+ // protocol version has been read as part of the header
+ if (protocolVersion <= 3)
+ decodeBody_V123(in, pos);
+ else
+ {
+ decodeBody_V4(in, pos);
+ }
+ if (protocolVersion==ProtocolVersion.getCurrentVersion())
+ {
+ bytes = in;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public AddOperationBasis createOperation(
+ InternalClientConnection connection, String newDn)
+ throws LDAPException, ASN1Exception
+ {
+ ArrayList<RawAttribute> attr = decodeRawAttributes(encodedAttributes);
+
+ AddOperationBasis add = new AddOperationBasis(connection,
+ InternalClientConnection.nextOperationID(),
+ InternalClientConnection.nextMessageID(), null,
+ ByteString.valueOf(newDn), attr);
+ AddContext ctx = new AddContext(getChangeNumber(), getUniqueId(),
+ parentUniqueId);
+ add.setAttachment(SYNCHROCONTEXT, ctx);
+ return add;
+ }
+
+ // ============
+ // Msg encoding
+ // ============
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes_V1() throws UnsupportedEncodingException
+ {
+ int bodyLength = encodedAttributes.length;
+ byte[] byteParentId = null;
+ if (parentUniqueId != null)
+ {
+ byteParentId = parentUniqueId.getBytes("UTF-8");
+ bodyLength += byteParentId.length + 1;
+ }
+ else
+ {
+ bodyLength += 1;
+ }
+
+ /* encode the header in a byte[] large enough to also contain the mods */
+ byte [] resultByteArray = encodeHeader_V1(MSG_TYPE_ADD_V1, bodyLength);
+
+ int pos = resultByteArray.length - bodyLength;
+
+ if (byteParentId != null)
+ pos = addByteArray(byteParentId, resultByteArray, pos);
+ else
+ resultByteArray[pos++] = 0;
+
+ /* put the attributes */
+ for (int i=0; i<encodedAttributes.length; i++,pos++)
+ {
+ resultByteArray[pos] = encodedAttributes[i];
+ }
+ return resultByteArray;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes_V23() throws UnsupportedEncodingException
+ {
+ // Put together the different encoded pieces
+ int bodyLength = encodedAttributes.length;
+
+ // Compute the total length of the body
+ byte[] byteParentId = null;
+ if (parentUniqueId != null)
+ {
+ // Encode parentID now to get the length of the encoded bytes
+ byteParentId = parentUniqueId.getBytes("UTF-8");
+ bodyLength += byteParentId.length + 1;
+ }
+ else
+ {
+ bodyLength += 1;
+ }
+
+ /* encode the header in a byte[] large enough to also contain the mods */
+ byte [] resultByteArray = encodeHeader(MSG_TYPE_ADD, bodyLength);
+
+ int pos = resultByteArray.length - bodyLength;
+
+ if (byteParentId != null)
+ pos = addByteArray(byteParentId, resultByteArray, pos);
+ else
+ resultByteArray[pos++] = 0;
+
+ /* put the attributes */
+ for (int i=0; i<encodedAttributes.length; i++,pos++)
+ {
+ resultByteArray[pos] = encodedAttributes[i];
+ }
+ return resultByteArray;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes_V4() throws UnsupportedEncodingException
+ {
+ // Put together the different encoded pieces
+ int bodyLength = 0;
+
+ // Compute the total length of the body
+ byte[] byteParentId = null;
+ if (parentUniqueId != null)
+ {
+ // Encode parentID now to get the length of the encoded bytes
+ byteParentId = parentUniqueId.getBytes("UTF-8");
+ bodyLength += byteParentId.length + 1;
+ }
+ else
+ {
+ bodyLength += 1;
+ }
+
+ byte[] byteAttrLen =
+ String.valueOf(encodedAttributes.length).getBytes("UTF-8");
+ bodyLength += byteAttrLen.length + 1;
+ bodyLength += encodedAttributes.length + 1;
+
+ byte[] byteEntryAttrLen =
+ String.valueOf(encodedEclIncludes.length).getBytes("UTF-8");
+ bodyLength += byteEntryAttrLen.length + 1;
+ bodyLength += encodedEclIncludes.length + 1;
+
+ /* encode the header in a byte[] large enough to also contain the mods */
+ byte [] encodedMsg = encodeHeader(MSG_TYPE_ADD, bodyLength);
+
+ int pos = encodedMsg.length - bodyLength;
+ if (byteParentId != null)
+ pos = addByteArray(byteParentId, encodedMsg, pos);
+ else
+ encodedMsg[pos++] = 0;
+ pos = addByteArray(byteAttrLen, encodedMsg, pos);
+ pos = addByteArray(encodedAttributes, encodedMsg, pos);
+ pos = addByteArray(byteEntryAttrLen, encodedMsg, pos);
+ pos = addByteArray(encodedEclIncludes, encodedMsg, pos);
+ return encodedMsg;
}
private byte[] encodeAttributes(
@@ -128,59 +366,13 @@
return byteBuilder.toByteArray();
}
- /**
- * Creates a new AddMessage.
- *
- * @param cn ChangeNumber of the add.
- * @param dn DN of the added entry.
- * @param uniqueId The Unique identifier of the added entry.
- * @param parentId The unique Id of the parent of the added
- * entry.
- * @param objectClasses objectclass of the added entry.
- * @param userAttributes user attributes of the added entry.
- * @param operationalAttributes operational attributes of the added entry.
- */
- public AddMsg(ChangeNumber cn,
- String dn,
- String uniqueId,
- String parentId,
- Map<ObjectClass, String> objectClasses,
- Map<AttributeType,List<Attribute>> userAttributes,
- Map<AttributeType,List<Attribute>> operationalAttributes)
+ private byte[] encodeAttributes(
+ Attribute objectClass,
+ Collection<Attribute> userAttributes,
+ Collection<Attribute> operationalAttributes)
{
- super (cn, uniqueId, dn);
- this.parentUniqueId = parentId;
-
- encodedAttributes = encodeAttributes(objectClasses,
- userAttributes, operationalAttributes);
- }
-
-
- /**
- * Creates a new AddMessage.
- *
- * @param cn ChangeNumber of the add.
- * @param dn DN of the added entry.
- * @param uniqueId The Unique identifier of the added entry.
- * @param parentId The unique Id of the parent of the added entry.
- * @param objectClass objectclass of the added entry.
- * @param userAttributes user attributes of the added entry.
- * @param operationalAttributes operational attributes of the added entry.
- */
- public AddMsg(ChangeNumber cn,
- String dn,
- String uniqueId,
- String parentId,
- Attribute objectClass,
- Collection<Attribute> userAttributes,
- Collection<Attribute> operationalAttributes)
- {
- super (cn, uniqueId, dn);
- this.parentUniqueId = parentId;
-
ByteStringBuilder byteBuilder = new ByteStringBuilder();
ASN1Writer writer = ASN1.getWriter(byteBuilder);
-
try
{
new LDAPAttribute(objectClass).write(writer);
@@ -196,25 +388,16 @@
{
// Do something
}
-
- encodedAttributes = byteBuilder.toByteArray();
+ return byteBuilder.toByteArray();
}
- /**
- * Creates a new Add message from a byte[].
- *
- * @param in The byte[] from which the operation must be read.
- * @throws DataFormatException The input byte[] is not a valid AddMsg
- * @throws UnsupportedEncodingException If UTF8 is not supported by the jvm
- */
- public AddMsg(byte[] in) throws DataFormatException,
- UnsupportedEncodingException
- {
- byte[] allowedPduTypes = new byte[2];
- allowedPduTypes[0] = MSG_TYPE_ADD;
- allowedPduTypes[1] = MSG_TYPE_ADD_V1;
- int pos = decodeHeader(allowedPduTypes, in);
+ // ============
+ // Msg decoding
+ // ============
+ private void decodeBody_V123(byte[] in, int pos)
+ throws DataFormatException, UnsupportedEncodingException
+ {
// read the parent unique Id
int length = getNextLength(in, pos);
if (length != 0)
@@ -228,7 +411,7 @@
pos += 1;
}
- // Read the attributes : all the remaining bytes
+ // Read/Don't decode attributes : all the remaining bytes
encodedAttributes = new byte[in.length-pos];
int i =0;
while (pos<in.length)
@@ -237,72 +420,63 @@
}
}
- /**
- * {@inheritDoc}
- */
- @Override
- public AddOperationBasis createOperation(
- InternalClientConnection connection, String newDn)
- throws LDAPException, ASN1Exception
+ private void decodeBody_V4(byte[] in, int pos)
+ throws DataFormatException, UnsupportedEncodingException
{
- ASN1Reader asn1Reader = ASN1.getReader(encodedAttributes);
- ArrayList<RawAttribute> attr = new ArrayList<RawAttribute>();
-
- while(asn1Reader.hasNextElement())
+ // read the parent unique Id
+ int length = getNextLength(in, pos);
+ if (length != 0)
{
- attr.add(LDAPAttribute.decode(asn1Reader));
- }
-
- AddOperationBasis add = new AddOperationBasis(connection,
- InternalClientConnection.nextOperationID(),
- InternalClientConnection.nextMessageID(), null,
- ByteString.valueOf(newDn), attr);
- AddContext ctx = new AddContext(getChangeNumber(), getUniqueId(),
- parentUniqueId);
- add.setAttachment(SYNCHROCONTEXT, ctx);
- return add;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public byte[] getBytes() throws UnsupportedEncodingException
- {
- if (bytes == null)
- {
- int length = encodedAttributes.length;
- byte[] byteParentId = null;
- if (parentUniqueId != null)
- {
- byteParentId = parentUniqueId.getBytes("UTF-8");
- length += byteParentId.length + 1;
- }
- else
- {
- length += 1;
- }
-
- /* encode the header in a byte[] large enough to also contain the mods */
- byte [] resultByteArray = encodeHeader(MSG_TYPE_ADD, length);
-
- int pos = resultByteArray.length - length;
-
- if (byteParentId != null)
- pos = addByteArray(byteParentId, resultByteArray, pos);
- else
- resultByteArray[pos++] = 0;
-
- /* put the attributes */
- for (int i=0; i<encodedAttributes.length; i++,pos++)
- {
- resultByteArray[pos] = encodedAttributes[i];
- }
- return resultByteArray;
+ parentUniqueId = new String(in, pos, length, "UTF-8");
+ pos += length + 1;
}
else
{
- return bytes;
+ parentUniqueId = null;
+ pos += 1;
+ }
+
+ // Read attr len
+ length = getNextLength(in, pos);
+ int attrLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+ pos += length + 1;
+
+ // Read/Don't decode attributes
+ this.encodedAttributes = new byte[attrLen];
+ try
+ {
+ System.arraycopy(in, pos, encodedAttributes, 0, attrLen);
+ } catch (IndexOutOfBoundsException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (ArrayStoreException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (NullPointerException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ }
+ pos += attrLen + 1;
+
+ // Read ecl attr len
+ length = getNextLength(in, pos);
+ int eclAttrLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+ pos += length + 1;
+
+ // Read/Don't decode entry attributes
+ encodedEclIncludes = new byte[eclAttrLen];
+ try
+ {
+ System.arraycopy(in, pos, encodedEclIncludes, 0, eclAttrLen);
+ } catch (IndexOutOfBoundsException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (ArrayStoreException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (NullPointerException e)
+ {
+ throw new DataFormatException(e.getMessage());
}
}
@@ -371,13 +545,7 @@
*/
public List<Attribute> getAttributes() throws LDAPException, ASN1Exception
{
- List<Attribute> attrs = new ArrayList<Attribute>();
-
- ASN1Reader reader = ASN1.getReader(encodedAttributes);
-
- while (reader.hasNextElement())
- attrs.add(LDAPAttribute.decode(reader).toAttribute());
-
+ List<Attribute> attrs = decodeAttributes(encodedAttributes);
return attrs;
}
@@ -406,42 +574,8 @@
@Override
public int size()
{
- return encodedAttributes.length + 40;
+ return encodedAttributes.length + + encodedEclIncludes.length
+ + headerSize();
}
- /**
- * {@inheritDoc}
- */
- @Override
- public byte[] getBytes_V1() throws UnsupportedEncodingException
- {
- int length = encodedAttributes.length;
- byte[] byteParentId = null;
- if (parentUniqueId != null)
- {
- byteParentId = parentUniqueId.getBytes("UTF-8");
- length += byteParentId.length + 1;
- }
- else
- {
- length += 1;
- }
-
- /* encode the header in a byte[] large enough to also contain the mods */
- byte [] resultByteArray = encodeHeader_V1(MSG_TYPE_ADD_V1, length);
-
- int pos = resultByteArray.length - length;
-
- if (byteParentId != null)
- pos = addByteArray(byteParentId, resultByteArray, pos);
- else
- resultByteArray[pos++] = 0;
-
- /* put the attributes */
- for (int i=0; i<encodedAttributes.length; i++,pos++)
- {
- resultByteArray[pos] = encodedAttributes[i];
- }
- return resultByteArray;
- }
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java b/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java
index 070c05b..fd1a111 100644
--- a/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java
@@ -80,7 +80,11 @@
byte[] allowedPduTypes = new byte[2];
allowedPduTypes[0] = MSG_TYPE_DELETE;
allowedPduTypes[1] = MSG_TYPE_DELETE_V1;
- decodeHeader(allowedPduTypes, in);
+ int pos = decodeHeader(allowedPduTypes, in);
+
+ // protocol version has been read as part of the header
+ if (protocolVersion >= 4)
+ decodeBody_V4(in, pos);
}
@@ -92,27 +96,83 @@
InternalClientConnection connection, String newDn)
{
DeleteOperationBasis del = new DeleteOperationBasis(connection,
- InternalClientConnection.nextOperationID(),
- InternalClientConnection.nextMessageID(), null,
+ InternalClientConnection.nextOperationID(),
+ InternalClientConnection.nextMessageID(), null,
ByteString.valueOf(newDn));
DeleteContext ctx = new DeleteContext(getChangeNumber(), getUniqueId());
del.setAttachment(SYNCHROCONTEXT, ctx);
return del;
}
+ // ============
+ // Msg encoding
+ // ============
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] getBytes_V1() throws UnsupportedEncodingException
+ {
+ return encodeHeader_V1(MSG_TYPE_DELETE_V1, 0);
+ }
+
/**
* {@inheritDoc}
*/
@Override
- public byte[] getBytes() throws UnsupportedEncodingException
+ public byte[] getBytes_V23() throws UnsupportedEncodingException
{
- if (bytes == null)
+ return encodeHeader(MSG_TYPE_DELETE, 0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes_V4() throws UnsupportedEncodingException
+ {
+ // Put together the different encoded pieces
+ int bodyLength = 0;
+
+ byte[] byteEntryAttrLen =
+ String.valueOf(encodedEclIncludes.length).getBytes("UTF-8");
+ bodyLength += byteEntryAttrLen.length + 1;
+ bodyLength += encodedEclIncludes.length + 1;
+
+ /* encode the header in a byte[] large enough to also contain the mods */
+ byte [] encodedMsg = encodeHeader(MSG_TYPE_DELETE, bodyLength);
+ int pos = encodedMsg.length - bodyLength;
+ pos = addByteArray(byteEntryAttrLen, encodedMsg, pos);
+ pos = addByteArray(encodedEclIncludes, encodedMsg, pos);
+ return encodedMsg;
+ }
+
+ // ============
+ // Msg decoding
+ // ============
+
+ private void decodeBody_V4(byte[] in, int pos)
+ throws DataFormatException, UnsupportedEncodingException
+ {
+ // Read ecl attr len
+ int length = getNextLength(in, pos);
+ int eclAttrLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+ pos += length + 1;
+
+ // Read/Don't decode entry attributes
+ encodedEclIncludes = new byte[eclAttrLen];
+ try
{
- return encodeHeader(MSG_TYPE_DELETE, 0);
- }
- else
+ System.arraycopy(in, pos, encodedEclIncludes, 0, eclAttrLen);
+ } catch (IndexOutOfBoundsException e)
{
- return bytes;
+ throw new DataFormatException(e.getMessage());
+ } catch (ArrayStoreException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (NullPointerException e)
+ {
+ throw new DataFormatException(e.getMessage());
}
}
@@ -151,16 +211,7 @@
@Override
public int size()
{
- // The DeleteMsg size is mostly dependent on the DN and should never
- // grow very large. It is therefore safe to assume an average of 40 bytes.
- return 40;
+ return encodedEclIncludes.length + headerSize();
}
- /**
- * {@inheritDoc}
- */
- public byte[] getBytes_V1() throws UnsupportedEncodingException
- {
- return encodeHeader_V1(MSG_TYPE_DELETE_V1, 0);
- }
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java b/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java
index 3927cfd..18e2914 100644
--- a/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/LDAPUpdateMsg.java
@@ -27,14 +27,25 @@
package org.opends.server.replication.protocol;
import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
import java.util.zip.DataFormatException;
+import org.opends.server.protocols.asn1.ASN1;
import org.opends.server.protocols.asn1.ASN1Exception;
+import org.opends.server.protocols.asn1.ASN1Reader;
+import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.ldap.LDAPAttribute;
import org.opends.server.replication.common.AssuredMode;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.ByteSequenceReader;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringBuilder;
import org.opends.server.types.LDAPException;
+import org.opends.server.types.RawAttribute;
import org.opends.server.types.operation.PostOperationAddOperation;
import org.opends.server.types.operation.PostOperationDeleteOperation;
import org.opends.server.types.operation.PostOperationModifyDNOperation;
@@ -63,6 +74,11 @@
protected byte[] bytes = null;
/**
+ * Encoded form of entry attributes.
+ */
+ protected byte[] encodedEclIncludes = new byte[0];
+
+ /**
* Creates a new UpdateMsg.
*/
public LDAPUpdateMsg()
@@ -164,21 +180,6 @@
}
/**
- * Do all the work necessary for the encoding.
- *
- * This is useful in case when one wants to perform this outside
- * of a synchronized portion of code.
- *
- * This method is not synchronized and therefore not MT safe.
- *
- * @throws UnsupportedEncodingException when encoding fails.
- */
- public void encode() throws UnsupportedEncodingException
- {
- bytes = getBytes();
- }
-
- /**
* Create and Operation from the message.
*
* @param conn connection to use when creating the message
@@ -208,6 +209,26 @@
InternalClientConnection conn, String newDn)
throws LDAPException, ASN1Exception, DataFormatException;
+
+ // ============
+ // Msg encoding
+ // ============
+
+ /**
+ * Do all the work necessary for the encoding.
+ *
+ * This is useful in case when one wants to perform this outside
+ * of a synchronized portion of code.
+ *
+ * This method is not synchronized and therefore not MT safe.
+ *
+ * @throws UnsupportedEncodingException when encoding fails.
+ */
+ public void encode() throws UnsupportedEncodingException
+ {
+ bytes = getBytes();
+ }
+
/**
* Encode the common header for all the UpdateMsg. This uses the current
* protocol version.
@@ -270,30 +291,6 @@
}
/**
- * {@inheritDoc}
- */
- @Override
- public byte[] getBytes(short reqProtocolVersion)
- throws UnsupportedEncodingException
- {
- if (reqProtocolVersion == ProtocolVersion.REPLICATION_PROTOCOL_V1)
- return getBytes_V1();
- else
- return getBytes();
- }
-
- /**
- * Get the byte array representation of this Message. This uses the version
- * 1 of the replication protocol (used for compatibility purpose).
- *
- * @return The byte array representation of this Message.
- *
- * @throws UnsupportedEncodingException When the encoding of the message
- * failed because the UTF-8 encoding is not supported.
- */
- public abstract byte[] getBytes_V1() throws UnsupportedEncodingException;
-
- /**
* Encode the common header for all the UpdateMessage. This uses the version
* 1 of the replication protocol (used for compatibility purpose).
*
@@ -345,6 +342,111 @@
}
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes()
+ throws UnsupportedEncodingException
+ {
+ // Encode in the current protocol version
+ if (bytes == null)
+ {
+ // this is the current version of the protocol
+ bytes = getBytes_V4();
+ }
+ return bytes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes(short reqProtocolVersion)
+ throws UnsupportedEncodingException
+ {
+ if (reqProtocolVersion == ProtocolVersion.REPLICATION_PROTOCOL_V1)
+ {
+ return getBytes_V1();
+ }
+ else if (reqProtocolVersion <= ProtocolVersion.REPLICATION_PROTOCOL_V3)
+ {
+ return getBytes_V23();
+ }
+ else
+ {
+ // Encode in the current protocol version
+ if (bytes == null)
+ {
+ // this is the current version of the protocol
+ bytes = getBytes_V4();
+ }
+ return bytes;
+ }
+ }
+
+ /**
+ * Get the byte array representation of this Message. This uses the version
+ * 1 of the replication protocol (used for compatibility purpose).
+ *
+ * @return The byte array representation of this Message.
+ *
+ * @throws UnsupportedEncodingException When the encoding of the message
+ * failed because the UTF-8 encoding is not supported.
+ */
+ public abstract byte[] getBytes_V1() throws UnsupportedEncodingException;
+
+ /**
+ * Get the byte array representation of this Message. This uses the version
+ * 2 of the replication protocol (used for compatibility purpose).
+ *
+ * @return The byte array representation of this Message.
+ *
+ * @throws UnsupportedEncodingException When the encoding of the message
+ * failed because the UTF-8 encoding is not supported.
+ */
+ public abstract byte[] getBytes_V23() throws UnsupportedEncodingException;
+
+
+ /**
+ * Get the byte array representation of this Message. This uses the version
+ * 4 of the replication protocol (used for compatibility purpose).
+ *
+ * @return The byte array representation of this Message.
+ *
+ * @throws UnsupportedEncodingException When the encoding of the message
+ * failed because the UTF-8 encoding is not supported.
+ */
+ public abstract byte[] getBytes_V4() throws UnsupportedEncodingException;
+
+
+ /**
+ * Encode a list of attributes.
+ */
+ static private byte[] encodeAttributes(List<Attribute> attributes)
+ {
+ if (attributes==null)
+ return new byte[0];
+ try
+ {
+ ByteStringBuilder byteBuilder = new ByteStringBuilder();
+ ASN1Writer writer = ASN1.getWriter(byteBuilder);
+ for (Attribute a : attributes)
+ {
+ new LDAPAttribute(a).write(writer);
+ }
+ return byteBuilder.toByteArray();
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ // ============
+ // Msg decoding
+ // ============
+
+ /**
* Decode the Header part of this Update Message, and check its type.
*
* @param types The allowed types of this Update Message.
@@ -353,82 +455,77 @@
* @throws DataFormatException if the encodedMsg does not contain a valid
* common header.
*/
- public int decodeHeader(byte[] types, byte[] encodedMsg)
+ public int decodeHeader(byte[] types, byte[] encodedMsg)
throws DataFormatException
- {
- /* The message header is stored in the form :
- * <operation type><protocol version><changenumber><dn><entryuuid><assured>
- * <assured mode> <safe data level>
- */
+ {
+ /* first byte is the type */
+ boolean foundMatchingType = false;
+ for (int i = 0; i < types.length; i++)
+ {
+ if (types[i] == encodedMsg[0])
+ {
+ foundMatchingType = true;
+ break;
+ }
+ }
+ if (!foundMatchingType)
+ throw new DataFormatException("byte[] is not a valid update msg: "
+ + encodedMsg[0]);
- /* first byte is the type */
- boolean foundMatchingType = false;
- for (int i = 0; i < types.length; i++)
- {
- if (types[i] == encodedMsg[0])
- {
- foundMatchingType = true;
- break;
- }
- }
- if (!foundMatchingType)
- throw new DataFormatException("byte[] is not a valid update msg: "
- + encodedMsg[0]);
+ /*
+ * For older protocol version PDUs, decode the matching version header
+ * instead.
+ */
+ if ((encodedMsg[0] == MSG_TYPE_ADD_V1) ||
+ (encodedMsg[0] == MSG_TYPE_DELETE_V1) ||
+ (encodedMsg[0] == MSG_TYPE_MODIFYDN_V1) ||
+ (encodedMsg[0] == MSG_TYPE_MODIFY_V1))
+ {
+ return decodeHeader_V1(encodedMsg);
+ }
- /*
- * For older protocol version PDUs, decode the matching version header
- * instead.
- */
- if ((encodedMsg[0] == MSG_TYPE_ADD_V1) ||
- (encodedMsg[0] == MSG_TYPE_DELETE_V1) ||
- (encodedMsg[0] == MSG_TYPE_MODIFYDN_V1) ||
- (encodedMsg[0] == MSG_TYPE_MODIFY_V1))
- {
- return decodeHeader_V1(encodedMsg);
- }
+ /* read the protocol version */
+ protocolVersion = (short)encodedMsg[1];
- /* read the protocol version */
- protocolVersion = (short)encodedMsg[1];
+ try
+ {
+ /* Read the changeNumber */
+ int pos = 2;
+ int length = getNextLength(encodedMsg, pos);
+ String changenumberStr = new String(encodedMsg, pos, length, "UTF-8");
+ pos += length + 1;
+ changeNumber = new ChangeNumber(changenumberStr);
- try
- {
- /* Read the changeNumber */
- int pos = 2;
- int length = getNextLength(encodedMsg, pos);
- String changenumberStr = new String(encodedMsg, pos, length, "UTF-8");
- pos += length + 1;
- changeNumber = new ChangeNumber(changenumberStr);
+ /* Read the dn */
+ length = getNextLength(encodedMsg, pos);
+ dn = new String(encodedMsg, pos, length, "UTF-8");
+ pos += length + 1;
- /* Read the dn */
- length = getNextLength(encodedMsg, pos);
- dn = new String(encodedMsg, pos, length, "UTF-8");
- pos += length + 1;
+ /* Read the entryuuid */
+ length = getNextLength(encodedMsg, pos);
+ uniqueId = new String(encodedMsg, pos, length, "UTF-8");
+ pos += length + 1;
- /* Read the entryuuid */
- length = getNextLength(encodedMsg, pos);
- uniqueId = new String(encodedMsg, pos, length, "UTF-8");
- pos += length + 1;
+ /* Read the assured information */
+ if (encodedMsg[pos++] == 1)
+ assuredFlag = true;
+ else
+ assuredFlag = false;
- /* Read the assured information */
- if (encodedMsg[pos++] == 1)
- assuredFlag = true;
- else
- assuredFlag = false;
+ /* Read the assured mode */
+ assuredMode = AssuredMode.valueOf(encodedMsg[pos++]);
- /* Read the assured mode */
- assuredMode = AssuredMode.valueOf(encodedMsg[pos++]);
+ /* Read the safe data level */
+ safeDataLevel = encodedMsg[pos++];
- /* Read the safe data level */
- safeDataLevel = encodedMsg[pos++];
-
- return pos;
- } catch (UnsupportedEncodingException e)
- {
- throw new DataFormatException("UTF-8 is not supported by this jvm.");
- } catch (IllegalArgumentException e)
- {
- throw new DataFormatException(e.getMessage());
- }
+ return pos;
+ } catch (UnsupportedEncodingException e)
+ {
+ throw new DataFormatException("UTF-8 is not supported by this jvm.");
+ } catch (IllegalArgumentException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ }
}
/**
@@ -493,4 +590,96 @@
* @return The number of bytes used by this message.
*/
public abstract int size();
+
+ /**
+ * Return the number of bytes used by the header.
+ * @return The number of bytes used by the header.
+ */
+ protected int headerSize()
+ {
+ return 100; // 100 let's assume header size is 100
+ }
+
+ /**
+ * Set a provided list of entry attributes.
+ * @param entryAttrs The provided list of entry attributes.
+ */
+ public void setEclIncludes(List<Attribute> entryAttrs)
+ {
+ this.encodedEclIncludes = encodeAttributes(entryAttrs);
+ }
+
+ /**
+ * Returns the list of entry attributes.
+ * @return The list of entry attributes.
+ */
+ public ArrayList<RawAttribute> getEclIncludes()
+ {
+ try
+ {
+ return decodeRawAttributes(this.encodedEclIncludes);
+ }
+ catch(Exception e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Decode a provided byte array as a list of RawAttribute.
+ * @param in The provided byte array.
+ * @return The list of Rawattribute objects.
+ * @throws LDAPException when it occurs.
+ * @throws ASN1Exception when it occurs.
+ */
+ public ArrayList<RawAttribute> decodeRawAttributes(byte[] in)
+ throws LDAPException, ASN1Exception
+ {
+ ArrayList<RawAttribute> rattr = new ArrayList<RawAttribute>();
+ try
+ {
+ ByteSequenceReader reader =
+ ByteString.wrap(in).asReader();
+ ASN1Reader asn1Reader = ASN1.getReader(reader);
+ // loop on attributes
+ while(asn1Reader.hasNextElement())
+ {
+ rattr.add(LDAPAttribute.decode(asn1Reader));
+ }
+ return rattr;
+ }
+ catch(Exception e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Decode a provided byte array as a list of Attribute.
+ * @param in The provided byte array.
+ * @return The list of Attribute objects.
+ * @throws LDAPException when it occurs.
+ * @throws ASN1Exception when it occurs.
+ */
+ public ArrayList<Attribute> decodeAttributes(byte[] in)
+ throws LDAPException, ASN1Exception
+ {
+ ArrayList<Attribute> lattr = new ArrayList<Attribute>();
+ try
+ {
+ ByteSequenceReader reader =
+ ByteString.wrap(in).asReader();
+ ASN1Reader asn1Reader = ASN1.getReader(reader);
+ // loop on attributes
+ while(asn1Reader.hasNextElement())
+ {
+ lattr.add(LDAPAttribute.decode(asn1Reader).toAttribute());
+ }
+ return lattr;
+ }
+ catch(Exception e)
+ {
+ return null;
+ }
+ }
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/ModifyCommonMsg.java b/opends/src/server/org/opends/server/replication/protocol/ModifyCommonMsg.java
index edf8877..b3d0e27 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ModifyCommonMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ModifyCommonMsg.java
@@ -24,6 +24,7 @@
*
* Copyright 2009 Sun Microsystems, Inc.
*/
+
package org.opends.server.replication.protocol;
import java.util.ArrayList;
@@ -43,6 +44,7 @@
import org.opends.server.types.ByteStringBuilder;
import org.opends.server.types.LDAPException;
import org.opends.server.types.Modification;
+import org.opends.server.types.RawModification;
/**
* This class holds every common code for the modify messages (mod, moddn).
@@ -97,26 +99,12 @@
*/
public void setMods(List<Modification> mods)
{
- encodedMods = modsToByte(mods);
+ encodedMods = encodeMods(mods);
}
- /**
- * Get the Modifications associated to the UpdateMsg to the provided value.
- * @throws LDAPException In case of LDAP decoding exception
- * @throws ASN1Exception In case of ASN1 decoding exception
- * @return the list of modifications
- */
- public List<Modification> getMods() throws ASN1Exception, LDAPException
- {
- List<Modification> mods = new ArrayList<Modification>();
-
- ASN1Reader reader = ASN1.getReader(encodedMods);
-
- while (reader.hasNextElement())
- mods.add((LDAPModification.decode(reader)).toModification());
-
- return mods;
- }
+ // ============
+ // Msg encoding
+ // ============
/**
* Encode an ArrayList of Modification into a byte[] suitable
@@ -125,7 +113,7 @@
* @param mods the ArrayList of Modification to be encoded.
* @return The encoded modifications.
*/
- protected byte[] modsToByte(List<Modification> mods)
+ protected byte[] encodeMods(List<Modification> mods)
{
if ((mods == null) || (mods.size() == 0))
return new byte[0];
@@ -161,8 +149,49 @@
}
}
}
-
return byteBuilder.toByteArray();
}
+ // ============
+ // Msg decoding
+ // ============
+
+ /**
+ * Decode mods from the provided byte array.
+ * @param in The provided byte array.
+ * @throws ASN1Exception when occurs.
+ * @throws LDAPException when occurs.
+ * @return The decoded mods.
+ */
+ protected List<Modification> decodeMods(byte[] in)
+ throws ASN1Exception, LDAPException
+ {
+ List<Modification> mods = new ArrayList<Modification>();
+ ASN1Reader reader = ASN1.getReader(in);
+ while (reader.hasNextElement())
+ {
+ mods.add((LDAPModification.decode(reader)).toModification());
+ }
+ return mods;
+ }
+
+ /**
+ * Decode raw mods from the provided byte array.
+ * @param in The provided byte array.
+ * @return The decoded mods.
+ * @throws ASN1Exception when occurs.
+ * @throws LDAPException when occurs.
+ */
+ protected ArrayList<RawModification> decodeRawMods(byte[] in)
+ throws LDAPException, ASN1Exception
+ {
+ ArrayList<RawModification> ldapmods = new ArrayList<RawModification>();
+ ASN1Reader asn1Reader = ASN1.getReader(in);
+ while(asn1Reader.hasNextElement())
+ {
+ ldapmods.add(LDAPModification.decode(asn1Reader));
+ }
+ return ldapmods;
+ }
+
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java b/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java
index 5beda7e..843c9e5 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ModifyDNMsg.java
@@ -33,11 +33,8 @@
import java.util.zip.DataFormatException;
import org.opends.server.core.ModifyDNOperationBasis;
-import org.opends.server.protocols.asn1.ASN1;
import org.opends.server.protocols.asn1.ASN1Exception;
-import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.internal.InternalClientConnection;
-import org.opends.server.protocols.ldap.LDAPModification;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.types.AbstractOperation;
import org.opends.server.types.ByteString;
@@ -68,7 +65,7 @@
super((OperationContext) operation.getAttachment(SYNCHROCONTEXT),
operation.getRawEntryDN().toString());
- encodedMods = modsToByte(operation.getModifications());
+ encodedMods = encodeMods(operation.getModifications());
ModifyDnContext ctx =
(ModifyDnContext) operation.getAttachment(SYNCHROCONTEXT);
@@ -130,7 +127,7 @@
{
this(dn, changeNumber, uid, newParentUid, deleteOldRdn, newSuperior,
newRDN);
- this.encodedMods = modsToByte(mods);
+ this.encodedMods = encodeMods(mods);
}
/**
@@ -143,11 +140,273 @@
public ModifyDNMsg(byte[] in) throws DataFormatException,
UnsupportedEncodingException
{
+ // Decode header
byte[] allowedPduTypes = new byte[2];
allowedPduTypes[0] = MSG_TYPE_MODIFYDN;
allowedPduTypes[1] = MSG_TYPE_MODIFYDN_V1;
int pos = decodeHeader(allowedPduTypes, in);
+ // protocol version has been read as part of the header
+ if (protocolVersion <= 3)
+ decodeBody_V123(in, pos);
+ else
+ {
+ decodeBody_V4(in, pos);
+ }
+
+ if (protocolVersion==ProtocolVersion.getCurrentVersion())
+ {
+ bytes = in;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public AbstractOperation createOperation(
+ InternalClientConnection connection, String newDn)
+ throws LDAPException, ASN1Exception
+ {
+ ModifyDNOperationBasis moddn = new ModifyDNOperationBasis(connection,
+ InternalClientConnection.nextOperationID(),
+ InternalClientConnection.nextMessageID(), null,
+ ByteString.valueOf(newDn), ByteString.valueOf(newRDN),
+ deleteOldRdn,
+ (newSuperior == null ? null : ByteString.valueOf(newSuperior)));
+
+ for (Modification mod : decodeMods(encodedMods))
+ {
+ moddn.addModification(mod);
+ }
+
+ ModifyDnContext ctx = new ModifyDnContext(getChangeNumber(), getUniqueId(),
+ newSuperiorId);
+ moddn.setAttachment(SYNCHROCONTEXT, ctx);
+ return moddn;
+ }
+
+ // ============
+ // Msg Encoding
+ // ============
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes_V1() throws UnsupportedEncodingException
+ {
+ byte[] byteNewRdn = newRDN.getBytes("UTF-8");
+ byte[] byteNewSuperior = null;
+ byte[] byteNewSuperiorId = null;
+
+ // calculate the length necessary to encode the parameters
+ int bodyLength = byteNewRdn.length + 1 + 1;
+ if (newSuperior != null)
+ {
+ byteNewSuperior = newSuperior.getBytes("UTF-8");
+ bodyLength += byteNewSuperior.length + 1;
+ }
+ else
+ bodyLength += 1;
+
+ if (newSuperiorId != null)
+ {
+ byteNewSuperiorId = newSuperiorId.getBytes("UTF-8");
+ bodyLength += byteNewSuperiorId.length + 1;
+ }
+ else
+ bodyLength += 1;
+
+ byte[] encodedMsg = encodeHeader_V1(MSG_TYPE_MODIFYDN_V1, bodyLength);
+ int pos = encodedMsg.length - bodyLength;
+
+ /* put the new RDN and a terminating 0 */
+ pos = addByteArray(byteNewRdn, encodedMsg, pos);
+
+ /* put the newsuperior and a terminating 0 */
+ if (newSuperior != null)
+ {
+ pos = addByteArray(byteNewSuperior, encodedMsg, pos);
+ }
+ else
+ encodedMsg[pos++] = 0;
+
+ /* put the newsuperiorId and a terminating 0 */
+ if (newSuperiorId != null)
+ {
+ pos = addByteArray(byteNewSuperiorId, encodedMsg, pos);
+ }
+ else
+ encodedMsg[pos++] = 0;
+
+ /* put the deleteoldrdn flag */
+ if (deleteOldRdn)
+ encodedMsg[pos++] = 1;
+ else
+ encodedMsg[pos++] = 0;
+
+ return encodedMsg;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes_V23() throws UnsupportedEncodingException
+ {
+ // Encoding V2 / V3
+
+ byte[] byteNewRdn = newRDN.getBytes("UTF-8");
+ byte[] byteNewSuperior = null;
+ byte[] byteNewSuperiorId = null;
+
+ // calculate the length necessary to encode the parameters
+ int length = byteNewRdn.length + 1 + 1;
+ if (newSuperior != null)
+ {
+ byteNewSuperior = newSuperior.getBytes("UTF-8");
+ length += byteNewSuperior.length + 1;
+ }
+ else
+ length += 1;
+
+ if (newSuperiorId != null)
+ {
+ byteNewSuperiorId = newSuperiorId.getBytes("UTF-8");
+ length += byteNewSuperiorId.length + 1;
+ }
+ else
+ length += 1;
+
+ length += encodedMods.length + 1;
+
+ /* encode the header in a byte[] large enough to also contain mods.. */
+ byte[] encodedMsg = encodeHeader(MSG_TYPE_MODIFYDN, length);
+ int pos = encodedMsg.length - length;
+
+ /* put the new RDN and a terminating 0 */
+ pos = addByteArray(byteNewRdn, encodedMsg, pos);
+
+ /* put the newsuperior and a terminating 0 */
+ if (newSuperior != null)
+ {
+ pos = addByteArray(byteNewSuperior, encodedMsg, pos);
+ }
+ else
+ encodedMsg[pos++] = 0;
+
+ /* put the newsuperiorId and a terminating 0 */
+ if (newSuperiorId != null)
+ {
+ pos = addByteArray(byteNewSuperiorId, encodedMsg, pos);
+ }
+ else
+ encodedMsg[pos++] = 0;
+
+ /* put the deleteoldrdn flag */
+ if (deleteOldRdn)
+ encodedMsg[pos++] = 1;
+ else
+ encodedMsg[pos++] = 0;
+
+ /* add the mods */
+ if (encodedMods.length > 0)
+ {
+ pos = encodedMsg.length - (encodedMods.length + 1);
+ addByteArray(encodedMods, encodedMsg, pos);
+ }
+ else
+ encodedMsg[pos++] = 0;
+
+ return encodedMsg;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] getBytes_V4() throws UnsupportedEncodingException
+ {
+ int bodyLength = 0;
+ byte[] byteNewSuperior = null;
+ byte[] byteNewSuperiorId = null;
+
+ // calculate the length necessary to encode the parameters
+
+ byte[] byteNewRdn = newRDN.getBytes("UTF-8");
+ bodyLength = byteNewRdn.length + 1 + 1;
+
+ if (newSuperior != null)
+ {
+ byteNewSuperior = newSuperior.getBytes("UTF-8");
+ bodyLength += byteNewSuperior.length + 1;
+ }
+ else
+ bodyLength += 1;
+
+ if (newSuperiorId != null)
+ {
+ byteNewSuperiorId = newSuperiorId.getBytes("UTF-8");
+ bodyLength += byteNewSuperiorId.length + 1;
+ }
+ else
+ bodyLength += 1;
+
+ byte[] byteModsLen =
+ String.valueOf(encodedMods.length).getBytes("UTF-8");
+ bodyLength += byteModsLen.length + 1;
+ bodyLength += encodedMods.length + 1;
+
+ byte[] byteEntryAttrLen =
+ String.valueOf(encodedEclIncludes.length).getBytes("UTF-8");
+ bodyLength += byteEntryAttrLen.length + 1;
+ bodyLength += encodedEclIncludes.length + 1;
+
+ /* encode the header in a byte[] large enough to also contain mods.. */
+ byte[] encodedMsg = encodeHeader(MSG_TYPE_MODIFYDN, bodyLength);
+
+ int pos = encodedMsg.length - bodyLength;
+
+ /* put the new RDN and a terminating 0 */
+ pos = addByteArray(byteNewRdn, encodedMsg, pos);
+ /* put the newsuperior and a terminating 0 */
+ if (newSuperior != null)
+ {
+ pos = addByteArray(byteNewSuperior, encodedMsg, pos);
+ }
+ else
+ encodedMsg[pos++] = 0;
+ /* put the newsuperiorId and a terminating 0 */
+ if (newSuperiorId != null)
+ {
+ pos = addByteArray(byteNewSuperiorId, encodedMsg, pos);
+ }
+ else
+ encodedMsg[pos++] = 0;
+
+ /* put the deleteoldrdn flag */
+ if (deleteOldRdn)
+ encodedMsg[pos++] = 1;
+ else
+ encodedMsg[pos++] = 0;
+
+ pos = addByteArray(byteModsLen, encodedMsg, pos);
+ pos = addByteArray(encodedMods, encodedMsg, pos);
+
+ pos = addByteArray(byteEntryAttrLen, encodedMsg, pos);
+ pos = addByteArray(encodedEclIncludes, encodedMsg, pos);
+
+ return encodedMsg;
+ }
+
+ // ============
+ // Msg decoding
+ // ============
+
+ private void decodeBody_V123(byte[] in, int pos)
+ throws DataFormatException, UnsupportedEncodingException
+ {
/* read the newRDN
* first calculate the length then construct the string
*/
@@ -208,102 +467,84 @@
}
}
- /**
- * {@inheritDoc}
- */
- @Override
- public AbstractOperation createOperation(
- InternalClientConnection connection, String newDn)
- throws LDAPException, ASN1Exception
+ private void decodeBody_V4(byte[] in, int pos)
+ throws DataFormatException, UnsupportedEncodingException
{
- ModifyDNOperationBasis moddn = new ModifyDNOperationBasis(connection,
- InternalClientConnection.nextOperationID(),
- InternalClientConnection.nextMessageID(), null,
- ByteString.valueOf(newDn), ByteString.valueOf(newRDN),
- deleteOldRdn,
- (newSuperior == null ? null : ByteString.valueOf(newSuperior)));
+ /* read the newRDN
+ * first calculate the length then construct the string
+ */
+ int length = getNextLength(in, pos);
+ newRDN = new String(in, pos, length, "UTF-8");
+ pos += length + 1;
- ASN1Reader asn1Reader = ASN1.getReader(encodedMods);
- while (asn1Reader.hasNextElement())
- {
- moddn.addModification(LDAPModification.decode(asn1Reader)
- .toModification());
- }
-
- ModifyDnContext ctx = new ModifyDnContext(getChangeNumber(), getUniqueId(),
- newSuperiorId);
- moddn.setAttachment(SYNCHROCONTEXT, ctx);
- return moddn;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public byte[] getBytes() throws UnsupportedEncodingException
- {
- byte[] byteNewRdn = newRDN.getBytes("UTF-8");
- byte[] byteNewSuperior = null;
- byte[] byteNewSuperiorId = null;
-
- // calculate the length necessary to encode the parameters
- int length = byteNewRdn.length + 1 + 1;
- if (newSuperior != null)
- {
- byteNewSuperior = newSuperior.getBytes("UTF-8");
- length += byteNewSuperior.length + 1;
- }
+ /* read the newSuperior
+ * first calculate the length then construct the string
+ */
+ length = getNextLength(in, pos);
+ if (length != 0)
+ newSuperior = new String(in, pos, length, "UTF-8");
else
- length += 1;
+ newSuperior = null;
+ pos += length + 1;
- if (newSuperiorId != null)
+ /* read the new parent Id
+ */
+ length = getNextLength(in, pos);
+ if (length != 0)
+ newSuperiorId = new String(in, pos, length, "UTF-8");
+ else
+ newSuperiorId = null;
+ pos += length + 1;
+
+ /* get the deleteoldrdn flag */
+ if (in[pos] == 0)
+ deleteOldRdn = false;
+ else
+ deleteOldRdn = true;
+ pos++;
+
+ // Read mods len
+ length = getNextLength(in, pos);
+ int modsLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+ pos += length + 1;
+
+ // Read/Don't decode attributes
+ this.encodedMods = new byte[modsLen];
+ try
{
- byteNewSuperiorId = newSuperiorId.getBytes("UTF-8");
- length += byteNewSuperiorId.length + 1;
- }
- else
- length += 1;
-
- length += encodedMods.length + 1;
-
- byte[] resultByteArray = encodeHeader(MSG_TYPE_MODIFYDN, length);
- int pos = resultByteArray.length - length;
-
- /* put the new RDN and a terminating 0 */
- pos = addByteArray(byteNewRdn, resultByteArray, pos);
-
- /* put the newsuperior and a terminating 0 */
- if (newSuperior != null)
+ System.arraycopy(in, pos, encodedMods, 0, modsLen);
+ } catch (IndexOutOfBoundsException e)
{
- pos = addByteArray(byteNewSuperior, resultByteArray, pos);
- }
- else
- resultByteArray[pos++] = 0;
-
- /* put the newsuperiorId and a terminating 0 */
- if (newSuperiorId != null)
+ throw new DataFormatException(e.getMessage());
+ } catch (ArrayStoreException e)
{
- pos = addByteArray(byteNewSuperiorId, resultByteArray, pos);
- }
- else
- resultByteArray[pos++] = 0;
-
- /* put the deleteoldrdn flag */
- if (deleteOldRdn)
- resultByteArray[pos++] = 1;
- else
- resultByteArray[pos++] = 0;
-
- /* add the mods */
- if (encodedMods.length > 0)
+ throw new DataFormatException(e.getMessage());
+ } catch (NullPointerException e)
{
- pos = resultByteArray.length - (encodedMods.length + 1);
- addByteArray(encodedMods, resultByteArray, pos);
+ throw new DataFormatException(e.getMessage());
}
- else
- resultByteArray[pos++] = 0;
+ pos += modsLen + 1;
- return resultByteArray;
+ // Read ecl attr len
+ length = getNextLength(in, pos);
+ int eclAttrLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+ pos += length + 1;
+
+ // Read/Don't decode entry attributes
+ encodedEclIncludes = new byte[eclAttrLen];
+ try
+ {
+ System.arraycopy(in, pos, encodedEclIncludes, 0, eclAttrLen);
+ } catch (IndexOutOfBoundsException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (ArrayStoreException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (NullPointerException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ }
}
/**
@@ -526,74 +767,8 @@
@Override
public int size()
{
- // The MODDN message size are mainly dependent on the
- // size of the DN. let's assume that they average on 100 bytes
- return encodedMods.length + 100;
+ return encodedMods.length + newRDN.length() +
+ encodedEclIncludes.length + headerSize();
}
- /**
- * {@inheritDoc}
- */
- @Override
- public byte[] getBytes_V1() throws UnsupportedEncodingException
- {
- if (bytes == null)
- {
- byte[] byteNewRdn = newRDN.getBytes("UTF-8");
- byte[] byteNewSuperior = null;
- byte[] byteNewSuperiorId = null;
-
- // calculate the length necessary to encode the parameters
- int length = byteNewRdn.length + 1 + 1;
- if (newSuperior != null)
- {
- byteNewSuperior = newSuperior.getBytes("UTF-8");
- length += byteNewSuperior.length + 1;
- }
- else
- length += 1;
-
- if (newSuperiorId != null)
- {
- byteNewSuperiorId = newSuperiorId.getBytes("UTF-8");
- length += byteNewSuperiorId.length + 1;
- }
- else
- length += 1;
-
- byte[] resultByteArray = encodeHeader_V1(MSG_TYPE_MODIFYDN_V1, length);
- int pos = resultByteArray.length - length;
-
- /* put the new RDN and a terminating 0 */
- pos = addByteArray(byteNewRdn, resultByteArray, pos);
-
- /* put the newsuperior and a terminating 0 */
- if (newSuperior != null)
- {
- pos = addByteArray(byteNewSuperior, resultByteArray, pos);
- }
- else
- resultByteArray[pos++] = 0;
-
- /* put the newsuperiorId and a terminating 0 */
- if (newSuperiorId != null)
- {
- pos = addByteArray(byteNewSuperiorId, resultByteArray, pos);
- }
- else
- resultByteArray[pos++] = 0;
-
- /* put the deleteoldrdn flag */
- if (deleteOldRdn)
- resultByteArray[pos++] = 1;
- else
- resultByteArray[pos++] = 0;
-
- return resultByteArray;
- }
- else
- {
- return bytes;
- }
- }
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java b/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
index 2b50944..099e215 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
@@ -28,27 +28,23 @@
import static org.opends.server.replication.protocol.OperationContext.*;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.DataFormatException;
+
import org.opends.server.core.ModifyOperationBasis;
-import org.opends.server.protocols.ldap.LDAPModification;
-import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.asn1.ASN1Exception;
-import org.opends.server.protocols.asn1.ASN1Reader;
-import org.opends.server.protocols.asn1.ASN1;
+import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.common.ChangeNumber;
-import org.opends.server.types.*;
import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.ByteString;
import org.opends.server.types.DN;
import org.opends.server.types.LDAPException;
import org.opends.server.types.Modification;
import org.opends.server.types.RawModification;
import org.opends.server.types.operation.PostOperationModifyOperation;
-
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.zip.DataFormatException;
-
/**
* Message used to send Modify information.
*/
@@ -63,7 +59,7 @@
{
super((OperationContext) op.getAttachment(OperationContext.SYNCHROCONTEXT),
op.getRawEntryDN().toString());
- encodedMods = modsToByte(op.getModifications());
+ encodedMods = encodeMods(op.getModifications());
}
/**
@@ -80,7 +76,7 @@
{
super(new ModifyContext(changeNumber, entryuuid),
dn.toNormalizedString());
- this.encodedMods = modsToByte(mods);
+ this.encodedMods = encodeMods(mods);
}
/**
@@ -93,30 +89,23 @@
public ModifyMsg(byte[] in) throws DataFormatException,
UnsupportedEncodingException
{
- bytes = in;
-
// Decode header
byte[] allowedPduTypes = new byte[2];
allowedPduTypes[0] = MSG_TYPE_MODIFY;
allowedPduTypes[1] = MSG_TYPE_MODIFY_V1;
int pos = decodeHeader(allowedPduTypes, in);
- /* Read the mods : all the remaining bytes but the terminating 0 */
- int length = in.length - pos - 1;
- encodedMods = new byte[length];
- try
+ // protocol version has been read as part of the header
+ if (protocolVersion <= 3)
+ decodeBody_V123(in, pos);
+ else
+ decodeBody_V4(in, pos);
+
+ if (protocolVersion==ProtocolVersion.getCurrentVersion())
{
- System.arraycopy(in, pos, encodedMods, 0, length);
- } catch (IndexOutOfBoundsException e)
- {
- throw new DataFormatException(e.getMessage());
- } catch (ArrayStoreException e)
- {
- throw new DataFormatException(e.getMessage());
- } catch (NullPointerException e)
- {
- throw new DataFormatException(e.getMessage());
+ bytes = in;
}
+
}
/**
@@ -132,6 +121,8 @@
UnsupportedEncodingException
{
ModifyMsg msg = new ModifyMsg(in);
+
+ // bytes is only for current version (of the protocol) bytes !
msg.bytes = null;
return msg;
@@ -141,53 +132,26 @@
* {@inheritDoc}
*/
@Override
- public byte[] getBytes() throws UnsupportedEncodingException
- {
- if (bytes == null)
- {
- /* encode the header in a byte[] large enough to also contain the mods */
- byte[] mybytes = encodeHeader(MSG_TYPE_MODIFY, encodedMods.length + 1);
-
- /* add the mods */
- int pos = mybytes.length - (encodedMods.length + 1);
- addByteArray(encodedMods, mybytes, pos);
-
- return mybytes;
- }
- else
- {
- return bytes;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public AbstractOperation createOperation(InternalClientConnection connection,
- String newDn)
- throws LDAPException, ASN1Exception, DataFormatException
+ String newDn)
+ throws LDAPException, ASN1Exception, DataFormatException
{
if (newDn == null)
newDn = getDn();
- ArrayList<RawModification> ldapmods = new ArrayList<RawModification>();
-
- ASN1Reader asn1Reader = ASN1.getReader(encodedMods);
- while(asn1Reader.hasNextElement())
- {
- ldapmods.add(LDAPModification.decode(asn1Reader));
- }
+ ArrayList<RawModification> ldapmods = decodeRawMods(encodedMods);
ModifyOperationBasis mod = new ModifyOperationBasis(connection,
- InternalClientConnection.nextOperationID(),
- InternalClientConnection.nextMessageID(), null,
+ InternalClientConnection.nextOperationID(),
+ InternalClientConnection.nextMessageID(), null,
ByteString.valueOf(newDn), ldapmods);
ModifyContext ctx = new ModifyContext(getChangeNumber(), getUniqueId());
mod.setAttachment(SYNCHROCONTEXT, ctx);
return mod;
+
}
+
/**
* {@inheritDoc}
*/
@@ -224,11 +188,15 @@
public int size()
{
// The ModifyMsg can be very large when added or deleted attribute
- // values are very large. We therefore need to count the
- // whole encoded msg.
- return encodedMods.length + 100; // 100 let's assume header size is 100
+ // values are very large.
+ // We therefore need to count the whole encoded msg.
+ return encodedMods.length + encodedEclIncludes.length + headerSize();
}
+ // ============
+ // Msg Encoding
+ // ============
+
/**
* {@inheritDoc}
*/
@@ -244,4 +212,121 @@
return encodedMsg;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] getBytes_V23() throws UnsupportedEncodingException
+ {
+ // Encoding V2 / V3
+
+ /* encode the header in a byte[] large enough to also contain mods */
+ byte[] encodedMsg = encodeHeader(MSG_TYPE_MODIFY, encodedMods.length + 1);
+
+ /* add the mods */
+ int pos = encodedMsg.length - (encodedMods.length + 1);
+ addByteArray(encodedMods, encodedMsg, pos);
+
+ return encodedMsg;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] getBytes_V4() throws UnsupportedEncodingException
+ {
+ int bodyLength = 0;
+ byte[] byteModsLen =
+ String.valueOf(encodedMods.length).getBytes("UTF-8");
+ bodyLength += byteModsLen.length + 1;
+ bodyLength += encodedMods.length + 1;
+
+ byte[] byteEntryAttrLen =
+ String.valueOf(encodedEclIncludes.length).getBytes("UTF-8");
+ bodyLength += byteEntryAttrLen.length + 1;
+ bodyLength += encodedEclIncludes.length + 1;
+
+ /* encode the header in a byte[] large enough to also contain the mods */
+ byte [] encodedMsg = encodeHeader(MSG_TYPE_MODIFY, bodyLength);
+
+ int pos = encodedMsg.length - bodyLength;
+ pos = addByteArray(byteModsLen, encodedMsg, pos);
+ pos = addByteArray(encodedMods, encodedMsg, pos);
+ pos = addByteArray(byteEntryAttrLen, encodedMsg, pos);
+ pos = addByteArray(encodedEclIncludes, encodedMsg, pos);
+ return encodedMsg;
+ }
+
+ // ============
+ // Msg decoding
+ // ============
+
+ private void decodeBody_V123(byte[] in, int pos)
+ throws DataFormatException
+ {
+ // Read and store the mods, in encoded form
+ // all the remaining bytes but the terminating 0 */
+ int length = in.length - pos - 1;
+ encodedMods = new byte[length];
+ try
+ {
+ System.arraycopy(in, pos, encodedMods, 0, length);
+ } catch (IndexOutOfBoundsException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (ArrayStoreException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (NullPointerException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ }
+ }
+
+ private void decodeBody_V4(byte[] in, int pos)
+ throws DataFormatException, UnsupportedEncodingException
+ {
+ // Read mods len
+ int length = getNextLength(in, pos);
+ int modsLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+ pos += length + 1;
+
+ // Read/Don't decode mods
+ this.encodedMods = new byte[modsLen];
+ try
+ {
+ System.arraycopy(in, pos, encodedMods, 0, modsLen);
+ } catch (IndexOutOfBoundsException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (ArrayStoreException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (NullPointerException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ }
+ pos += modsLen + 1;
+
+ // Read ecl attr len
+ length = getNextLength(in, pos);
+ int eclAttrLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+ pos += length + 1;
+
+ // Read/Don't decode entry attributes
+ encodedEclIncludes = new byte[eclAttrLen];
+ try
+ {
+ System.arraycopy(in, pos, encodedEclIncludes, 0, eclAttrLen);
+ } catch (IndexOutOfBoundsException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (ArrayStoreException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ } catch (NullPointerException e)
+ {
+ throw new DataFormatException(e.getMessage());
+ }
+ }
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/ProtocolVersion.java b/opends/src/server/org/opends/server/replication/protocol/ProtocolVersion.java
index 042f5a2..997267d 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ProtocolVersion.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ProtocolVersion.java
@@ -43,15 +43,24 @@
public static final short REPLICATION_PROTOCOL_V1_REAL = 49;
/**
* The constant for the second version of the replication protocol.
+ * Add fields in the header for assured replication.
*/
public static final short REPLICATION_PROTOCOL_V2 = 2;
/**
* The constant for the 3rd version of the replication protocol.
+ * Add messages for remote ECL : not used as of today.
*/
public static final short REPLICATION_PROTOCOL_V3 = 3;
/**
+ * 4th version of the replication protocol.
+ * Add to the body of the ADD/MOD/MODDN/DEL msgs, a list of attribute for
+ * ECL entry attributes.
+ */
+ public static final short REPLICATION_PROTOCOL_V4 = 4;
+
+ /**
* The replication protocol version used by the instance of RS/DS in this VM.
*/
private static short currentVersion = -1;
@@ -86,7 +95,7 @@
*/
public static void resetCurrentVersion()
{
- currentVersion = REPLICATION_PROTOCOL_V3;
+ currentVersion = REPLICATION_PROTOCOL_V4;
}
/**
diff --git a/opends/src/server/org/opends/server/replication/protocol/ReplicationMsg.java b/opends/src/server/org/opends/server/replication/protocol/ReplicationMsg.java
index 0feb441..466d884 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ReplicationMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ReplicationMsg.java
@@ -209,7 +209,7 @@
msg = new WindowProbeMsg(buffer);
break;
case MSG_TYPE_TOPOLOGY:
- msg = new TopologyMsg(buffer);
+ msg = new TopologyMsg(buffer, version);
break;
case MSG_TYPE_REPL_SERVER_MONITOR_REQUEST:
msg = new MonitorRequestMsg(buffer);
@@ -218,7 +218,7 @@
msg = new MonitorMsg(buffer, version);
break;
case MSG_TYPE_START_SESSION:
- msg = new StartSessionMsg(buffer);
+ msg = new StartSessionMsg(buffer, version);
break;
case MSG_TYPE_CHANGE_STATUS:
msg = new ChangeStatusMsg(buffer);
diff --git a/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java b/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java
index 5925ee5..3f22529 100644
--- a/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/StartSessionMsg.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2008 Sun Microsystems, Inc.
+ * Copyright 2008-2009 Sun Microsystems, Inc.
*/
package org.opends.server.replication.protocol;
@@ -30,10 +30,19 @@
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.zip.DataFormatException;
+
+import org.opends.server.protocols.asn1.ASN1;
+import org.opends.server.protocols.asn1.ASN1Reader;
+import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.replication.common.AssuredMode;
import org.opends.server.replication.common.ServerStatus;
+import org.opends.server.types.ByteSequenceReader;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringBuilder;
/**
* This message is used by DS to confirm a RS he wants to connect to him (open
@@ -62,14 +71,271 @@
// DS safe data level (relevant if assured mode is safe data)
private byte safeDataLevel = (byte) 1;
+ private Set<String> eclIncludes = new HashSet<String>();
+
+ /**
+ * The protocolVersion that should be used when serializing this message.
+ */
+ private final short protocolVersion;
+
/**
* Creates a new StartSessionMsg message from its encoded form.
*
* @param in The byte array containing the encoded form of the message.
+ * @param version The protocol version to use to decode the msg.
* @throws java.util.zip.DataFormatException If the byte array does not
* contain a valid encoded form of the message.
*/
- public StartSessionMsg(byte[] in) throws DataFormatException
+ public StartSessionMsg(byte[] in, short version) throws DataFormatException
+ {
+ protocolVersion = ProtocolVersion.getCurrentVersion();
+ if (version <= ProtocolVersion.REPLICATION_PROTOCOL_V3)
+ {
+ decode_V23(in);
+ }
+ else
+ {
+ decode_V4(in);
+ }
+ }
+
+ /**
+ * Creates a new StartSessionMsg message from its encoded form.
+ *
+ * Creates a new message with the given required parameters.
+ * @param status Status we are starting with
+ * @param referralsURLs Referrals URLs to be used by peer DSs
+ * @param assuredFlag If assured mode is enabled or not
+ * @param assuredMode Assured type
+ * @param safeDataLevel Assured mode safe data level
+ * @param replicationProtocol The protocol version to use.
+ */
+ public StartSessionMsg(ServerStatus status, List<String> referralsURLs,
+ boolean assuredFlag, AssuredMode assuredMode, byte safeDataLevel,
+ short replicationProtocol)
+ {
+ this.referralsURLs = referralsURLs;
+ this.status = status;
+ this.assuredFlag = assuredFlag;
+ this.assuredMode = assuredMode;
+ this.safeDataLevel = safeDataLevel;
+ this.protocolVersion = replicationProtocol;
+ }
+
+ /**
+ * Creates a new message with the given required parameters.
+ * @param status Status we are starting with
+ * @param referralsURLs Referrals URLs to be used by peer DSs
+ * @param assuredFlag If assured mode is enabled or not
+ * @param assuredMode Assured type
+ * @param safeDataLevel Assured mode safe data level
+ */
+ public StartSessionMsg(ServerStatus status, List<String> referralsURLs,
+ boolean assuredFlag, AssuredMode assuredMode, byte safeDataLevel)
+ {
+ this.referralsURLs = referralsURLs;
+ this.status = status;
+ this.assuredFlag = assuredFlag;
+ this.assuredMode = assuredMode;
+ this.safeDataLevel = safeDataLevel;
+ this.protocolVersion = ProtocolVersion.getCurrentVersion();
+ }
+
+ /**
+ * Creates a new message with the given required parameters.
+ * Assured mode is false.
+ * @param status Status we are starting with
+ * @param referralsURLs Referrals URLs to be used by peer DSs
+ */
+ public StartSessionMsg(ServerStatus status, List<String> referralsURLs)
+ {
+ this.referralsURLs = referralsURLs;
+ this.status = status;
+ this.assuredFlag = false;
+ this.protocolVersion = ProtocolVersion.getCurrentVersion();
+ }
+
+ /**
+ * Creates a new message with the given required parameters.
+ * Assured mode is false.
+ * @param status Status we are starting with
+ * @param referralsURLs Referrals URLs to be used by peer DSs
+ * @param replicationProtocol The requested protocol version.
+ */
+ public StartSessionMsg(ServerStatus status, List<String> referralsURLs,
+ short replicationProtocol)
+ {
+ this.referralsURLs = referralsURLs;
+ this.status = status;
+ this.assuredFlag = false;
+ this.protocolVersion = replicationProtocol;
+ }
+
+ // ============
+ // Msg encoding
+ // ============
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes()
+ throws UnsupportedEncodingException
+ {
+ if (protocolVersion <= ProtocolVersion.REPLICATION_PROTOCOL_V3)
+ {
+ return getBytes_V23();
+ }
+ else
+ {
+ return getBytes_V4();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes(short reqProtocolVersion)
+ throws UnsupportedEncodingException
+ {
+ if (reqProtocolVersion <= ProtocolVersion.REPLICATION_PROTOCOL_V3)
+ {
+ return getBytes_V23();
+ }
+ else
+ {
+ return getBytes_V4();
+ }
+ }
+
+ private byte[] getBytes_V4()
+ {
+ try
+ {
+ ByteStringBuilder byteBuilder = new ByteStringBuilder();
+ ASN1Writer writer = ASN1.getWriter(byteBuilder);
+
+ byteBuilder.append(MSG_TYPE_START_SESSION);
+ byteBuilder.append(status.getValue());
+ byteBuilder.append(assuredFlag ? (byte) 1 : (byte) 0);
+ byteBuilder.append(assuredMode.getValue());
+ byteBuilder.append(safeDataLevel);
+
+ writer.writeStartSequence();
+ for (String url : referralsURLs)
+ writer.writeOctetString(url);
+ writer.writeEndSequence();
+
+ writer.writeStartSequence();
+ for (String attrDef : eclIncludes)
+ writer.writeOctetString(attrDef);
+ writer.writeEndSequence();
+
+ return byteBuilder.toByteArray();
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ private byte[] getBytes_V23()
+ {
+ /*
+ * The message is stored in the form:
+ * <message type><status><assured flag><assured mode><safe data level>
+ * <list of referrals urls>
+ * (each referral url terminates with 0)
+ */
+
+ try
+ {
+ ByteArrayOutputStream oStream = new ByteArrayOutputStream();
+
+ /* Put the message type */
+ oStream.write(MSG_TYPE_START_SESSION);
+
+ // Put the status
+ oStream.write(status.getValue());
+
+ // Put the assured flag
+ oStream.write(assuredFlag ? (byte) 1 : (byte) 0);
+
+ // Put assured mode
+ oStream.write(assuredMode.getValue());
+
+ // Put safe data level
+ oStream.write(safeDataLevel);
+
+ // Put the referrals URLs
+ if (referralsURLs.size() >= 1)
+ {
+ for (String url : referralsURLs)
+ {
+ byte[] byteArrayURL = url.getBytes("UTF-8");
+ oStream.write(byteArrayURL);
+ oStream.write(0);
+ }
+ }
+ return oStream.toByteArray();
+ } catch (IOException e)
+ {
+ // never happens
+ return null;
+ }
+ }
+
+ // ============
+ // Msg decoding
+ // ============
+
+ private void decode_V4(byte[] in)
+ throws DataFormatException
+ {
+ ByteSequenceReader reader = ByteString.wrap(in).asReader();
+ try
+ {
+ if (reader.get() != MSG_TYPE_START_SESSION)
+ throw new DataFormatException("input is not a valid " +
+ this.getClass().getCanonicalName());
+
+ /*
+ status = ServerStatus.valueOf(asn1Reader.readOctetString().byteAt(0));
+ assuredFlag = (asn1Reader.readOctetString().byteAt(0) == 1);
+ assuredMode=AssuredMode.valueOf((asn1Reader.readOctetString().byteAt(0)));
+ safeDataLevel = asn1Reader.readOctetString().byteAt(0);
+ */
+ status = ServerStatus.valueOf(reader.get());
+ assuredFlag = (reader.get() == 1);
+ assuredMode = AssuredMode.valueOf(reader.get());
+ safeDataLevel = reader.get();
+
+ ASN1Reader asn1Reader = ASN1.getReader(reader);
+
+ asn1Reader.readStartSequence();
+ while(asn1Reader.hasNextElement())
+ {
+ String s = asn1Reader.readOctetStringAsString();
+ this.referralsURLs.add(s);
+ }
+ asn1Reader.readEndSequence();
+
+ asn1Reader.readStartSequence();
+ while(asn1Reader.hasNextElement())
+ {
+ String s = asn1Reader.readOctetStringAsString();
+ this.eclIncludes.add(s);
+ }
+ asn1Reader.readEndSequence();
+ }
+ catch (Exception e)
+ {
+ }
+ }
+
+ private void decode_V23(byte[] in)
+ throws DataFormatException
{
/*
* The message is stored in the form:
@@ -128,88 +394,6 @@
}
/**
- * Creates a new StartSessionMsg message with the given required parameters.
- * @param status Status we are starting with
- * @param referralsURLs Referrals URLs to be used by peer DSs
- * @param assuredFlag If assured mode is enabled or not
- * @param assuredMode Assured type
- * @param safeDataLevel Assured mode safe data level
- */
- public StartSessionMsg(ServerStatus status, List<String> referralsURLs,
- boolean assuredFlag, AssuredMode assuredMode, byte safeDataLevel)
- {
- this.referralsURLs = referralsURLs;
- this.status = status;
- this.assuredFlag = assuredFlag;
- this.assuredMode = assuredMode;
- this.safeDataLevel = safeDataLevel;
- }
-
- /**
- * Creates a new StartSessionMsg message with the given required parameters.
- * Assured mode is false.
- * @param status Status we are starting with
- * @param referralsURLs Referrals URLs to be used by peer DSs
- */
- public StartSessionMsg(ServerStatus status, List<String> referralsURLs)
- {
- this.referralsURLs = referralsURLs;
- this.status = status;
- this.assuredFlag = false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public byte[] getBytes()
- {
- /*
- * The message is stored in the form:
- * <message type><status><assured flag><assured mode><safe data level>
- * <list of referrals urls>
- * (each referral url terminates with 0)
- */
-
- try
- {
- ByteArrayOutputStream oStream = new ByteArrayOutputStream();
-
- /* Put the message type */
- oStream.write(MSG_TYPE_START_SESSION);
-
- // Put the status
- oStream.write(status.getValue());
-
- // Put the assured flag
- oStream.write(assuredFlag ? (byte) 1 : (byte) 0);
-
- // Put assured mode
- oStream.write(assuredMode.getValue());
-
- // Put safe data level
- oStream.write(safeDataLevel);
-
- // Put the referrals URLs
- if (referralsURLs.size() >= 1)
- {
- for (String url : referralsURLs)
- {
- byte[] byteArrayURL = url.getBytes("UTF-8");
- oStream.write(byteArrayURL);
- oStream.write(0);
- }
- }
-
- return oStream.toByteArray();
- } catch (IOException e)
- {
- // never happens
- return null;
- }
- }
-
- /**
* Get the list of referrals URLs.
*
* @return The list of referrals URLs.
@@ -243,7 +427,8 @@
"\nassuredFlag: " + assuredFlag +
"\nassuredMode: " + assuredMode +
"\nsafeDataLevel: " + safeDataLevel +
- "\nreferralsURLs: " + urls);
+ "\nreferralsURLs: " + urls +
+ "\nEclIncludes: " + eclIncludes);
}
/**
@@ -273,4 +458,23 @@
return safeDataLevel;
}
+ /**
+ * Set the list of entry attributes to include in the ECL.
+ * @param eclIncludes The list of attributes.
+ */
+ public void setEclIncludes(Set<String> eclIncludes)
+ {
+ if (eclIncludes != null)
+ this.eclIncludes = eclIncludes;
+ }
+
+ /**
+ * Get the list of entry attributes to include in the ECL..
+ * @return The list of entry attributes to include in the ECL.
+ */
+ public Set<String> getEclIncludes()
+ {
+ return eclIncludes;
+ }
+
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java b/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java
index b30f0dd..fd34473 100644
--- a/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/TopologyMsg.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2007-2008 Sun Microsystems, Inc.
+ * Copyright 2007-2009 Sun Microsystems, Inc.
*/
package org.opends.server.replication.protocol;
@@ -30,8 +30,11 @@
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.zip.DataFormatException;
+
import org.opends.server.replication.common.AssuredMode;
import org.opends.server.replication.common.DSInfo;
import org.opends.server.replication.common.RSInfo;
@@ -62,13 +65,165 @@
private List<RSInfo> rsList = new ArrayList<RSInfo>();
/**
+ * The protocolVersion that should be used when serializing this message.
+ */
+ private final short protocolVersion;
+
+ /**
* Creates a new changelogInfo message from its encoded form.
*
* @param in The byte array containing the encoded form of the message.
+ * @param version The protocol version to use to decode the msg.
* @throws java.util.zip.DataFormatException If the byte array does not
* contain a valid encoded form of the message.
*/
- public TopologyMsg(byte[] in) throws DataFormatException
+ public TopologyMsg(byte[] in, short version) throws DataFormatException
+ {
+ protocolVersion = ProtocolVersion.getCurrentVersion();
+ decode(in, version);
+ }
+
+ /**
+ * Creates a new message from a list of the currently connected servers.
+ *
+ * @param dsList The list of currently connected DS servers ID.
+ * @param rsList The list of currently connected RS servers ID.
+ * @param version The protocol version to use to decode the msg.
+ */
+ public TopologyMsg(List<DSInfo> dsList, List<RSInfo> rsList, short version)
+ {
+ if (dsList != null) // null means no info, let empty list from init time
+ this.dsList = dsList;
+ if (rsList != null) // null means no info, let empty list from init time
+ this.rsList = rsList;
+ this.protocolVersion = version;
+ }
+
+ /**
+ * Creates a new message from a list of the currently connected servers.
+ *
+ * @param dsList The list of currently connected DS servers ID.
+ * @param rsList The list of currently connected RS servers ID.
+ */
+ public TopologyMsg(List<DSInfo> dsList, List<RSInfo> rsList)
+ {
+ if (dsList != null) // null means no info, let empty list from init time
+ this.dsList = dsList;
+ if (rsList != null) // null means no info, let empty list from init time
+ this.rsList = rsList;
+ this.protocolVersion = ProtocolVersion.getCurrentVersion();
+ }
+
+ // ============
+ // Msg encoding
+ // ============
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getBytes()
+ throws UnsupportedEncodingException
+ {
+ try
+ {
+ /**
+ * Message has the following form:
+ * <pdu type><number of following DSInfo entries>[<DSInfo>]*
+ * <number of following RSInfo entries>[<RSInfo>]*
+ */
+ ByteArrayOutputStream oStream = new ByteArrayOutputStream();
+
+ /* Put the message type */
+ oStream.write(MSG_TYPE_TOPOLOGY);
+
+ // Put number of following DS info entries
+ oStream.write((byte)dsList.size());
+
+ // Put DS info
+ for (DSInfo dsInfo : dsList)
+ {
+ // Put DS id
+ byte[] byteServerId =
+ String.valueOf(dsInfo.getDsId()).getBytes("UTF-8");
+ oStream.write(byteServerId);
+ oStream.write(0);
+ // Put RS id
+ byteServerId =
+ String.valueOf(dsInfo.getRsId()).getBytes("UTF-8");
+ oStream.write(byteServerId);
+ oStream.write(0);
+ // Put the generation id
+ oStream.write(String.valueOf(dsInfo.getGenerationId()).
+ getBytes("UTF-8"));
+ oStream.write(0);
+ // Put DS status
+ oStream.write(dsInfo.getStatus().getValue());
+ // Put DS assured flag
+ oStream.write(dsInfo.isAssured() ? (byte) 1 : (byte) 0);
+ // Put DS assured mode
+ oStream.write(dsInfo.getAssuredMode().getValue());
+ // Put DS safe data level
+ oStream.write(dsInfo.getSafeDataLevel());
+ // Put DS group id
+ oStream.write(dsInfo.getGroupId());
+
+ List<String> refUrls = dsInfo.getRefUrls();
+ // Put number of following URLs as a byte
+ oStream.write(refUrls.size());
+ for (String url : refUrls)
+ {
+ // Write the url and a 0 terminating byte
+ oStream.write(url.getBytes("UTF-8"));
+ oStream.write(0);
+ }
+
+ if (protocolVersion >= ProtocolVersion.REPLICATION_PROTOCOL_V4)
+ {
+ Set<String> attrs = dsInfo.getEclIncludes();
+ oStream.write(attrs.size());
+ for (String attr : attrs)
+ {
+ oStream.write(attr.getBytes("UTF-8"));
+ oStream.write(0);
+ }
+ }
+ }
+
+ // Put number of following RS info entries
+ oStream.write((byte)rsList.size());
+
+ // Put RS info
+ for (RSInfo rsInfo : rsList)
+ {
+ // Put RS id
+ byte[] byteServerId =
+ String.valueOf(rsInfo.getId()).getBytes("UTF-8");
+ oStream.write(byteServerId);
+ oStream.write(0);
+ // Put the generation id
+ oStream.write(String.valueOf(rsInfo.getGenerationId()).
+ getBytes("UTF-8"));
+ oStream.write(0);
+ // Put DS group id
+ oStream.write(rsInfo.getGroupId());
+ }
+
+ return oStream.toByteArray();
+ } catch (IOException e)
+ {
+ // never happens
+ return null;
+ }
+
+ }
+
+ // ============
+ // Msg decoding
+ // ============
+
+ private void decode(byte[] in, short version)
+ throws DataFormatException
{
try
{
@@ -151,10 +306,29 @@
nRead++;
}
+ Set<String> attrs = new HashSet<String>();
+ 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
+ )
+ {
+ length = getNextLength(in, pos);
+ String attr = new String(in, pos, length, "UTF-8");
+ attrs.add(attr);
+ pos +=
+ length + 1;
+ nRead++;
+ }
+ }
+
/* Now create DSInfo and store it in list */
DSInfo dsInfo = new DSInfo(dsId, rsId, generationId, status,
- assuredFlag, assuredMode, safeDataLevel, groupId, refUrls);
+ assuredFlag, assuredMode, safeDataLevel, groupId, refUrls, attrs);
dsList.add(dsInfo);
nDsInfo--;
@@ -197,110 +371,6 @@
{
throw new DataFormatException("UTF-8 is not supported by this jvm.");
}
-
- }
-
- /**
- * Creates a new ReplServerInfo message from a list of the currently
- * connected servers.
- *
- * @param dsList The list of currently connected DS servers ID.
- * @param rsList The list of currently connected RS servers ID.
- */
- public TopologyMsg(List<DSInfo> dsList, List<RSInfo> rsList)
- {
- if (dsList != null) // null means no info, let empty list from init time
- this.dsList = dsList;
- if (rsList != null) // null means no info, let empty list from init time
- this.rsList = rsList;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public byte[] getBytes()
- {
- try
- {
- /**
- * Message has the following form:
- * <pdu type><number of following DSInfo entries>[<DSInfo>]*
- * <number of following RSInfo entries>[<RSInfo>]*
- */
- ByteArrayOutputStream oStream = new ByteArrayOutputStream();
-
- /* Put the message type */
- oStream.write(MSG_TYPE_TOPOLOGY);
-
- // Put number of following DS info entries
- oStream.write((byte)dsList.size());
-
- // Put DS info
- for (DSInfo dsInfo : dsList)
- {
- // Put DS id
- byte[] byteServerId =
- String.valueOf(dsInfo.getDsId()).getBytes("UTF-8");
- oStream.write(byteServerId);
- oStream.write(0);
- // Put RS id
- byteServerId =
- String.valueOf(dsInfo.getRsId()).getBytes("UTF-8");
- oStream.write(byteServerId);
- oStream.write(0);
- // Put the generation id
- oStream.write(String.valueOf(dsInfo.getGenerationId()).
- getBytes("UTF-8"));
- oStream.write(0);
- // Put DS status
- oStream.write(dsInfo.getStatus().getValue());
- // Put DS assured flag
- oStream.write(dsInfo.isAssured() ? (byte) 1 : (byte) 0);
- // Put DS assured mode
- oStream.write(dsInfo.getAssuredMode().getValue());
- // Put DS safe data level
- oStream.write(dsInfo.getSafeDataLevel());
- // Put DS group id
- oStream.write(dsInfo.getGroupId());
-
- List<String> refUrls = dsInfo.getRefUrls();
- // Put number of following URLs as a byte
- oStream.write(refUrls.size());
- for (String url : refUrls)
- {
- // Write the url and a 0 terminating byte
- oStream.write(url.getBytes("UTF-8"));
- oStream.write(0);
- }
- }
-
- // Put number of following RS info entries
- oStream.write((byte)rsList.size());
-
- // Put RS info
- for (RSInfo rsInfo : rsList)
- {
- // Put RS id
- byte[] byteServerId =
- String.valueOf(rsInfo.getId()).getBytes("UTF-8");
- oStream.write(byteServerId);
- oStream.write(0);
- // Put the generation id
- oStream.write(String.valueOf(rsInfo.getGenerationId()).
- getBytes("UTF-8"));
- oStream.write(0);
- // Put DS group id
- oStream.write(rsInfo.getGroupId());
- }
-
- return oStream.toByteArray();
- } catch (IOException e)
- {
- // never happens
- return null;
- }
-
}
/**
diff --git a/opends/src/server/org/opends/server/replication/server/DataServerHandler.java b/opends/src/server/org/opends/server/replication/server/DataServerHandler.java
index 2c12cc5..e7f00f0 100644
--- a/opends/src/server/org/opends/server/replication/server/DataServerHandler.java
+++ b/opends/src/server/org/opends/server/replication/server/DataServerHandler.java
@@ -35,8 +35,10 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.zip.DataFormatException;
import org.opends.messages.Message;
@@ -74,6 +76,7 @@
private AssuredMode assuredMode = AssuredMode.SAFE_DATA_MODE;
// DS safe data level (relevant if assured mode is safe data)
private byte safeDataLevel = (byte) -1;
+ private Set<String> eclIncludes = new HashSet<String>();
/**
* Creates a new data server handler.
@@ -582,7 +585,8 @@
public DSInfo toDSInfo()
{
DSInfo dsInfo = new DSInfo(serverId, replicationServerId, generationId,
- status, assuredFlag, assuredMode, safeDataLevel, groupId, refUrls);
+ status, assuredFlag, assuredMode, safeDataLevel, groupId, refUrls,
+ eclIncludes);
return dsInfo;
}
@@ -645,6 +649,7 @@
this.assuredFlag = startSessionMsg.isAssured();
this.assuredMode = startSessionMsg.getAssuredMode();
this.safeDataLevel = startSessionMsg.getSafeDataLevel();
+ this.eclIncludes = startSessionMsg.getEclIncludes();
/*
* If we have already a generationID set for the domain
diff --git a/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java b/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java
index eae7115..27d6e8d 100644
--- a/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java
+++ b/opends/src/server/org/opends/server/replication/server/LightweightServerHandler.java
@@ -32,8 +32,10 @@
import java.util.ArrayList;
import java.util.Date;
-
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+
import org.opends.server.admin.std.server.MonitorProviderCfg;
import org.opends.server.api.MonitorProvider;
import org.opends.server.config.ConfigException;
@@ -86,6 +88,8 @@
// DS safe data level (relevant if assured mode is safe data)
private byte safeDataLevel = (byte) -1;
+ private Set<String> eclInclude = new HashSet<String>();
+
/**
* Creates a new LighweightServerHandler with the provided serverid, connected
* to the remote Replication Server represented by replServerHandler.
@@ -102,11 +106,12 @@
* @param assuredFlag The assured flag of the remote DS
* @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.
*/
public LightweightServerHandler(ReplicationServerHandler replServerHandler,
short replicationServerId, short serverId, long generationId, byte groupId,
ServerStatus status, List<String> refUrls, boolean assuredFlag,
- AssuredMode assuredMode, byte safeDataLevel)
+ AssuredMode assuredMode, byte safeDataLevel, Set<String> eclInclude)
{
super("Server Handler");
this.replServerHandler = replServerHandler;
@@ -120,6 +125,7 @@
this.assuredFlag = assuredFlag;
this.assuredMode = assuredMode;
this.safeDataLevel = safeDataLevel;
+ this.eclInclude = eclInclude;
if (debugEnabled())
TRACER.debugInfo(
@@ -137,7 +143,8 @@
public DSInfo toDSInfo()
{
DSInfo dsInfo = new DSInfo(serverId, replicationServerId, generationId,
- status, assuredFlag, assuredMode, safeDataLevel, groupId, refUrls);
+ status, assuredFlag, assuredMode, safeDataLevel, groupId, refUrls,
+ eclInclude);
return dsInfo;
}
diff --git a/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java b/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
index 06ebf06..2e4f34c 100644
--- a/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
+++ b/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
@@ -63,8 +63,8 @@
import org.opends.server.replication.common.ServerStatus;
import org.opends.server.replication.common.StatusMachineEvent;
import org.opends.server.replication.protocol.AckMsg;
-import org.opends.server.replication.protocol.ChangeTimeHeartbeatMsg;
import org.opends.server.replication.protocol.ChangeStatusMsg;
+import org.opends.server.replication.protocol.ChangeTimeHeartbeatMsg;
import org.opends.server.replication.protocol.DoneMsg;
import org.opends.server.replication.protocol.EntryMsg;
import org.opends.server.replication.protocol.ErrorMsg;
@@ -3045,6 +3045,7 @@
return eligibleCN;
}
+
/**
* Processes a ChangeTimeHeartbeatMsg received, by storing the CN (timestamp)
* value received, and forwarding the message to the other RSes.
@@ -3070,7 +3071,7 @@
if (senderHandler.isDataServer())
{
// If we are the first replication server warned,
- // then forwards the reset message to the remote replication servers
+ // then forwards the message to the remote replication servers
for (ReplicationServerHandler rsHandler : replicationServers.values())
{
try
diff --git a/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java b/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java
index 2c61852..a288986 100644
--- a/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java
+++ b/opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java
@@ -631,7 +631,8 @@
serverId, dsInfo.getDsId(), dsInfo.getGenerationId(),
dsInfo.getGroupId(), dsInfo.getStatus(), dsInfo.getRefUrls(),
dsInfo.isAssured(), dsInfo.getAssuredMode(),
- dsInfo.getSafeDataLevel());
+ dsInfo.getSafeDataLevel(),
+ dsInfo.getEclIncludes());
lsh.startHandler();
remoteDirectoryServers.put(lsh.getServerId(), lsh);
}
diff --git a/opends/src/server/org/opends/server/replication/server/ServerReader.java b/opends/src/server/org/opends/server/replication/server/ServerReader.java
index 0bae9e6..6e35b64 100644
--- a/opends/src/server/org/opends/server/replication/server/ServerReader.java
+++ b/opends/src/server/org/opends/server/replication/server/ServerReader.java
@@ -26,38 +26,19 @@
*/
package org.opends.server.replication.server;
-import org.opends.messages.Message;
-
-import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.messages.ReplicationMessages.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
-
import java.io.IOException;
+import org.opends.messages.Message;
import org.opends.server.api.DirectoryThread;
-import org.opends.server.replication.protocol.AckMsg;
-import org.opends.server.replication.protocol.DoneMsg;
-import org.opends.server.replication.protocol.EntryMsg;
-import org.opends.server.replication.protocol.ErrorMsg;
-import org.opends.server.replication.protocol.ResetGenerationIdMsg;
-import org.opends.server.replication.protocol.InitializeRequestMsg;
-import org.opends.server.replication.protocol.InitializeTargetMsg;
-import org.opends.server.replication.protocol.ProtocolSession;
-import org.opends.server.replication.protocol.ReplicationMsg;
-import org.opends.server.replication.protocol.UpdateMsg;
-import org.opends.server.replication.protocol.WindowMsg;
-import org.opends.server.replication.protocol.WindowProbeMsg;
-import org.opends.server.replication.protocol.TopologyMsg;
-import org.opends.server.replication.protocol.MonitorMsg;
-import org.opends.server.replication.protocol.MonitorRequestMsg;
-import org.opends.server.replication.protocol.ChangeTimeHeartbeatMsg;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.common.ServerStatus;
-import org.opends.server.replication.protocol.ChangeStatusMsg;
-import org.opends.server.replication.protocol.
- NotSupportedOldVersionPDUException;
+import org.opends.server.replication.protocol.*;
/**
* This class implement the part of the replicationServer that is reading
diff --git a/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java b/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java
index cfd8337..be3237c 100644
--- a/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java
+++ b/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java
@@ -1119,6 +1119,8 @@
domain.isAssured(),
domain.getAssuredMode(),
domain.getAssuredSdLevel());
+ startSessionMsg.setEclIncludes(
+ domain.getEclInclude());
} else
{
startSessionMsg =
@@ -1943,7 +1945,7 @@
private boolean debugEnabled()
{
- return false;
+ return true;
}
private static final void debugInfo(String s)
@@ -2165,8 +2167,22 @@
rsList = topoMsg.getRsList();
}
}
+ if (domain != null)
+ {
+ for (DSInfo info : dsList)
+ {
+ for (String attr : info.getEclIncludes())
+ {
+ domain.addEclInclude(attr);
+ }
+ }
+ if (debugEnabled())
+ {
+ TRACER.debugInfo("domain: " + domain.getServiceID() +
+ " EclIncludes" + domain.getEclInclude());
+ }
+ }
}
-
/**
* Check if the broker could not find any Replication Server and therefore
* connection attempt failed.
diff --git a/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java b/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java
index c39d447..f70d3ae 100644
--- a/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java
+++ b/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java
@@ -64,6 +64,7 @@
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;
@@ -318,6 +319,9 @@
private Map<Short, ServerState> replicaStates =
new HashMap<Short, ServerState>();
+ Set<String> cfgEclIncludes = new HashSet<String>();
+ Set<String> eClIncludes = new HashSet<String>();
+
/**
* Returns the {@link ChangeNumberGenerator} that will be used to
* generate {@link ChangeNumber} for this domain.
@@ -2923,4 +2927,32 @@
else
return 0;
}
+
+ /**
+ * Add an attribute to the list of attributes to include in the ECL.
+ * @param attribute The attribute to add.
+ */
+ synchronized public void addEclInclude(String attribute)
+ {
+ eClIncludes.add(attribute);
+ }
+
+ /**
+ * Get the list of attributes to include in the ECL.
+ * @return The list of attributes.
+ */
+ public Set<String> getEclInclude()
+ {
+ return eClIncludes;
+ }
+
+ /**
+ * Set the list of attributes to include in the ECL.
+ * @param eclIncludes The list of attributes.
+ */
+ protected void setCfgEclInclude(Set<String> eclIncludes)
+ {
+ this.cfgEclIncludes = eclIncludes;
+ this.eClIncludes = eclIncludes;
+ }
}
diff --git a/opends/src/server/org/opends/server/types/RawAttribute.java b/opends/src/server/org/opends/server/types/RawAttribute.java
index 35435ef..1e9ad43 100644
--- a/opends/src/server/org/opends/server/types/RawAttribute.java
+++ b/opends/src/server/org/opends/server/types/RawAttribute.java
@@ -218,8 +218,8 @@
stream.writeOctetString(value);
}
}
- stream.writeEndSequence();
+ stream.writeEndSet();
stream.writeEndSequence();
}
diff --git a/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java b/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
index 1a40621..459b45a 100644
--- a/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
@@ -82,6 +82,7 @@
import org.opends.server.replication.protocol.UpdateMsg;
import org.opends.server.replication.server.ReplicationServer;
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;
@@ -720,6 +721,8 @@
// Map the addMsg to an LDIF string for the 'changes' attribute
String LDIFchanges = addMsgToLDIFString(addMsg);
+ ArrayList<RawAttribute> eclAttributes = addMsg.getEclIncludes();
+
clEntry = createChangelogEntry(
eclmsg.getServiceId(),
eclmsg.getCookie().toString(),
@@ -728,8 +731,7 @@
LDIFchanges, // entry as created (in LDIF format)
addMsg.getUniqueId(),
null, // real time current entry
- null, // real time attrs names
- null, // hist entry attributes
+ eclAttributes, // entry attributes
eclmsg.getDraftChangeNumber(),
"add");
@@ -747,8 +749,8 @@
(ModifyOperation)modMsg.createOperation(conn);
String LDIFchanges = modToLDIF(modifyOperation.getModifications());
- // TODO:ECL Hist entry attributes
- // ArrayList<RawAttribute> attributes = modMsg.getEntryAttributes();
+ ArrayList<RawAttribute> eclAttributes = modMsg.getEclIncludes();
+
clEntry = createChangelogEntry(
eclmsg.getServiceId(),
eclmsg.getCookie().toString(),
@@ -757,10 +759,9 @@
LDIFchanges,
modMsg.getUniqueId(),
null, // real time current entry
- null, // real time attrs names
- null, // hist entry attributes
+ eclAttributes, // entry attributes
eclmsg.getDraftChangeNumber(),
- "modify");
+ "modify");
}
catch(Exception e)
@@ -775,6 +776,8 @@
{
ModifyDNMsg modDNMsg = (ModifyDNMsg)msg;
+ ArrayList<RawAttribute> eclAttributes = modDNMsg.getEclIncludes();
+
clEntry = createChangelogEntry(
eclmsg.getServiceId(),
eclmsg.getCookie().toString(),
@@ -783,10 +786,9 @@
null,
modDNMsg.getUniqueId(),
null, // real time current entry
- null, // real time attrs names
- null, // hist entry attributes
+ eclAttributes, // entry attributes
eclmsg.getDraftChangeNumber(),
- "modrdn");
+ "modrdn");
Attribute a = Attributes.create("newrdn", modDNMsg.getNewRDN());
clEntry.addAttribute(a, null);
@@ -806,25 +808,20 @@
else if (msg instanceof DeleteMsg)
{
DeleteMsg delMsg = (DeleteMsg)msg;
- /* TODO:ECL Entry attributes for DEL op
- ArrayList<RawAttribute> rattributes = new ArrayList<RawAttribute>();
- ArrayList<RawAttribute> rattributes = delMsg.getEntryAttributes();
- // Map the entry attributes of the DelMsg to an LDIF string
- // for the 'deletedentryattributes' attribute of the CL entry
- String delAttrs = delMsgToLDIFString(rattributes);
- */
+
+ ArrayList<RawAttribute> eclAttributes = delMsg.getEclIncludes();
+
clEntry = createChangelogEntry(
eclmsg.getServiceId(),
eclmsg.getCookie().toString(),
DN.decode(delMsg.getDn()),
delMsg.getChangeNumber(),
- null,
+ null, // no changes
delMsg.getUniqueId(),
null,
- null,
- null, //rattributes,
+ eclAttributes, // entry attributes
eclmsg.getDraftChangeNumber(),
- "delete");
+ "delete");
}
return clEntry;
}
@@ -861,8 +858,6 @@
* @param clearLDIFchanges The provided LDIF changes for ADD and MODIFY
* @param targetUUID The provided targetUUID.
* @param entry The provided related current entry.
- * @param targetAttrNames The provided list of attributes names that should
- * be read from the entry (real time values)
* @param histEntryAttributes TODO:ECL Adress hist entry attributes
* @param draftChangenumber The provided draft change number (integer)
* @param changetype The provided change type (add, ...)
@@ -878,7 +873,6 @@
String clearLDIFchanges,
String targetUUID,
Entry entry,
- List<String> targetAttrNames,
List<RawAttribute> histEntryAttributes,
int draftChangenumber,
String changetype)
@@ -1013,28 +1007,13 @@
if (clearLDIFchanges != null)
{
- if (changetype.equalsIgnoreCase("delete"))
- {
- a = Attributes.create("clearDeletedEntryAttrs", clearLDIFchanges);
- }
- attrList = new ArrayList<Attribute>(1);
- attrList.add(a);
- operationalAttrs.put(a.getAttributeType(), attrList);
+ if((attributeType =
+ DirectoryServer.getAttributeType("changes")) == null)
+ attributeType =
+ DirectoryServer.getDefaultAttributeType("changes");
- if (changetype.equalsIgnoreCase("delete"))
- {
- a = Attributes.create("deletedentryattrs",
- clearLDIFchanges + "\n"); // force base64
- }
- else
- {
- if((attributeType =
- DirectoryServer.getAttributeType("changes")) == null)
- attributeType =
- DirectoryServer.getDefaultAttributeType("changes");
- a = Attributes.create(attributeType, clearLDIFchanges + "\n");
- // force base64
- }
+ a = Attributes.create(attributeType, clearLDIFchanges + "\n");
+ // force base64
attrList = new ArrayList<Attribute>(1);
attrList.add(a);
if(attributeType.isOperational())
@@ -1087,68 +1066,21 @@
else
uAttrs.put(attributeType, attrList);
- // entryAttribute version
- /*
- if (targetAttrNames != null)
- {
- String sEntryAttrs = null;
- for (String attrName : targetAttrNames)
- {
- List<Attribute> attrs = entry.getAttribute(attrName);
- for (Attribute attr : attrs)
- {
- if (sEntryAttrs==null)
- sEntryAttrs="";
- else
- sEntryAttrs+=";";
- sEntryAttrs += attr.toString();
- }
- }
- if (sEntryAttrs!=null)
- {
- a = Attributes.create("entryAttributes", sEntryAttrs);
- attrList = new ArrayList<Attribute>(1);
- attrList.add(a);
- uAttrs.put(a.getAttributeType(), attrList);
- }
- }
- */
-
- /*
- if (targetAttrNames != null)
- {
- for (String attrName : targetAttrNames)
- {
- String newName = "target"+attrName;
- List<Attribute> attrs = entry.getAttribute(attrName);
- for (Attribute aa : attrs)
- {
- AttributeBuilder builder = new AttributeBuilder(
- DirectoryServer.getDefaultAttributeType(newName));
- builder.setOptions(aa.getOptions());
- builder.addAll(aa);
- attrList = new ArrayList<Attribute>(1);
- attrList.add(builder.toAttribute());
- uAttrs.put(aa.getAttributeType(), attrList);
- }
- }
- }
- */
- /* TODO: Implement entry attributes historical values
if (histEntryAttributes != null)
{
- for (RawAttribute rea : histEntryAttributes)
+ for (RawAttribute ra : histEntryAttributes)
{
- // uAttrs.put(ea.getAttributeType(), null);
- // FIXME: ERRONEOUS TYPING !!!!!!!!!!!!!
try
{
- String newName = "target"+rea.getAttributeType();
- AttributeType nat=DirectoryServer.getDefaultAttributeType(newName);
- rea.setAttributeType(newName);
+ String eclName = "target" + ra.getAttributeType().toLowerCase();
+ AttributeBuilder builder = new AttributeBuilder(
+ DirectoryServer.getDefaultAttributeType(eclName));
+ AttributeType at = builder.getAttributeType();
+ builder.setOptions(ra.toAttribute().getOptions());
+ builder.addAll(ra.toAttribute());
attrList = new ArrayList<Attribute>(1);
- attrList.add(rea.toAttribute());
- uAttrs.put(nat, attrList);
+ attrList.add(builder.toAttribute());
+ uAttrs.put(at, attrList);
}
catch(Exception e)
{
@@ -1156,7 +1088,6 @@
}
}
}
- */
// at the end build the CL entry to be returned
Entry cle = new Entry(
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
index 1c88152..3a644bb 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
@@ -27,9 +27,8 @@
package org.opends.server.replication;
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;
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.replication.protocol.OperationContext.SYNCHROCONTEXT;
import static org.opends.server.util.StaticUtils.createEntry;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
@@ -45,17 +44,16 @@
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
-import java.util.HashMap;
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 org.opends.messages.Category;
-import org.opends.messages.Message;
-import org.opends.messages.Severity;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.Backend;
import org.opends.server.api.ConnectionHandler;
@@ -66,8 +64,10 @@
import org.opends.server.controls.PersistentSearchChangeType;
import org.opends.server.controls.PersistentSearchControl;
import org.opends.server.core.AddOperationBasis;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyDNOperationBasis;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.plugins.InvocationCounterPlugin;
import org.opends.server.protocols.asn1.ASN1Exception;
@@ -103,7 +103,6 @@
import org.opends.server.replication.protocol.StartECLSessionMsg;
import org.opends.server.replication.protocol.UpdateMsg;
import org.opends.server.replication.server.DraftCNDbHandler;
-import org.opends.server.replication.server.ExternalChangeLogSessionImpl;
import org.opends.server.replication.server.ReplServerFakeConfiguration;
import org.opends.server.replication.server.ReplicationServer;
import org.opends.server.replication.server.ReplicationServerDomain;
@@ -111,6 +110,7 @@
import org.opends.server.tools.LDAPSearch;
import org.opends.server.tools.LDAPWriter;
import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeBuilder;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.Attributes;
import org.opends.server.types.ByteString;
@@ -157,6 +157,9 @@
private static final String TEST_ROOT_DN_STRING2 = "o=test2";
private static final String TEST_BACKEND_ID2 = "test2";
+ private static final String TEST_ROOT_DN_STRING3 = "o=test3";
+ private static final String TEST_BACKEND_ID3 = "test3";
+
// The LDAPStatistics object associated with the LDAP connection handler.
private LDAPStatistics ldapStatistics;
@@ -206,8 +209,9 @@
@Test(enabled=true)
public void ECLReplicationServerTest()
{
- // --
+ // ***********************************************
// First set of test are in the cookie mode
+ // ***********************************************
// Test that private backend is excluded from ECL
ECLOnPrivateBackend();replicationServer.clearDb();
@@ -250,7 +254,6 @@
// TODO:ECL Test SEARCH abandon and check everything shutdown and cleaned
// TODO:ECL Test PSEARCH abandon and check everything shutdown and cleaned
// TODO:ECL Test invalid DN in cookie returns UNWILLING + message
- // TODO:ECL Test notif control returned contains the cookie
// TODO:ECL Test the attributes list and values returned in ECL entries
// TODO:ECL Test search -s base, -s one
@@ -262,8 +265,9 @@
// optimize the request.
ECLFilterTest();
- // --
+ // ***********************************************
// Second set of test are in the draft compat mode
+ // ***********************************************
// Empty replication changelog
ECLCompatEmpty();
@@ -309,6 +313,10 @@
// Test simultaneous persistent searches in draft compat mode.
ECLSimultaneousPsearches();replicationServer.clearDb();
+ // ***********************************************
+ // Entry attributes
+ // ***********************************************
+ ECLIncludeAttributes();replicationServer.clearDb();
}
//=======================================================
@@ -391,7 +399,6 @@
server1.stop();
server2.stop();
server3.stop();
- sleep(500);
debugInfo(tn, "Ending test successfully\n\n");
}
catch(Exception e)
@@ -484,8 +491,7 @@
// clean
serverECL.stop();
server01.stop();
- server02.stop();
- sleep(2000);
+ server02.stop();
debugInfo(tn, "Ending test successfully");
}
catch(Exception e)
@@ -605,7 +611,8 @@
// Initialize a second test backend o=test2, in addtion to o=test
// Configure replication on this backend
// Add the root entry in the backend
- Backend backend2 = initializeTestBackend2(false);
+ Backend backend2 = initializeTestBackend(false, TEST_ROOT_DN_STRING2,
+ TEST_BACKEND_ID2);
DN baseDn2 = DN.decode(TEST_ROOT_DN_STRING2);
SortedSet<String> replServers = new TreeSet<String>();
replServers.add("localhost:"+replicationServerPort);
@@ -647,16 +654,25 @@
assertEquals(searchOp.getResultCode(), ResultCode.SUCCESS,
searchOp.getErrorMessage().toString() + searchOp.getAdditionalLogMessage());
LinkedList<SearchResultEntry> entries = searchOp.getSearchEntries();
+ assertEquals(entries.size(),2, "Entries number returned by search");
assertTrue(entries != null);
if (entries != null)
+ {
+ int i = 0;
for (SearchResultEntry resultEntry : entries)
{
+ i++;
// Expect
debugInfo(tn, "Entry returned when test2 is public =" +
resultEntry.toLDIFString());
+
+ // Test entry attributes
+ //if (i==2)
+ //{
+ // checkPossibleValues(resultEntry,"targetobjectclass","top","organization");
+ //}
}
- assertEquals(entries.size(),2, "Entries number returned by search");
-
+ }
//
// Set the backend private and do again a search on ECL that should
// now not return the entry
@@ -732,7 +748,8 @@
try
{
// Initialize a second test backend
- Backend backend2 = initializeTestBackend2(true);
+ Backend backend2 = initializeTestBackend(true,
+ TEST_ROOT_DN_STRING2, TEST_BACKEND_ID2);
//
LDIFWriter ldifWriter = getLDIFWriter();
@@ -1485,6 +1502,22 @@
}
}
+ private static String getAttributeValue(Entry entry, String attrName)
+ {
+ AttributeValue av = null;
+ try
+ {
+ List<Attribute> attrs = entry.getAttribute(attrName);
+ Attribute a = attrs.iterator().next();
+ av = a.iterator().next();
+ return av.toString();
+ }
+ catch(Exception e)
+ {
+ }
+ return null;
+ }
+
private static void checkPossibleValues(Entry entry, String attrName,
String expectedValue1, String expectedValue2)
{
@@ -1511,6 +1544,36 @@
}
}
+ private static void checkValues(Entry entry, String attrName,
+ Set<String> expectedValues)
+ {
+ AttributeValue av = null;
+ int i=0;
+ try
+ {
+ List<Attribute> attrs = entry.getAttribute(attrName);
+ Attribute a;
+ Iterator<Attribute> iat = attrs.iterator();
+ while ((a=iat.next())!=null)
+ {
+ Iterator<AttributeValue> iatv = a.iterator();
+ while ((av = iatv.next())!=null)
+ {
+ String encodedValue = av.toString();
+ assertTrue(
+ expectedValues.contains(encodedValue),
+ "In entry " + entry + " attr <" + attrName + "> equals " +
+ av + " instead of one of the expected values " + expectedValues);
+ i++;
+ }
+ }
+ }
+ catch(NoSuchElementException e)
+ {
+ assertTrue(i==expectedValues.size());
+ }
+ }
+
/**
* Test persistent search
*/
@@ -2385,23 +2448,26 @@
*/
private void debugInfo(String tn, String s)
{
- //if (debugEnabled())
+ if (debugEnabled())
{
- logError(Message.raw(Category.SYNC, Severity.NOTICE,
- "** TEST " + tn + " ** " + s));
- //TRACER.debugInfo("** TEST " + tn + " ** " + s);
+// logError(Message.raw(Category.SYNC, Severity.NOTICE,
+// "** TEST " + tn + " ** " + s));
+ TRACER.debugInfo("** TEST " + tn + " ** " + s);
}
}
/**
* Utility - create a second backend in order to test ECL with 2 suffixes.
*/
- private static Backend initializeTestBackend2(boolean createBaseEntry)
+ private static Backend initializeTestBackend(
+ boolean createBaseEntry,
+ String rootDN,
+ String backendId)
throws IOException, InitializationException, ConfigException,
DirectoryException
{
- DN baseDN = DN.decode(TEST_ROOT_DN_STRING2);
+ DN baseDN = DN.decode(rootDN);
// Retrieve backend. Warning: it is important to perform this each time,
// because a test may have disabled then enabled the backend (i.e a test
@@ -2410,12 +2476,12 @@
// to memory backend must be invalidated. So to prevent this problem, we
// retrieve the memory backend reference each time before cleaning it.
MemoryBackend memoryBackend =
- (MemoryBackend)DirectoryServer.getBackend(TEST_BACKEND_ID2);
+ (MemoryBackend)DirectoryServer.getBackend(backendId);
if (memoryBackend == null)
{
memoryBackend = new MemoryBackend();
- memoryBackend.setBackendID(TEST_BACKEND_ID2);
+ memoryBackend.setBackendID(backendId);
memoryBackend.setBaseDNs(new DN[] {baseDN});
memoryBackend.initializeBackend();
DirectoryServer.registerBackend(memoryBackend);
@@ -2447,7 +2513,8 @@
try
{
// Initialize a second test backend
- Backend backend2 = initializeTestBackend2(true);
+ Backend backend2 = initializeTestBackend(true, TEST_ROOT_DN_STRING2,
+ TEST_BACKEND_ID2);
// --
ReplicationBroker s1test = openReplicationSession(
@@ -2862,8 +2929,6 @@
}
}
assertEquals(searchOp.getSearchEntries().size(), 4);
-
-
}
catch(Exception e)
{
@@ -3410,4 +3475,220 @@
debugInfo(tn, "Ending test with success");
}
+ /**
+ * Test ECl entry attributes, and there configuration.
+ *
+ */
+ private void ECLIncludeAttributes()
+ {
+ String tn = "ECLIncludeAttributes";
+ debugInfo(tn, "Starting test\n\n");
+ try
+ {
+ // Initialize a second test backend o=test2, in addtion to o=test
+ // Configure replication on this backend
+ // Add the root entry in the backend
+ Backend backend2 = initializeTestBackend(false,
+ TEST_ROOT_DN_STRING2, TEST_BACKEND_ID2);
+ DN baseDn2 = DN.decode(TEST_ROOT_DN_STRING2);
+ SortedSet<String> replServers = new TreeSet<String>();
+ replServers.add("localhost:"+replicationServerPort);
+ DomainFakeCfg domainConf =
+ new DomainFakeCfg(baseDn2, (short) 1702, replServers);
+ SortedSet<String> includeAttributes = new TreeSet<String>();
+ includeAttributes.add("sn");
+ domainConf.setEclIncludes(includeAttributes);
+ LDAPReplicationDomain domain2 = MultimasterReplication.createNewDomain(domainConf);
+ SynchronizationProvider replicationPlugin2 = new MultimasterReplication();
+ replicationPlugin2.completeSynchronizationProvider();
+
+ Backend backend3 = initializeTestBackend(false,
+ TEST_ROOT_DN_STRING3, TEST_BACKEND_ID3);
+ DN baseDn3 = DN.decode(TEST_ROOT_DN_STRING3);
+ domainConf =
+ new DomainFakeCfg(baseDn3, (short) 1703, replServers);
+ includeAttributes = new TreeSet<String>();
+ includeAttributes.add("objectclass");
+ domainConf.setEclIncludes(includeAttributes);
+ LDAPReplicationDomain domain3 = MultimasterReplication.createNewDomain(domainConf);
+ SynchronizationProvider replicationPlugin3 = new MultimasterReplication();
+ replicationPlugin3.completeSynchronizationProvider();
+
+ domainConf =
+ new DomainFakeCfg(baseDn2, (short) 1704, replServers);
+ includeAttributes = new TreeSet<String>();
+ includeAttributes.add("cn");
+ domainConf.setEclIncludes(includeAttributes);
+ LDAPReplicationDomain domain21 = MultimasterReplication.createNewDomain(domainConf);
+
+ Set<String> attrList = new HashSet<String>();
+ attrList.add(new String("cn"));
+ ReplicationBroker server01 = openReplicationSession(
+ DN.decode(TEST_ROOT_DN_STRING2), (short) 1206,
+ 100, replicationServerPort,
+ 1000, true, -1 , domain21);
+
+ sleep(1000);
+
+ Entry e2 = createEntry(baseDn2);
+ addEntry(e2);
+
+ Entry e3 = createEntry(baseDn3);
+ addEntry(e3);
+
+ String lentry = new String(
+ "dn: cn=Fiona Jensen," + TEST_ROOT_DN_STRING2 + "\n"
+ + "objectclass: top\n"
+ + "objectclass: person\n"
+ + "objectclass: organizationalPerson\n"
+ + "objectclass: inetOrgPerson\n"
+ + "cn: Fiona Jensen\n"
+ + "sn: Jensen\n"
+ + "uid: fiona\n"
+ + "telephonenumber: 12121212");
+
+ Entry uentry1 = TestCaseUtils.entryFromLdifString(lentry);
+ addEntry(uentry1);
+
+ lentry = new String(
+ "dn: cn=Robert Hue," + TEST_ROOT_DN_STRING3 + "\n"
+ + "objectclass: top\n"
+ + "objectclass: person\n"
+ + "objectclass: organizationalPerson\n"
+ + "objectclass: inetOrgPerson\n"
+ + "cn: Robert Hue\n"
+ + "sn: Robby\n"
+ + "uid: robert\n"
+ + "telephonenumber: 131313");
+ Entry uentry2 = TestCaseUtils.entryFromLdifString(lentry);
+ addEntry(uentry2);
+
+ AttributeBuilder builder = new AttributeBuilder("sn");
+ builder.add("newsn");
+ Modification mod =
+ new Modification(ModificationType.REPLACE, builder.toAttribute());
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add(mod);
+
+ ModifyOperationBasis modOpBasis =
+ new ModifyOperationBasis(connection, 1, 1, null, uentry1.getDN(), mods);
+ modOpBasis.run();
+
+ builder = new AttributeBuilder("telephonenumber");
+ builder.add("555555");
+ mod =
+ new Modification(ModificationType.REPLACE, builder.toAttribute());
+ mods = new ArrayList<Modification>();
+ mods.add(mod);
+
+ modOpBasis =
+ new ModifyOperationBasis(connection, 1, 1, null, uentry2.getDN(), mods);
+ modOpBasis.run();
+
+ ModifyDNOperationBasis modDNOp = new ModifyDNOperationBasis(connection,
+ InternalClientConnection.nextOperationID(),
+ InternalClientConnection.nextMessageID(),
+ null,
+ DN.decode("cn=Robert Hue," + TEST_ROOT_DN_STRING3),
+ RDN.decode("cn=Robert Hue2"), true,
+ DN.decode(TEST_ROOT_DN_STRING3));
+ modDNOp.run();
+ assertEquals(modDNOp.getResultCode(), ResultCode.SUCCESS,
+ modDNOp.getErrorMessage().toString() + modDNOp.getAdditionalLogMessage());
+
+ DeleteOperationBasis delOp = new DeleteOperationBasis(connection,
+ InternalClientConnection.nextOperationID(),
+ InternalClientConnection.nextMessageID(), null,
+ DN.decode("cn=Robert Hue2," + TEST_ROOT_DN_STRING3));
+ delOp.run();
+ assertEquals(delOp.getResultCode(), ResultCode.SUCCESS,
+ delOp.getErrorMessage().toString() + delOp.getAdditionalLogMessage());
+
+ sleep(400);
+
+ // Search on ECL from start on all suffixes
+ String cookie = "";
+ ExternalChangelogRequestControl control =
+ new ExternalChangelogRequestControl(true,
+ new MultiDomainServerState(cookie));
+ ArrayList<Control> controls = new ArrayList<Control>(0);
+ controls.add(control);
+ LinkedHashSet<String> attributes = new LinkedHashSet<String>();
+ attributes.add("+");
+ attributes.add("*");
+
+
+ debugInfo(tn, "Search with cookie=" + cookie);
+ InternalSearchOperation searchOp = connection.processSearch(
+ ByteString.valueOf("cn=changelog"),
+ SearchScope.WHOLE_SUBTREE,
+ DereferencePolicy.NEVER_DEREF_ALIASES,
+ 0, // Size limit
+ 0, // Time limit
+ false, // Types only
+ LDAPFilter.decode("(targetDN=*)"),
+ attributes,
+ controls,
+ null);
+
+ sleep(500);
+
+ // Expect SUCCESS and root entry returned
+ assertEquals(searchOp.getResultCode(), ResultCode.SUCCESS,
+ searchOp.getErrorMessage().toString() + searchOp.getAdditionalLogMessage());
+ LinkedList<SearchResultEntry> entries = searchOp.getSearchEntries();
+
+
+ assertEquals(entries.size(),8, "Entries number returned by search");
+ assertTrue(entries != null);
+
+ if (entries != null)
+ {
+ for (SearchResultEntry resultEntry : entries)
+ {
+ // Expect
+ debugInfo(tn, "Entry returned =" + resultEntry.toLDIFString());
+
+ String targetdn = getAttributeValue(resultEntry, "targetdn");
+ if ((targetdn.endsWith("cn=robert hue,o=test3"))
+ ||(targetdn.endsWith("cn=robert hue2,o=test3")))
+ {
+ HashSet<String> eoc = new HashSet<String>();
+ eoc.add("person");eoc.add("inetOrgPerson");eoc.add("organizationalPerson");eoc.add("top");
+ checkValues(resultEntry,"targetobjectclass",eoc);
+ }
+ if (targetdn.endsWith("cn=fiona jensen,o=test2"))
+ {
+ checkValue(resultEntry,"targetsn","jensen");
+ checkValue(resultEntry,"targetcn","Fiona Jensen");
+ }
+ }
+ }
+ server01.stop();
+
+ // Cleaning
+ if (domain2 != null)
+ MultimasterReplication.deleteDomain(baseDn2);
+ if (replicationPlugin2 != null)
+ DirectoryServer.deregisterSynchronizationProvider(replicationPlugin2);
+ removeTestBackend2(backend2);
+
+ if (domain3 != null)
+ MultimasterReplication.deleteDomain(baseDn3);
+ if (replicationPlugin3 != null)
+ DirectoryServer.deregisterSynchronizationProvider(replicationPlugin3);
+ removeTestBackend2(backend3);
+
+ }
+ catch(Exception e)
+ {
+ fail("Ending "+tn+" test with exception:\n"
+ + stackTraceToSingleLineString(e));
+ }
+ finally
+ {
+
+ }
+ debugInfo(tn, "Ending test with success");
+ }
}
\ No newline at end of file
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
index d5bac70..45b7986 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
@@ -26,8 +26,9 @@
*/
package org.opends.server.replication;
-import java.io.File;
-import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_COMPLETION_TIME;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_LOG_MESSAGES;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_STATE;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
@@ -36,6 +37,7 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import java.io.File;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -48,6 +50,7 @@
import org.opends.messages.MessageBuilder;
import org.opends.messages.Severity;
import org.opends.server.DirectoryServerTestCase;
+import org.opends.server.TestCaseUtils;
import org.opends.server.backends.task.TaskState;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AddOperation;
@@ -58,21 +61,35 @@
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.ldap.LDAPFilter;
-import org.opends.server.replication.service.ReplicationBroker;
import org.opends.server.replication.common.ServerState;
-import org.opends.server.replication.plugin.PersistentServerState;
import org.opends.server.replication.plugin.LDAPReplicationDomain;
+import org.opends.server.replication.plugin.MultimasterReplication;
+import org.opends.server.replication.plugin.PersistentServerState;
import org.opends.server.replication.protocol.ErrorMsg;
import org.opends.server.replication.protocol.ReplSessionSecurity;
import org.opends.server.replication.protocol.ReplicationMsg;
+import org.opends.server.replication.service.ReplicationBroker;
+import org.opends.server.replication.service.ReplicationDomain;
import org.opends.server.schema.DirectoryStringSyntax;
import org.opends.server.schema.IntegerSyntax;
-import org.opends.server.types.*;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.AttributeValues;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.LockManager;
+import org.opends.server.types.Modification;
+import org.opends.server.types.ModificationType;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchResultEntry;
+import org.opends.server.types.SearchScope;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-import org.opends.server.TestCaseUtils;
-import org.opends.server.replication.plugin.MultimasterReplication;
/**
* An abstract class that all Replication unit test should extend.
@@ -214,12 +231,26 @@
long generationId)
throws Exception, SocketException
{
+ return openReplicationSession(baseDn, serverId, window_size,
+ port, timeout, emptyOldChanges, generationId, null);
+ }
+
+ /**
+ * Open a replicationServer session to the local ReplicationServer
+ * providing the generationId.
+ */
+ protected ReplicationBroker openReplicationSession(
+ final DN baseDn, short serverId, int window_size,
+ int port, int timeout, boolean emptyOldChanges,
+ long generationId, ReplicationDomain replicationDomain)
+ throws Exception, SocketException
+ {
ServerState state = new ServerState();
if (emptyOldChanges)
new PersistentServerState(baseDn, serverId, new ServerState());
- ReplicationBroker broker = new ReplicationBroker(null,
+ ReplicationBroker broker = new ReplicationBroker(replicationDomain,
state, baseDn.toNormalizedString(), serverId, window_size,
generationId, 100000, getReplSessionSecurity(), (byte)1, 500);
ArrayList<String> servers = new ArrayList<String>(1);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
index 798cb28..f03f32d 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
@@ -1316,7 +1316,7 @@
final DN baseDn = DN.decode("ou=People," + TEST_ROOT_DN_STRING);
ReplicationBroker broker =
- openReplicationSession(baseDn, (short) 27, 100, replServerPort, 1000, true);
+ openReplicationSession(baseDn, (short) 27, 100, replServerPort, 2000, true);
try {
ChangeNumberGenerator gen = new ChangeNumberGenerator((short) 27, 0);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java
index 7f65980..286ed40 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java
@@ -26,10 +26,11 @@
*/
package org.opends.server.replication.plugin;
+import java.util.HashSet;
import java.util.List;
import java.util.SortedSet;
-
import java.util.TreeSet;
+
import org.opends.server.admin.Configuration;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ServerManagedObject;
@@ -67,6 +68,8 @@
private SortedSet<String> fractionalExcludes = new TreeSet<String>();
private SortedSet<String> fractionalIncludes = new TreeSet<String>();
+ private SortedSet<String> eclIncludes = new TreeSet<String>();
+
/**
* Creates a new Domain with the provided information
* (assured mode disabled, default group id)
@@ -356,4 +359,14 @@
{
return true;
}
+
+ public void setEclIncludes(SortedSet<String> attrs)
+ {
+ this.eclIncludes = attrs;
+ }
+
+ public SortedSet<String> getEclInclude()
+ {
+ return this.eclIncludes;
+ }
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java
index 3f4c7ad..b72b145 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java
@@ -26,18 +26,24 @@
*/
package org.opends.server.replication.plugin;
+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;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
-import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
-import static org.opends.server.loggers.ErrorLogger.logError;
-import static org.opends.server.loggers.debug.DebugLogger.getTracer;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
-
import org.opends.messages.Category;
import org.opends.messages.Message;
import org.opends.messages.Severity;
@@ -54,8 +60,6 @@
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.testng.annotations.Test;
-import static org.testng.Assert.*;
-import static org.opends.server.TestCaseUtils.*;
/**
* Some tests to know if at any time the view DSs and RSs have of the current
@@ -850,6 +854,7 @@
AssuredType assuredType = null;
int assuredSdLevel = -100;
SortedSet<String> refUrls = null;
+ SortedSet<String> attrs = null;
switch (dsId)
{
@@ -904,7 +909,7 @@
}
return new DSInfo(dsId, rsId, TEST_DN_WITH_ROOT_ENTRY_GENID, status, assuredFlag, assMode,
- (byte)assuredSdLevel, groupId, urls);
+ (byte)assuredSdLevel, groupId, urls, attrs);
}
/**
@@ -1103,8 +1108,9 @@
byte safeDataLevel = rd.getAssuredSdLevel();
byte groupId = rd.getGroupId();
List<String> refUrls = rd.getRefUrls();
+ Set<String> eclInclude = rd.getEclInclude();
DSInfo dsInfo = new DSInfo(dsId, rsId, TEST_DN_WITH_ROOT_ENTRY_GENID, status, assuredFlag, assuredMode,
- safeDataLevel, groupId, refUrls);
+ safeDataLevel, groupId, refUrls, eclInclude);
dsList.add(dsInfo);
TopoView dsTopoView = new TopoView(dsList, rd.getRsList());
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java
index 1bae3dd..5f9f96e 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/ProtocolCompatibilityTest.java
@@ -47,6 +47,7 @@
import org.opends.server.types.ModificationType;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Operation;
+import org.opends.server.types.RawAttribute;
import org.opends.server.util.TimeThread;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@@ -62,7 +63,7 @@
*/
public class ProtocolCompatibilityTest extends ReplicationTestCase {
- short REPLICATION_PROTOCOL_VLAST = ProtocolVersion.REPLICATION_PROTOCOL_V3;
+ short REPLICATION_PROTOCOL_VLAST = ProtocolVersion.REPLICATION_PROTOCOL_V4;
/**
* Set up the environment for performing the tests in this Class.
*
@@ -177,16 +178,24 @@
}
@DataProvider(name = "createAddData")
- public Object[][] createAddData() {
+ public Object[][] createAddData()
+ {
+ // Entry attributes
+ Attribute eattr1 = Attributes.create("description", "eav description");
+ Attribute eattr2 = Attributes.create("namingcontexts", "eav naming contexts");
+ List<Attribute> entryAttrList = new ArrayList<Attribute>();
+ entryAttrList.add(eattr1);
+ entryAttrList.add(eattr2);
+
return new Object[][] {
- {"dc=example,dc=com", false, AssuredMode.SAFE_DATA_MODE, (byte)0},
- {"o=test", true, AssuredMode.SAFE_READ_MODE, (byte)1},
- {"o=group,dc=example,dc=com", true, AssuredMode.SAFE_READ_MODE, (byte)3}};
+ {"dc=example,dc=com", false, AssuredMode.SAFE_DATA_MODE, (byte)0, null},
+ {"o=test", true, AssuredMode.SAFE_READ_MODE, (byte)1, entryAttrList},
+ {"o=group,dc=example,dc=com", true, AssuredMode.SAFE_READ_MODE, (byte)3, entryAttrList}};
}
@Test(dataProvider = "createAddData")
public void addMsgTestVLASTV2(String rawDN, boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
+ byte safeDataLevel, List<Attribute> entryAttrList)
throws Exception
{
// TODO: addMsgTest as soon as V3 will have any incompatibility with V2
@@ -194,8 +203,8 @@
@Test(dataProvider = "createAddData")
public void addMsgTestVLASTV1(String rawDN, boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
- throws Exception
+ byte safeDataLevel, List<Attribute> entryAttrList)
+ throws Exception
{
// Create VLAST message
Attribute objectClass = Attributes.create(DirectoryServer
@@ -228,6 +237,11 @@
msg.setAssured(isAssured);
msg.setAssuredMode(assuredMode);
msg.setSafeDataLevel(safeDataLevel);
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ msg.setEclIncludes(entryAttrList);
+ }
// Check version of message
assertEquals(msg.getVersion(), REPLICATION_PROTOCOL_VLAST);
@@ -249,7 +263,7 @@
assertEquals(newMsg.isAssured(), msg.isAssured());
assertEquals(newMsg.getParentUid(), msg.getParentUid());
- // Create an add operation from each message to compare attributes (kept encoded in messages)
+ // Create an add operation from each message to compare attributes (kept encoded in messages)
Operation op = msg.createOperation(connection, rawDN);
Operation generatedOperation = newMsg.createOperation(connection, rawDN);
@@ -268,10 +282,15 @@
// Check default value for only VLAST fields
assertEquals(newMsg.getAssuredMode(), AssuredMode.SAFE_DATA_MODE);
assertEquals(newMsg.getSafeDataLevel(), (byte)1);
+ assertEquals(newMsg.getEclIncludes().size(), 0);
// Set again only VLAST fields
newMsg.setAssuredMode(assuredMode);
newMsg.setSafeDataLevel(safeDataLevel);
+ if (entryAttrList != null)
+ {
+ newMsg.setEclIncludes(entryAttrList);
+ }
// Serialize in VLAST msg
AddMsg vlastMsg = (AddMsg)ReplicationMsg.generateMsg(
@@ -289,6 +308,23 @@
assertEquals(msg.getAssuredMode(), vlastMsg.getAssuredMode());
assertEquals(msg.getSafeDataLevel(), vlastMsg.getSafeDataLevel());
+ // Get ECL entry attributes
+ ArrayList<RawAttribute> genAttrList = vlastMsg.getEclIncludes();
+ if (entryAttrList==null)
+ assertTrue(genAttrList.size()==0);
+ else
+ {
+ assertTrue(genAttrList.size()==entryAttrList.size());
+ int i=0;
+ for (Attribute eattr : entryAttrList)
+ {
+ assertTrue(eattr.getName().equalsIgnoreCase(genAttrList.get(i).toAttribute().getName()));
+ assertTrue(eattr.toString().equalsIgnoreCase(genAttrList.get(i).toAttribute().toString()),
+ "Comparing: " + eattr.toString() + " and " + genAttrList.get(i).toAttribute().toString());
+ i++;
+ }
+ }
+
// Create an add operation from each message to compare attributes (kept encoded in messages)
op = msg.createOperation(connection, rawDN);
generatedOperation = vlastMsg.createOperation(connection, rawDN);
@@ -310,11 +346,19 @@
* Build some data for the DeleteMsg test below.
*/
@DataProvider(name = "createDeleteData")
- public Object[][] createDeleteData() {
+ public Object[][] createDeleteData()
+ {
+ // Entry attributes
+ Attribute eattr1 = Attributes.create("description", "eav description");
+ Attribute eattr2 = Attributes.create("namingcontexts", "eav naming contexts");
+ List<Attribute> entryAttrList = new ArrayList<Attribute>();
+ entryAttrList.add(eattr1);
+ entryAttrList.add(eattr2);
+
return new Object[][] {
- {"dc=example,dc=com", false, AssuredMode.SAFE_DATA_MODE, (byte)0},
- {"dc=delete,dc=an,dc=entry,dc=with,dc=a,dc=long dn", true, AssuredMode.SAFE_READ_MODE, (byte)1},
- {"o=group,dc=example,dc=com", true, AssuredMode.SAFE_READ_MODE, (byte)3}};
+ {"dc=example,dc=com", false, AssuredMode.SAFE_DATA_MODE, (byte)0, null},
+ {"dc=delete,dc=an,dc=entry,dc=with,dc=a,dc=long dn", true, AssuredMode.SAFE_READ_MODE, (byte)1, entryAttrList},
+ {"o=group,dc=example,dc=com", true, AssuredMode.SAFE_READ_MODE, (byte)3, entryAttrList}};
}
/**
@@ -323,7 +367,7 @@
*/
@Test(dataProvider = "createDeleteData")
public void deleteMsgTestVLASTV2(String rawDN, boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
+ byte safeDataLevel, List<Attribute> entryAttrList)
throws Exception
{
// TODO: deleteMsgTestVLASTV2 as soon as V3 will have any incompatibility with V2
@@ -335,8 +379,8 @@
*/
@Test(dataProvider = "createDeleteData")
public void deleteMsgTestVLASTV1(String rawDN, boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
- throws Exception
+ byte safeDataLevel, List<Attribute> entryAttrList)
+ throws Exception
{
ChangeNumber cn = new ChangeNumber(TimeThread.getTime(),
(short) 123, (short) 45);
@@ -346,6 +390,12 @@
msg.setAssuredMode(assuredMode);
msg.setSafeDataLevel(safeDataLevel);
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ msg.setEclIncludes(entryAttrList);
+ }
+
// Check version of message
assertEquals(msg.getVersion(), REPLICATION_PROTOCOL_VLAST);
@@ -368,10 +418,16 @@
// Check default value for only VLAST fields
assertEquals(newMsg.getAssuredMode(), AssuredMode.SAFE_DATA_MODE);
assertEquals(newMsg.getSafeDataLevel(), (byte)1);
+ assertEquals(newMsg.getEclIncludes().size(), 0);
// Set again only VLAST fields
newMsg.setAssuredMode(assuredMode);
newMsg.setSafeDataLevel(safeDataLevel);
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ newMsg.setEclIncludes(entryAttrList);
+ }
// Serialize in VLAST msg
DeleteMsg vlastMsg = (DeleteMsg)ReplicationMsg.generateMsg(
@@ -380,13 +436,30 @@
// Check original version of message
assertEquals(vlastMsg.getVersion(), REPLICATION_PROTOCOL_VLAST);
- // Check we retrieve original V2 message (V2 fields)
+ // Check we retrieve original VLAST message (VLAST fields)
assertEquals(msg.getUniqueId(), vlastMsg.getUniqueId());
assertEquals(msg.getDn(), vlastMsg.getDn());
assertEquals(msg.getChangeNumber(), vlastMsg.getChangeNumber());
assertEquals(msg.isAssured(), vlastMsg.isAssured());
assertEquals(msg.getAssuredMode(), vlastMsg.getAssuredMode());
assertEquals(msg.getSafeDataLevel(), vlastMsg.getSafeDataLevel());
+
+ // Get ECL entry attributes
+ ArrayList<RawAttribute> genAttrList = vlastMsg.getEclIncludes();
+ if (entryAttrList==null)
+ assertTrue(genAttrList.size()==0);
+ else
+ {
+ assertTrue(genAttrList.size()==entryAttrList.size());
+ int i=0;
+ for (Attribute attr : entryAttrList)
+ {
+ assertTrue(attr.getName().equalsIgnoreCase(genAttrList.get(i).toAttribute().getName()));
+ assertTrue(attr.toString().equalsIgnoreCase(genAttrList.get(i).toAttribute().toString()),
+ "Comparing: " + attr.toString() + " and " + genAttrList.get(i).toAttribute().toString());
+ i++;
+ }
+ }
}
/**
@@ -434,17 +507,24 @@
List<Modification> mods5 = new ArrayList<Modification>();
mods5.add(mod5);
+ // Entry attributes
+ Attribute eattr1 = Attributes.create("description", "eav description");
+ Attribute eattr2 = Attributes.create("namingcontexts", "eav naming contexts");
+ List<Attribute> entryAttrList = new ArrayList<Attribute>();
+ entryAttrList.add(eattr1);
+ entryAttrList.add(eattr2);
+
return new Object[][] {
- { cn1, "dc=test", mods1, false, AssuredMode.SAFE_DATA_MODE, (byte)0},
- { cn2, "dc=cn2", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)1},
+ { cn1, "dc=test", mods1, false, AssuredMode.SAFE_DATA_MODE, (byte)0, null},
+ { cn2, "dc=cn2", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)1, entryAttrList},
{ cn2, "dc=test with a much longer dn in case this would "
- + "make a difference", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)3},
- { cn2, "dc=test, cn=with a, o=more complex, ou=dn", mods1, false, AssuredMode.SAFE_READ_MODE, (byte)5},
- { cn2, "cn=use\\, backslash", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)3},
- { cn2, "dc=test with several mod", mods2, false, AssuredMode.SAFE_DATA_MODE, (byte)16},
- { cn2, "dc=test with several values", mods3, false, AssuredMode.SAFE_READ_MODE, (byte)3},
- { cn2, "dc=test with long mod", mods4, true, AssuredMode.SAFE_READ_MODE, (byte)120},
- { cn2, "dc=testDsaOperation", mods5, true, AssuredMode.SAFE_DATA_MODE, (byte)99},
+ + "make a difference", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)3, null},
+ { cn2, "dc=test, cn=with a, o=more complex, ou=dn", mods1, false, AssuredMode.SAFE_READ_MODE, (byte)5, entryAttrList},
+ { cn2, "cn=use\\, backslash", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)3, null},
+ { cn2, "dc=test with several mod", mods2, false, AssuredMode.SAFE_DATA_MODE, (byte)16, entryAttrList},
+ { cn2, "dc=test with several values", mods3, false, AssuredMode.SAFE_READ_MODE, (byte)3, null},
+ { cn2, "dc=test with long mod", mods4, true, AssuredMode.SAFE_READ_MODE, (byte)120, entryAttrList},
+ { cn2, "dc=testDsaOperation", mods5, true, AssuredMode.SAFE_DATA_MODE, (byte)99, null},
};
}
@@ -456,7 +536,8 @@
public void modifyMsgTestVLASTV2(ChangeNumber changeNumber,
String rawdn, List<Modification> mods,
boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
+ byte safeDataLevel,
+ List<Attribute> entryAttrList)
throws Exception
{
// TODO: modifyMsgTestVLASTV2 as soon as V3 will have any incompatibility with V2
@@ -470,86 +551,120 @@
public void modifyMsgTestVLASTV1(ChangeNumber changeNumber,
String rawdn, List<Modification> mods,
boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
+ byte safeDataLevel,
+ List<Attribute> entryAttrList)
throws Exception
{
// Create VLAST message
DN dn = DN.decode(rawdn);
- ModifyMsg msg = new ModifyMsg(changeNumber, dn, mods, "fakeuniqueid");
+ ModifyMsg origVlastMsg = new ModifyMsg(changeNumber, dn, mods, "fakeuniqueid");
- msg.setAssured(isAssured);
- msg.setAssuredMode(assuredMode);
- msg.setSafeDataLevel(safeDataLevel);
+ origVlastMsg.setAssured(isAssured);
+ origVlastMsg.setAssuredMode(assuredMode);
+ origVlastMsg.setSafeDataLevel(safeDataLevel);
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ origVlastMsg.setEclIncludes(entryAttrList);
+ }
// Check version of message
- assertEquals(msg.getVersion(), REPLICATION_PROTOCOL_VLAST);
+ assertEquals(origVlastMsg.getVersion(), REPLICATION_PROTOCOL_VLAST);
// Serialize in V1
- byte[] v1MsgBytes = msg.getBytes(ProtocolVersion.REPLICATION_PROTOCOL_V1);
+ byte[] v1MsgBytes = origVlastMsg.getBytes(ProtocolVersion.REPLICATION_PROTOCOL_V1);
// Un-serialize V1 message
- ModifyMsg newMsg = (ModifyMsg)ReplicationMsg.generateMsg(
+ ModifyMsg newv1Msg = (ModifyMsg)ReplicationMsg.generateMsg(
v1MsgBytes, ProtocolVersion.REPLICATION_PROTOCOL_V1);
// Check original version of message
- assertEquals(newMsg.getVersion(), ProtocolVersion.REPLICATION_PROTOCOL_V1);
+ assertEquals(newv1Msg.getVersion(), ProtocolVersion.REPLICATION_PROTOCOL_V1);
// Check fields common to both versions
- assertEquals(newMsg.getUniqueId(), msg.getUniqueId());
- assertEquals(newMsg.getDn(), msg.getDn());
- assertEquals(newMsg.getChangeNumber(), msg.getChangeNumber());
- assertEquals(newMsg.isAssured(), msg.isAssured());
+ assertEquals(newv1Msg.getUniqueId(), origVlastMsg.getUniqueId());
+ assertEquals(newv1Msg.getDn(), origVlastMsg.getDn());
+ assertEquals(newv1Msg.getChangeNumber(), origVlastMsg.getChangeNumber());
+ assertEquals(newv1Msg.isAssured(), origVlastMsg.isAssured());
- // Create a modify operation from each message to compare mods (kept encoded in messages)
- Operation op = msg.createOperation(connection);
- Operation generatedOperation = newMsg.createOperation(connection);
+ // Create a modify operation from each message to compare mods (kept encoded in messages)
+ Operation opFromOrigVlast = origVlastMsg.createOperation(connection);
+ Operation opFromV1 = newv1Msg.createOperation(connection);
- assertEquals(op.getClass(), ModifyOperationBasis.class);
- assertEquals(generatedOperation.getClass(), ModifyOperationBasis.class);
- ModifyOperationBasis modOpBasis = (ModifyOperationBasis) op;
- ModifyOperationBasis genModOpBasis = (ModifyOperationBasis) generatedOperation;
+ assertEquals(opFromOrigVlast.getClass(), ModifyOperationBasis.class);
+ assertEquals(opFromV1.getClass(), ModifyOperationBasis.class);
+
+ ModifyOperationBasis modOpBasisFromOrigVlast = (ModifyOperationBasis) opFromOrigVlast;
+ ModifyOperationBasis genModOpBasisFromV1 = (ModifyOperationBasis) opFromV1;
- assertEquals(modOpBasis.getRawEntryDN(), genModOpBasis.getRawEntryDN());
- assertEquals( modOpBasis.getAttachment(SYNCHROCONTEXT),
- genModOpBasis.getAttachment(SYNCHROCONTEXT));
- assertEquals(modOpBasis.getModifications(), genModOpBasis.getModifications());
+ assertEquals(modOpBasisFromOrigVlast.getRawEntryDN(), genModOpBasisFromV1.getRawEntryDN());
+ assertEquals( modOpBasisFromOrigVlast.getAttachment(SYNCHROCONTEXT),
+ genModOpBasisFromV1.getAttachment(SYNCHROCONTEXT));
+ List<Modification> modsvlast = modOpBasisFromOrigVlast.getModifications();
+ List<Modification> modsv1 = genModOpBasisFromV1.getModifications();
+
+ assertEquals(modsvlast, modsv1);
// Check default value for only VLAST fields
- assertEquals(newMsg.getAssuredMode(), AssuredMode.SAFE_DATA_MODE);
- assertEquals(newMsg.getSafeDataLevel(), (byte)1);
+ assertEquals(newv1Msg.getAssuredMode(), AssuredMode.SAFE_DATA_MODE);
+ assertEquals(newv1Msg.getSafeDataLevel(), (byte)1);
// Set again only VLAST fields
- newMsg.setAssuredMode(assuredMode);
- newMsg.setSafeDataLevel(safeDataLevel);
-
+ newv1Msg.setAssuredMode(assuredMode);
+ newv1Msg.setSafeDataLevel(safeDataLevel);
+ if (entryAttrList != null)
+ {
+ newv1Msg.setEclIncludes(entryAttrList);
+ }
+
// Serialize in VLAST msg
- ModifyMsg vlastMsg = (ModifyMsg)ReplicationMsg.generateMsg(
- newMsg.getBytes(), ProtocolVersion.REPLICATION_PROTOCOL_V1);
+ ModifyMsg generatedVlastMsg = (ModifyMsg)ReplicationMsg.generateMsg(
+ newv1Msg.getBytes(), ProtocolVersion.REPLICATION_PROTOCOL_V1);
// Check original version of message
- assertEquals(vlastMsg.getVersion(), REPLICATION_PROTOCOL_VLAST);
+ assertEquals(generatedVlastMsg.getVersion(), REPLICATION_PROTOCOL_VLAST);
// Check we retrieve original VLAST message (VLAST fields)
- assertEquals(msg.getUniqueId(), vlastMsg.getUniqueId());
- assertEquals(msg.getDn(), vlastMsg.getDn());
- assertEquals(msg.getChangeNumber(), vlastMsg.getChangeNumber());
- assertEquals(msg.isAssured(), vlastMsg.isAssured());
- assertEquals(msg.getAssuredMode(), vlastMsg.getAssuredMode());
- assertEquals(msg.getSafeDataLevel(), vlastMsg.getSafeDataLevel());
+ assertEquals(origVlastMsg.getUniqueId(), generatedVlastMsg.getUniqueId());
+ assertEquals(origVlastMsg.getDn(), generatedVlastMsg.getDn());
+ assertEquals(origVlastMsg.getChangeNumber(), generatedVlastMsg.getChangeNumber());
+ assertEquals(origVlastMsg.isAssured(), generatedVlastMsg.isAssured());
+ assertEquals(origVlastMsg.getAssuredMode(), generatedVlastMsg.getAssuredMode());
+ assertEquals(origVlastMsg.getSafeDataLevel(), generatedVlastMsg.getSafeDataLevel());
+ assertEquals(origVlastMsg.getSafeDataLevel(), generatedVlastMsg.getSafeDataLevel());
+ // Get ECL entry attributes
+ ArrayList<RawAttribute> genAttrList = generatedVlastMsg.getEclIncludes();
+ if (entryAttrList==null)
+ assertTrue(genAttrList.size()==0);
+ else
+ {
+ assertTrue(genAttrList.size()==entryAttrList.size());
+ int i=0;
+ for (Attribute attr : entryAttrList)
+ {
+ assertTrue(attr.getName().equalsIgnoreCase(genAttrList.get(i).toAttribute().getName()));
+ assertTrue(attr.toString().equalsIgnoreCase(genAttrList.get(i).toAttribute().toString()),
+ "Comparing: " + attr.toString() + " and " + genAttrList.get(i).toAttribute().toString());
+ i++;
+ }
+ }
- // Create a modify operation from each message to compare mods (kept encoded in messages)
- op = msg.createOperation(connection);
- generatedOperation = vlastMsg.createOperation(connection);
+ // Create a modify operation from each message to compare mods (kept encoded in messages)
+ opFromOrigVlast = origVlastMsg.createOperation(connection);
+ Operation opFromGeneratedVlastMsg = generatedVlastMsg.createOperation(connection);
- assertEquals(op.getClass(), ModifyOperationBasis.class);
- assertEquals(generatedOperation.getClass(), ModifyOperationBasis.class);
- modOpBasis = (ModifyOperationBasis) op;
- genModOpBasis = (ModifyOperationBasis) generatedOperation;
+ assertEquals(opFromOrigVlast.getClass(), ModifyOperationBasis.class);
+ assertEquals(opFromGeneratedVlastMsg.getClass(), ModifyOperationBasis.class);
- assertEquals(modOpBasis.getRawEntryDN(), genModOpBasis.getRawEntryDN());
- assertEquals( modOpBasis.getAttachment(SYNCHROCONTEXT),
- genModOpBasis.getAttachment(SYNCHROCONTEXT));
- assertEquals(modOpBasis.getModifications(), genModOpBasis.getModifications());
+ modOpBasisFromOrigVlast = (ModifyOperationBasis) opFromOrigVlast;
+ ModifyOperationBasis modOpBasisFromGeneratedVlast = (ModifyOperationBasis) opFromGeneratedVlastMsg;
+
+ assertEquals(modOpBasisFromOrigVlast.getRawEntryDN(),
+ modOpBasisFromGeneratedVlast.getRawEntryDN());
+ assertEquals( modOpBasisFromOrigVlast.getAttachment(SYNCHROCONTEXT),
+ modOpBasisFromGeneratedVlast.getAttachment(SYNCHROCONTEXT));
+ assertEquals(modOpBasisFromOrigVlast.getModifications(),
+ modOpBasisFromGeneratedVlast.getModifications());
}
@DataProvider(name = "createModifyDnData")
@@ -586,12 +701,19 @@
mods4.add(mod);
}
+ // Entry attributes
+ Attribute eattr1 = Attributes.create("description", "eav description");
+ Attribute eattr2 = Attributes.create("namingcontexts", "eav naming contexts");
+ List<Attribute> entryAttrList = new ArrayList<Attribute>();
+ entryAttrList.add(eattr1);
+ entryAttrList.add(eattr2);
+
return new Object[][] {
- {"dc=test,dc=com", "dc=new", "11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222", false, "dc=change", mods1, false, AssuredMode.SAFE_DATA_MODE, (byte)0},
- {"dc=test,dc=com", "dc=new", "33333333-3333-3333-3333-333333333333", "44444444-4444-4444-4444-444444444444", true, "dc=change", mods2, true, AssuredMode.SAFE_READ_MODE, (byte)1},
- {"dc=test,dc=com", "dc=new", "55555555-5555-5555-5555-555555555555", "66666666-6666-6666-6666-666666666666", false, null, mods3, true, AssuredMode.SAFE_READ_MODE, (byte)3},
+ {"dc=test,dc=com", "dc=new", "11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222", false, "dc=change", mods1, false, AssuredMode.SAFE_DATA_MODE, (byte)0, null},
+ {"dc=test,dc=com", "dc=new", "33333333-3333-3333-3333-333333333333", "44444444-4444-4444-4444-444444444444", true, "dc=change", mods2, true, AssuredMode.SAFE_READ_MODE, (byte)1, entryAttrList},
+ {"dc=test,dc=com", "dc=new", "55555555-5555-5555-5555-555555555555", "66666666-6666-6666-6666-666666666666", false, null, mods3, true, AssuredMode.SAFE_READ_MODE, (byte)3, null},
{"dc=delete,dc=an,dc=entry,dc=with,dc=a,dc=long dn",
- "dc=new", "77777777-7777-7777-7777-777777777777", "88888888-8888-8888-8888-888888888888",true, null, mods4, true, AssuredMode.SAFE_DATA_MODE, (byte)99},
+ "dc=new", "77777777-7777-7777-7777-777777777777", "88888888-8888-8888-8888-888888888888",true, null, mods4, true, AssuredMode.SAFE_DATA_MODE, (byte)99, entryAttrList},
};
}
@@ -603,7 +725,8 @@
public void modifyDnMsgTestVLASTV2(String rawDN, String newRdn, String uid, String newParentUid,
boolean deleteOldRdn, String newSuperior,
List<Modification> mods, boolean isAssured,
- AssuredMode assuredMode, byte safeDataLevel)
+ AssuredMode assuredMode, byte safeDataLevel,
+ List<Attribute> entryAttrList)
throws Exception
{
// TODO: modifyMsgTestVLASTV2 as soon as V3 will have any incompatibility with V2
@@ -617,7 +740,8 @@
public void modifyDnMsgTestVLASTV1(String rawDN, String newRdn, String uid, String newParentUid,
boolean deleteOldRdn, String newSuperior,
List<Modification> mods, boolean isAssured,
- AssuredMode assuredMode, byte safeDataLevel)
+ AssuredMode assuredMode, byte safeDataLevel,
+ List<Attribute> entryAttrList)
throws Exception
{
// Create VLAST message
@@ -631,6 +755,12 @@
msg.setAssuredMode(assuredMode);
msg.setSafeDataLevel(safeDataLevel);
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ msg.setEclIncludes(entryAttrList);
+ }
+
// Check version of message
assertEquals(msg.getVersion(), REPLICATION_PROTOCOL_VLAST);
@@ -654,7 +784,7 @@
assertEquals(newMsg.getNewSuperiorId(), msg.getNewSuperiorId());
assertEquals(newMsg.deleteOldRdn(), msg.deleteOldRdn());
- // Create a modDn operation from each message to compare fields)
+ // Create a modDn operation from each message to compare fields)
Operation op = msg.createOperation(connection);
Operation generatedOperation = newMsg.createOperation(connection);
@@ -677,6 +807,11 @@
newMsg.setAssuredMode(assuredMode);
newMsg.setSafeDataLevel(safeDataLevel);
newMsg.setMods(mods);
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ newMsg.setEclIncludes(entryAttrList);
+ }
// Serialize in VLAST msg
ModifyDNMsg vlastMsg = (ModifyDNMsg)ReplicationMsg.generateMsg(
@@ -697,7 +832,24 @@
assertEquals(msg.getNewSuperiorId(), vlastMsg.getNewSuperiorId());
assertEquals(msg.deleteOldRdn(), vlastMsg.deleteOldRdn());
- // Create a modDn operation from each message to compare mods (kept encoded in messages)
+ // Get ECL entry attributes
+ ArrayList<RawAttribute> genAttrList = vlastMsg.getEclIncludes();
+ if (entryAttrList==null)
+ assertTrue(genAttrList.size()==0);
+ else
+ {
+ assertTrue(genAttrList.size()==entryAttrList.size());
+ int i=0;
+ for (Attribute attr : entryAttrList)
+ {
+ assertTrue(attr.getName().equalsIgnoreCase(genAttrList.get(i).toAttribute().getName()));
+ assertTrue(attr.toString().equalsIgnoreCase(genAttrList.get(i).toAttribute().toString()),
+ "Comparing: " + attr.toString() + " and " + genAttrList.get(i).toAttribute().toString());
+ i++;
+ }
+ }
+
+ // Create a modDn operation from each message to compare mods (kept encoded in messages)
op = msg.createOperation(connection);
generatedOperation = vlastMsg.createOperation(connection);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
index c73ac80..a3a7b3b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
@@ -36,8 +36,10 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import java.util.UUID;
import java.util.zip.DataFormatException;
@@ -47,6 +49,7 @@
import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyDNOperationBasis;
+import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.ReplicationTestCase;
@@ -67,10 +70,12 @@
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Operation;
import org.opends.server.types.RDN;
+import org.opends.server.types.RawAttribute;
import org.opends.server.util.TimeThread;
import org.opends.server.workflowelement.localbackend.LocalBackendAddOperation;
import org.opends.server.workflowelement.localbackend.LocalBackendDeleteOperation;
import org.opends.server.workflowelement.localbackend.LocalBackendModifyDNOperation;
+import org.opends.server.workflowelement.localbackend.LocalBackendModifyOperation;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -141,17 +146,24 @@
List<Modification> mods5 = new ArrayList<Modification>();
mods5.add(mod5);
+ // Entry attributes
+ Attribute eattr1 = Attributes.create("description", "eav description");
+ Attribute eattr2 = Attributes.create("namingcontexts", "eav naming contexts");
+ List<Attribute> eclIncludes = new ArrayList<Attribute>();
+ eclIncludes.add(eattr1);
+ eclIncludes.add(eattr2);
+
return new Object[][] {
- { cn1, "dc=test", mods1, false, AssuredMode.SAFE_DATA_MODE, (byte)0},
- { cn2, "dc=cn2", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)1},
+ { cn1, "dc=test", mods1, false, AssuredMode.SAFE_DATA_MODE, (byte)0, null},
+ { cn2, "dc=cn2", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)1, eclIncludes},
{ cn2, "dc=test with a much longer dn in case this would "
- + "make a difference", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)3},
- { cn2, "dc=test, cn=with a, o=more complex, ou=dn", mods1, false, AssuredMode.SAFE_READ_MODE, (byte)5},
- { cn2, "cn=use\\, backslash", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)3},
- { cn2, "dc=test with several mod", mods2, false, AssuredMode.SAFE_DATA_MODE, (byte)16},
- { cn2, "dc=test with several values", mods3, false, AssuredMode.SAFE_READ_MODE, (byte)3},
- { cn2, "dc=test with long mod", mods4, true, AssuredMode.SAFE_READ_MODE, (byte)120},
- { cn2, "dc=testDsaOperation", mods5, true, AssuredMode.SAFE_DATA_MODE, (byte)99},
+ + "make a difference", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)3, null},
+ { cn2, "dc=test, cn=with a, o=more complex, ou=dn", mods1, false, AssuredMode.SAFE_READ_MODE, (byte)5, eclIncludes},
+ { cn2, "cn=use\\, backslash", mods1, true, AssuredMode.SAFE_READ_MODE, (byte)3, null},
+ { cn2, "dc=test with several mod", mods2, false, AssuredMode.SAFE_DATA_MODE, (byte)16, eclIncludes},
+ { cn2, "dc=test with several values", mods3, false, AssuredMode.SAFE_READ_MODE, (byte)3, null},
+ { cn2, "dc=test with long mod", mods4, true, AssuredMode.SAFE_READ_MODE, (byte)120, eclIncludes},
+ { cn2, "dc=testDsaOperation", mods5, true, AssuredMode.SAFE_DATA_MODE, (byte)99, null},
};
}
@@ -161,11 +173,12 @@
* create another ModifyMsg from the encoded byte array.
* Finally test that both Msg matches.
*/
- @Test(dataProvider = "createModifyData")
+ @Test(enabled=true,dataProvider = "createModifyData")
public void modifyMsgTest(ChangeNumber changeNumber,
String rawdn, List<Modification> mods,
boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
+ byte safeDataLevel,
+ List<Attribute> entryAttrList)
throws Exception
{
DN dn = DN.decode(rawdn);
@@ -177,6 +190,12 @@
msg.setAssuredMode(assuredMode);
msg.setSafeDataLevel(safeDataLevel);
+ // Set ECL entry inlcuded attributes
+ if (entryAttrList != null)
+ {
+ msg.setEclIncludes(entryAttrList);
+ }
+
ModifyMsg generatedMsg = (ModifyMsg) ReplicationMsg.generateMsg(
msg.getBytes(), ProtocolVersion.getCurrentVersion());
@@ -187,6 +206,23 @@
assertEquals(msg.getChangeNumber(), generatedMsg.getChangeNumber());
+ // Get ECL entry attributes
+ ArrayList<RawAttribute> genAttrList = generatedMsg.getEclIncludes();
+ if (entryAttrList==null)
+ assertTrue(genAttrList.size()==0);
+ else
+ {
+ assertTrue(genAttrList.size()==entryAttrList.size());
+ int i=0;
+ for (Attribute attr : entryAttrList)
+ {
+ assertTrue(attr.getName().equalsIgnoreCase(genAttrList.get(i).toAttribute().getName()));
+ assertTrue(attr.toString().equalsIgnoreCase(genAttrList.get(i).toAttribute().toString()),
+ "Comparing: " + attr.toString() + " and " + genAttrList.get(i).toAttribute().toString());
+ i++;
+ }
+ }
+
Operation op = msg.createOperation(connection);
Operation generatedOperation = generatedMsg.createOperation(connection);
@@ -208,11 +244,12 @@
* create another ModifyMsg from the encoded byte array.
* Finally test that both Msgs match.
*/
- @Test(dataProvider = "createModifyData")
+ @Test(enabled=true,dataProvider = "createModifyData")
public void updateMsgTest(ChangeNumber changeNumber,
String rawdn, List<Modification> mods,
boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
+ byte safeDataLevel ,
+ List<Attribute> entryAttrList)
throws Exception
{
DN dn = DN.decode(rawdn);
@@ -272,10 +309,19 @@
* Build some data for the DeleteMsg test below.
*/
@DataProvider(name = "createDeleteData")
- public Object[][] createDeleteData() {
+ public Object[][] createDeleteData()
+ {
+
+ // Entry attributes
+ Attribute eattr1 = Attributes.create("description", "eav description");
+ Attribute eattr2 = Attributes.create("namingcontexts", "eav naming contexts");
+ List<Attribute> entryAttrList = new ArrayList<Attribute>();
+ entryAttrList.add(eattr1);
+ entryAttrList.add(eattr2);
+
return new Object[][] {
- {"dc=com"},
- {"dc=delete,dc=an,dc=entry,dc=with,dc=a,dc=long dn"},
+ {"dc=com", entryAttrList},
+ {"dc=delete,dc=an,dc=entry,dc=with,dc=a,dc=long dn", null},
};
}
@@ -285,9 +331,9 @@
* create another DeleteMsg from the encoded byte array.
* Finally test that both Msg matches.
*/
- @Test(dataProvider = "createDeleteData")
- public void deleteMsgTest(String rawDN)
- throws Exception
+ @Test(enabled=true,dataProvider = "createDeleteData")
+ public void deleteMsgTest(String rawDN, List<Attribute> entryAttrList)
+ throws Exception
{
InternalClientConnection connection =
InternalClientConnection.getRootConnection();
@@ -298,6 +344,13 @@
(short) 123, (short) 45);
op.setAttachment(SYNCHROCONTEXT, new DeleteContext(cn, "uniqueid"));
DeleteMsg msg = new DeleteMsg(op);
+
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ msg.setEclIncludes(entryAttrList);
+ }
+
DeleteMsg generatedMsg = (DeleteMsg) ReplicationMsg.generateMsg(
msg.getBytes(), ProtocolVersion.getCurrentVersion());
@@ -305,6 +358,23 @@
assertEquals(msg.getChangeNumber(), generatedMsg.getChangeNumber());
+ // Get ECL entry attributes
+ ArrayList<RawAttribute> genAttrList = generatedMsg.getEclIncludes();
+ if (entryAttrList==null)
+ assertTrue(genAttrList.size()==0);
+ else
+ {
+ assertTrue(genAttrList.size()==entryAttrList.size());
+ int i=0;
+ for (Attribute attr : entryAttrList)
+ {
+ assertTrue(attr.getName().equalsIgnoreCase(genAttrList.get(i).toAttribute().getName()));
+ assertTrue(attr.toString().equalsIgnoreCase(genAttrList.get(i).toAttribute().toString()),
+ "Comparing: " + attr.toString() + " and " + genAttrList.get(i).toAttribute().toString());
+ i++;
+ }
+ }
+
Operation generatedOperation = generatedMsg.createOperation(connection);
assertEquals(generatedOperation.getClass(), DeleteOperationBasis.class);
@@ -352,23 +422,31 @@
mods4.add(mod);
}
+ // Entry attributes
+ Attribute eattr1 = Attributes.create("description", "eav description");
+ Attribute eattr2 = Attributes.create("namingcontexts", "eav naming contexts");
+ List<Attribute> entryAttrList = new ArrayList<Attribute>();
+ entryAttrList.add(eattr1);
+ entryAttrList.add(eattr2);
+
+
return new Object[][] {
- {"dc=test,dc=com", "dc=new", false, "dc=change", mods1, false, AssuredMode.SAFE_DATA_MODE, (byte)0},
- {"dc=test,dc=com", "dc=new", true, "dc=change", mods2, true, AssuredMode.SAFE_READ_MODE, (byte)1},
+ {"dc=test,dc=com", "dc=new", false, "dc=change", mods1, false, AssuredMode.SAFE_DATA_MODE, (byte)0, entryAttrList},
+ {"dc=test,dc=com", "dc=new", true, "dc=change", mods2, true, AssuredMode.SAFE_READ_MODE, (byte)1, null},
// testNG does not like null argument so use "" for the newSuperior
// instead of null
- {"dc=test,dc=com", "dc=new", false, "", mods3, true, AssuredMode.SAFE_READ_MODE, (byte)3},
+ {"dc=test,dc=com", "dc=new", false, "", mods3, true, AssuredMode.SAFE_READ_MODE, (byte)3, entryAttrList},
{"dc=delete,dc=an,dc=entry,dc=with,dc=a,dc=long dn",
- "dc=new", true, "", mods4, true, AssuredMode.SAFE_DATA_MODE, (byte)99},
+ "dc=new", true, "", mods4, true, AssuredMode.SAFE_DATA_MODE, (byte)99, null},
};
}
- @Test(dataProvider = "createModifyDnData")
+ @Test(enabled=true,dataProvider = "createModifyDnData")
public void modifyDnMsgTest(String rawDN, String newRdn,
boolean deleteOldRdn, String newSuperior,
List<Modification> mods, boolean isAssured,
AssuredMode assuredMode,
- byte safeDataLevel)
+ byte safeDataLevel, List<Attribute> entryAttrList)
throws Exception
{
InternalClientConnection connection =
@@ -392,6 +470,12 @@
msg.setAssuredMode(assuredMode);
msg.setSafeDataLevel(safeDataLevel);
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ msg.setEclIncludes(entryAttrList);
+ }
+
ModifyDNMsg generatedMsg = (ModifyDNMsg) ReplicationMsg
.generateMsg(msg.getBytes(), ProtocolVersion.getCurrentVersion());
@@ -400,6 +484,23 @@
assertEquals(generatedMsg.getAssuredMode(), assuredMode);
assertEquals(generatedMsg.getSafeDataLevel(), safeDataLevel);
+ // Get ECL entry attributes
+ ArrayList<RawAttribute> genAttrList = generatedMsg.getEclIncludes();
+ if (entryAttrList==null)
+ assertTrue(genAttrList.size()==0);
+ else
+ {
+ assertTrue(genAttrList.size()==entryAttrList.size());
+ int i=0;
+ for (Attribute attr : entryAttrList)
+ {
+ assertTrue(attr.getName().equalsIgnoreCase(genAttrList.get(i).toAttribute().getName()));
+ assertTrue(attr.toString().equalsIgnoreCase(genAttrList.get(i).toAttribute().toString()),
+ "Comparing: " + attr.toString() + " and " + genAttrList.get(i).toAttribute().toString());
+ i++;
+ }
+ }
+
Operation oriOp = msg.createOperation(connection);
Operation generatedOperation = generatedMsg.createOperation(connection);
@@ -422,16 +523,24 @@
}
@DataProvider(name = "createAddData")
- public Object[][] createAddData() {
+ public Object[][] createAddData()
+ {
+
+ // Entry attributes
+ Attribute eattr1 = Attributes.create("description", "eav description");
+ Attribute eattr2 = Attributes.create("namingcontexts", "eav naming contexts");
+ List<Attribute> entryAttrList = new ArrayList<Attribute>();
+ entryAttrList.add(eattr1);
+ entryAttrList.add(eattr2);
return new Object[][] {
- {"dc=example,dc=com", false, AssuredMode.SAFE_DATA_MODE, (byte)0},
- {"o=test", true, AssuredMode.SAFE_READ_MODE, (byte)1},
- {"o=group,dc=example,dc=com", true, AssuredMode.SAFE_READ_MODE, (byte)3}};
+ {"dc=example,dc=com", false, AssuredMode.SAFE_DATA_MODE, (byte)0, entryAttrList},
+ {"o=test", true, AssuredMode.SAFE_READ_MODE, (byte)1, null},
+ {"o=group,dc=example,dc=com", true, AssuredMode.SAFE_READ_MODE, (byte)3, entryAttrList}};
}
- @Test(dataProvider = "createAddData")
+ @Test(enabled=true,dataProvider = "createAddData")
public void addMsgTest(String rawDN, boolean isAssured, AssuredMode assuredMode,
- byte safeDataLevel)
+ byte safeDataLevel, List<Attribute> entryAttrList)
throws Exception
{
Attribute objectClass = Attributes.create(DirectoryServer
@@ -465,6 +574,12 @@
msg.setAssuredMode(assuredMode);
msg.setSafeDataLevel(safeDataLevel);
+ // Set ECL entry attributes
+ if (entryAttrList != null)
+ {
+ msg.setEclIncludes(entryAttrList);
+ }
+
AddMsg generatedMsg = (AddMsg) ReplicationMsg.generateMsg(msg
.getBytes(), ProtocolVersion.getCurrentVersion());
assertEquals(msg.getBytes(), generatedMsg.getBytes());
@@ -476,6 +591,24 @@
assertEquals(generatedMsg.getAssuredMode(), assuredMode);
assertEquals(generatedMsg.getSafeDataLevel(), safeDataLevel);
+ // Get ECL entry attributes
+ ArrayList<RawAttribute> genAttrList = generatedMsg.getEclIncludes();
+ if (entryAttrList==null)
+ assertTrue(genAttrList.size()==0);
+ else
+ {
+ assertTrue(genAttrList.size()==entryAttrList.size());
+ int i=0;
+ for (Attribute eattr : entryAttrList)
+ {
+ assertTrue(eattr.getName().equalsIgnoreCase(genAttrList.get(i).toAttribute().getName()));
+ assertTrue(eattr.toString().equalsIgnoreCase(genAttrList.get(i).toAttribute().toString()),
+ "Comparing: " + eattr.toString() + " and " + genAttrList.get(i).toAttribute().toString());
+ i++;
+ }
+ }
+
+
// Create an new Add Operation from the current addMsg
InternalClientConnection connection =
InternalClientConnection.getRootConnection();
@@ -514,6 +647,11 @@
generatedMsg.setAssuredMode(assuredMode);
generatedMsg.setSafeDataLevel(safeDataLevel);
+ if (entryAttrList != null)
+ {
+ generatedMsg.setEclIncludes(entryAttrList);
+ }
+
assertEquals(msg.getBytes(), generatedMsg.getBytes());
assertEquals(msg.toString(), generatedMsg.toString());
// TODO : should test that generated attributes match original attributes.
@@ -562,7 +700,7 @@
};
}
- @Test(dataProvider = "createAckData")
+ @Test(enabled=true,dataProvider = "createAckData")
public void ackMsgTest(ChangeNumber cn, boolean hasTimeout, boolean hasWrongStatus,
boolean hasReplayError, List<Short> failedServers)
throws Exception
@@ -615,7 +753,7 @@
msg1.getBytes(), ProtocolVersion.getCurrentVersion());
}
- @Test()
+ @Test(enabled=true)
public void eclUpdateMsg()
throws Exception
{
@@ -681,7 +819,7 @@
* Test that ServerStartMsg encoding and decoding works
* by checking that : msg == new ServerStartMsg(msg.getBytes()).
*/
- @Test(dataProvider="createServerStartData")
+ @Test(enabled=true,dataProvider="createServerStartData")
public void serverStartMsgTest(short serverId, String baseDN, int window,
ServerState state, long genId, boolean sslEncryption, byte groupId) throws Exception
{
@@ -720,7 +858,7 @@
* Test that ReplServerStartMsg encoding and decoding works
* by checking that : msg == new ReplServerStartMsg(msg.getBytes()).
*/
- @Test(dataProvider="createReplServerStartData")
+ @Test(enabled=true,dataProvider="createReplServerStartData")
public void replServerStartMsgTest(short serverId, String baseDN, int window,
String url, ServerState state, long genId, byte groupId, int degTh) throws Exception
{
@@ -783,17 +921,25 @@
urls4.add("ldaps://host:port/dc=foobar1??sub?(sn=Another Entry 1)");
urls4.add("ldaps://host:port/dc=foobar2??sub?(sn=Another Entry 2)");
+ Set<String> a1 = new HashSet<String>();
+ Set<String> a2 = new HashSet<String>();
+ a2.add("dc");
+ Set<String> a3 = new HashSet<String>();
+ a3.add("dc");
+ a3.add("uid");
+ Set<String> a4 = new HashSet<String>();
+
DSInfo dsInfo1 = new DSInfo((short)13, (short)26, (long)154631, ServerStatus.FULL_UPDATE_STATUS,
- false, AssuredMode.SAFE_DATA_MODE, (byte)12, (byte)132, urls1);
+ false, AssuredMode.SAFE_DATA_MODE, (byte)12, (byte)132, urls1, a1);
DSInfo dsInfo2 = new DSInfo((short)-436, (short)493, (long)-227896, ServerStatus.DEGRADED_STATUS,
- true, AssuredMode.SAFE_READ_MODE, (byte)-7, (byte)-265, urls2);
+ true, AssuredMode.SAFE_READ_MODE, (byte)-7, (byte)-265, urls2, a2);
DSInfo dsInfo3 = new DSInfo((short)2436, (short)591, (long)0, ServerStatus.NORMAL_STATUS,
- false, AssuredMode.SAFE_READ_MODE, (byte)17, (byte)0, urls3);
+ false, AssuredMode.SAFE_READ_MODE, (byte)17, (byte)0, urls3, a3);
DSInfo dsInfo4 = new DSInfo((short)415, (short)146, (long)0, ServerStatus.BAD_GEN_ID_STATUS,
- true, AssuredMode.SAFE_DATA_MODE, (byte)2, (byte)15, urls4);
+ true, AssuredMode.SAFE_DATA_MODE, (byte)2, (byte)15, urls4, a4);
List<DSInfo> dsList1 = new ArrayList<DSInfo>();
dsList1.add(dsInfo1);
@@ -824,25 +970,27 @@
rsList2.add(rsInfo3);
return new Object [][] {
- {dsList1, rsList1},
- {dsList2, rsList2},
- {dsList3, rsList1},
- {dsList3, null},
- {null, rsList1},
- {null, null},
- {dsList4, rsList2}
+ {dsList1, rsList1, a1},
+ {dsList2, rsList2, a2},
+ {dsList3, rsList1, a3},
+ {dsList3, null, null},
+ {null, rsList1, a1},
+ {null, null, a2},
+ {dsList4, rsList2, a3}
};
}
/**
* Test TopologyMsg encoding and decoding.
*/
- @Test(dataProvider = "createTopologyData")
- public void topologyMsgTest(List<DSInfo> dsList, List<RSInfo> rsList)
+ @Test(enabled=true,dataProvider = "createTopologyData")
+ public void topologyMsgTest(List<DSInfo> dsList, List<RSInfo> rsList,
+ Set<String> attrs)
throws Exception
{
TopologyMsg msg = new TopologyMsg(dsList, rsList);
- TopologyMsg newMsg = new TopologyMsg(msg.getBytes());
+ TopologyMsg newMsg = new TopologyMsg(msg.getBytes(),
+ ProtocolVersion.getCurrentVersion());
assertEquals(msg.getDsList(), newMsg.getDsList());
assertEquals(msg.getRsList(), newMsg.getRsList());
}
@@ -879,32 +1027,44 @@
urls6.add("ldaps://host:port/dc=foo??sub?(sn=Fourth Entry)");
urls6.add("ldaps://host:port/dc=foo??sub?(sn=Fifth Entry)");
+ Set<String> a1 = new HashSet<String>();
+ Set<String> a2 = new HashSet<String>();
+ a2.add("dc");
+ Set<String> a3 = new HashSet<String>();
+ a3.add("dc");
+ a3.add("uid");
+
return new Object[][]{
- {ServerStatus.NORMAL_STATUS, urls1, true, AssuredMode.SAFE_DATA_MODE, (byte)1},
- {ServerStatus.DEGRADED_STATUS, urls2, false, AssuredMode.SAFE_READ_MODE, (byte)123},
- {ServerStatus.FULL_UPDATE_STATUS, urls3, false, AssuredMode.SAFE_DATA_MODE, (byte)111},
- {ServerStatus.NORMAL_STATUS, urls4, true, AssuredMode.SAFE_READ_MODE, (byte)-1},
- {ServerStatus.DEGRADED_STATUS, urls5, true, AssuredMode.SAFE_DATA_MODE, (byte)97},
- {ServerStatus.FULL_UPDATE_STATUS, urls6, false, AssuredMode.SAFE_READ_MODE, (byte)-13}
+ {ServerStatus.NORMAL_STATUS, urls1, true, AssuredMode.SAFE_DATA_MODE, (byte)1, a1},
+ {ServerStatus.DEGRADED_STATUS, urls2, false, AssuredMode.SAFE_READ_MODE, (byte)123, a2},
+ {ServerStatus.FULL_UPDATE_STATUS, urls3, false, AssuredMode.SAFE_DATA_MODE, (byte)111, a3},
+ {ServerStatus.NORMAL_STATUS, urls4, true, AssuredMode.SAFE_READ_MODE, (byte)-1, a1},
+ {ServerStatus.DEGRADED_STATUS, urls5, true, AssuredMode.SAFE_DATA_MODE, (byte)97, a2},
+ {ServerStatus.FULL_UPDATE_STATUS, urls6, false, AssuredMode.SAFE_READ_MODE, (byte)-13, a3}
};
}
/**
* Test StartSessionMsg encoding and decoding.
*/
- @Test(dataProvider = "createStartSessionData")
+ @Test(enabled=true,dataProvider = "createStartSessionData")
public void startSessionMsgTest(ServerStatus status, List<String> refUrls,
- boolean assuredFlag, AssuredMode assuredMode, byte safedataLevel)
+ boolean assuredFlag, AssuredMode assuredMode, byte safedataLevel,
+ Set<String> attrs)
throws Exception
{
StartSessionMsg msg = new StartSessionMsg(status, refUrls, assuredFlag,
assuredMode, safedataLevel);
- StartSessionMsg newMsg = new StartSessionMsg(msg.getBytes());
+ msg.setEclIncludes(attrs);
+ StartSessionMsg newMsg =
+ new StartSessionMsg(msg.getBytes(),ProtocolVersion.getCurrentVersion());
assertEquals(msg.getStatus(), newMsg.getStatus());
assertTrue(msg.isAssured() == newMsg.isAssured());
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());
}
/**
@@ -923,7 +1083,7 @@
/**
* Test ChangeStatusMsg encoding and decoding.
*/
- @Test(dataProvider = "createChangeStatusData")
+ @Test(enabled=true,dataProvider = "createChangeStatusData")
public void changeStatusMsgTest(ServerStatus reqStatus, ServerStatus newStatus)
throws Exception
{
@@ -1174,7 +1334,7 @@
* Test that ServerStartMsg encoding and decoding works
* by checking that : msg == new ServerStartMsg(msg.getBytes()).
*/
- @Test(dataProvider="createServerStartData")
+ @Test(enabled=true,dataProvider="createServerStartData")
public void startECLMsgTest(short serverId, String baseDN, int window,
ServerState state, long genId, boolean sslEncryption, byte groupId) throws Exception
{
@@ -1250,4 +1410,262 @@
assertTrue(dn1found);
assertTrue(dn2found);
}
+
+ int perfRep = 100000;
+
+
+ @Test(enabled=false,dataProvider = "createAddData")
+ public void addMsgPerfs(String rawDN, boolean isAssured, AssuredMode assuredMode,
+ byte safeDataLevel, List<Attribute> entryAttrList)
+ throws Exception
+ {
+ long createop = 0;
+ long createmsgfromop = 0;
+ long encodemsg = 0;
+ long getbytes = 0;
+ long alld = 0;
+ long setentryattr = 0;
+ long buildnew = 0;
+ long t1,t2,t3,t31,t4,t5,t6 = 0;
+
+ HashMap<ObjectClass, String> objectClassList = new HashMap<ObjectClass, String>();
+ objectClassList.put(DirectoryServer.getObjectClass("organization"),
+ "organization");
+
+ ArrayList<Attribute> userAttributes = new ArrayList<Attribute>(1);
+ Attribute attr = Attributes.create("o", "com");
+ userAttributes.add(attr);
+ HashMap<AttributeType, List<Attribute>> userAttList = new HashMap<AttributeType, List<Attribute>>();
+ userAttList.put(attr.getAttributeType(), userAttributes);
+
+
+ ArrayList<Attribute> operationalAttributes = new ArrayList<Attribute>(1);
+ attr = Attributes.create("creatorsname", "dc=creator");
+ operationalAttributes.add(attr);
+ HashMap<AttributeType,List<Attribute>> opList=
+ new HashMap<AttributeType,List<Attribute>>();
+ opList.put(attr.getAttributeType(), operationalAttributes);
+
+ ChangeNumber cn = new ChangeNumber(TimeThread.getTime(),
+ (short) 123, (short) 45);
+ DN dn = DN.decode(rawDN);
+
+ for (int i=1;i<perfRep;i++)
+ {
+ t1 = System.nanoTime();
+
+ // create op
+ AddOperation addOpB = new AddOperationBasis(connection,
+ (long) 1, 1, null, dn, objectClassList, userAttList, opList);
+ LocalBackendAddOperation addOp = new LocalBackendAddOperation(addOpB);
+ OperationContext opCtx = new AddContext(cn, "thisIsaUniqueID",
+ "parentUniqueId");
+ addOp.setAttachment(SYNCHROCONTEXT, opCtx);
+ t2 = System.nanoTime();
+ createop += (t2 - t1);
+
+ // create msg from op
+ AddMsg generatedMsg = new AddMsg(addOp);
+ t3 = System.nanoTime();
+ createmsgfromop += (t3 - t2);
+
+ // set entry attr
+ generatedMsg.setEclIncludes(entryAttrList);
+ t31 = System.nanoTime();
+ setentryattr += (t31 - t3);
+
+ // encode msg
+ generatedMsg.encode();
+ t4 = System.nanoTime();
+ encodemsg += (t4 - t31);
+
+ // getBytes
+ byte[] bytes = generatedMsg.getBytes(ProtocolVersion.getCurrentVersion());
+ t5 = System.nanoTime();
+ getbytes += (t5 - t4);
+
+ // getBytes
+ new AddMsg(bytes);
+ t6 = System.nanoTime();
+ buildnew += (t6 - t5);
+
+ alld += (t6 - t1);
+ }
+
+ System.out.println(
+ "addMsgPerfs "
+ + "createop\t"
+ + "createmsgfromop\t"
+ + "setentryattr\t"
+ + "encodemsg\t"
+ + "getbytes\t"
+ + "buildnew\t");
+
+ System.out.println(
+ "addMsgPerfs "
+ + createop/perfRep/1000.0 + " μs \t"
+ + createmsgfromop/perfRep/1000.0 + " μs \t"
+ + setentryattr/perfRep/1000.0 + " μs \t"
+ + encodemsg/perfRep/1000.0 + " μs \t"
+ + getbytes/perfRep/1000.0 + " μs \t"
+ + buildnew/perfRep/1000.0 + " μs \t");
+ }
+
+ @Test(enabled=false,dataProvider = "createModifyData")
+ public void modMsgPerfs(ChangeNumber changeNumber,
+ String rawdn, List<Modification> mods,
+ boolean isAssured, AssuredMode assuredMode,
+ byte safeDataLevel, List<Attribute> entryAttrList)
+ throws Exception
+ {
+ long createop = 0;
+ long createmsgfromop = 0;
+ long encodemsg = 0;
+ long getbytes = 0;
+ long alld = 0;
+ long setentryattr = 0;
+ long buildnew = 0;
+ long t1,t2,t3,t31,t4,t5,t6 = 0;
+
+ ChangeNumber cn = new ChangeNumber(TimeThread.getTime(),
+ (short) 123, (short) 45);
+ DN dn = DN.decode(rawdn);
+
+ for (int i=1;i<perfRep;i++)
+ {
+ t1 = System.nanoTime();
+
+ // create op
+ ModifyOperation modifyOpB = new ModifyOperationBasis(
+ connection, (long)1, 1, null, dn, mods);
+ LocalBackendModifyOperation modifyOp =
+ new LocalBackendModifyOperation(modifyOpB);
+ OperationContext opCtx = new ModifyContext(cn, "thisIsaUniqueID");
+ modifyOp.setAttachment(SYNCHROCONTEXT, opCtx);
+ t2 = System.nanoTime();
+ createop += (t2 - t1);
+
+ // create msg from op
+ ModifyMsg generatedMsg = new ModifyMsg(modifyOp);
+ t3 = System.nanoTime();
+ createmsgfromop += (t3 - t2);
+
+ // set entry attr
+ // generatedMsg.setEntryAttributes(entryAttrList);
+ t31 = System.nanoTime();
+ setentryattr += (t31 - t3);
+
+ // encode msg
+ generatedMsg.encode();
+ t4 = System.nanoTime();
+ encodemsg += (t4 - t31);
+
+ // getBytes
+ byte[] bytes = generatedMsg.getBytes(ProtocolVersion.getCurrentVersion());
+ t5 = System.nanoTime();
+ getbytes += (t5 - t4);
+
+ // getBytes
+ new ModifyMsg(bytes);
+ t6 = System.nanoTime();
+ buildnew += (t6 - t5);
+
+ alld += (t6 - t1);
+ }
+
+ System.out.println(
+ "modMsgPerfs "
+ + "createop\t"
+ + "createmsgfromop\t"
+ + "setentryattr\t"
+ + "encodemsg\t"
+ + "getbytes\t"
+ + "buildnew\t");
+
+ System.out.println(
+ "modMsgPerfs "
+ + createop/perfRep/1000.0 + " μs \t"
+ + createmsgfromop/perfRep/1000.0 + " μs \t"
+ + setentryattr/perfRep/1000.0 + " μs \t"
+ + encodemsg/perfRep/1000.0 + " μs \t"
+ + getbytes/perfRep/1000.0 + " μs \t"
+ + buildnew/perfRep/1000.0 + " μs \t");
+ }
+
+ @Test(enabled=false,dataProvider = "createDeleteData")
+ public void deleteMsgPerfs(String rawDN, List<Attribute> entryAttrList)
+ throws Exception
+ {
+ InternalClientConnection connection =
+ InternalClientConnection.getRootConnection();
+
+ long createop = 0;
+ long createmsgfromop = 0;
+ long encodemsg = 0;
+ long getbytes = 0;
+ long alld = 0;
+ long setentryattr = 0;
+ long buildnew = 0;
+ long t1,t2,t3,t31,t4,t5,t6 = 0;
+
+ for (int i=1;i<perfRep;i++)
+ {
+ t1 = System.nanoTime();
+
+ // create op
+ DeleteOperationBasis opBasis =
+ new DeleteOperationBasis(connection, 1, 1,null, DN.decode(rawDN));
+ LocalBackendDeleteOperation op = new LocalBackendDeleteOperation(opBasis);
+ ChangeNumber cn = new ChangeNumber(TimeThread.getTime(),
+ (short) 123, (short) 45);
+ op.setAttachment(SYNCHROCONTEXT, new DeleteContext(cn, "uniqueid"));
+ t2 = System.nanoTime();
+ createop += (t2 - t1);
+
+ // create msg from op
+ DeleteMsg generatedMsg = new DeleteMsg(op);
+ t3 = System.nanoTime();
+ createmsgfromop += (t3 - t2);
+
+ // set entry attr
+ //generatedMsg.setEntryAttributes(entryAttrList);
+ t31 = System.nanoTime();
+ setentryattr += (t31 - t3);
+
+ // encode msg
+ generatedMsg.encode();
+ t4 = System.nanoTime();
+ encodemsg += (t4 - t31);
+
+ // getBytes
+ byte[] bytes = generatedMsg.getBytes(ProtocolVersion.getCurrentVersion());
+ t5 = System.nanoTime();
+ getbytes += (t5 - t4);
+
+ // getBytes
+ new DeleteMsg(bytes);
+ t6 = System.nanoTime();
+ buildnew += (t6 - t5);
+
+ alld += (t6 - t1);
+ }
+
+ System.out.println(
+ "deleteMsgPerfs "
+ + "createop\t"
+ + "createmsgfromop\t"
+ + "setentryattr\t"
+ + "encodemsg\t"
+ + "getbytes\t"
+ + "buildnew\t");
+
+ System.out.println(
+ "deleteMsgPerfs "
+ + createop/perfRep/1000.0 + " μs \t"
+ + createmsgfromop/perfRep/1000.0 + " μs \t"
+ + setentryattr/perfRep/1000.0 + " μs \t"
+ + encodemsg/perfRep/1000.0 + " μs \t"
+ + getbytes/perfRep/1000.0 + " μs \t"
+ + buildnew/perfRep/1000.0 + " μs \t");
+ }
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/FakeReplicationDomain.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/FakeReplicationDomain.java
index fbb952e..06a801b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/FakeReplicationDomain.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/FakeReplicationDomain.java
@@ -123,7 +123,6 @@
protected void importBackend(InputStream input) throws DirectoryException
{
byte[] buffer = new byte[1000];
-
int ret;
do
{
@@ -136,7 +135,8 @@
ResultCode.OPERATIONS_ERROR,
ERR_BACKEND_EXPORT_ENTRY.get("", ""));
}
- importString.append(new String(buffer, 0, ret));
+ if (ret>0)
+ importString.append(new String(buffer, 0, ret));
}
while (ret >= 0);
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java
index 773babb..d1d639b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java
@@ -152,28 +152,45 @@
assertTrue(replServerInfo.getGenerationId() == 2);
}
- for (DSInfo serverInfo : domain1.getReplicasList())
+ int sleepTime = 50;
+ while (true)
{
- if (serverInfo.getDsId() == domain2ServerId)
- assertEquals(serverInfo.getStatus(), ServerStatus.BAD_GEN_ID_STATUS);
- else
+ try
{
- assertTrue(serverInfo.getDsId() == domain1ServerId);
- assertTrue(serverInfo.getStatus() == ServerStatus.NORMAL_STATUS);
- }
- }
+ for (DSInfo serverInfo : domain1.getReplicasList())
+ {
+ if (serverInfo.getDsId() == domain2ServerId)
+ assertEquals(serverInfo.getStatus(), ServerStatus.BAD_GEN_ID_STATUS);
+ else
+ {
+ assertTrue(serverInfo.getDsId() == domain1ServerId);
+ assertTrue(serverInfo.getStatus() == ServerStatus.NORMAL_STATUS);
+ }
+ }
- for (DSInfo serverInfo : domain2.getReplicasList())
- {
- if (serverInfo.getDsId() == domain2ServerId)
- assertTrue(serverInfo.getStatus() == ServerStatus.BAD_GEN_ID_STATUS);
- else
+ for (DSInfo serverInfo : domain2.getReplicasList())
+ {
+ if (serverInfo.getDsId() == domain2ServerId)
+ assertTrue(serverInfo.getStatus() == ServerStatus.BAD_GEN_ID_STATUS);
+ else
+ {
+ assertTrue(serverInfo.getDsId() == domain1ServerId);
+ assertTrue(serverInfo.getStatus() == ServerStatus.NORMAL_STATUS);
+ }
+ }
+ break;
+ }
+ catch (AssertionError e)
{
- assertTrue(serverInfo.getDsId() == domain1ServerId);
- assertTrue(serverInfo.getStatus() == ServerStatus.NORMAL_STATUS);
- }
+ if (sleepTime < 30000)
+ {
+ Thread.sleep(sleepTime);
+ sleepTime *=2;
+ }
+ else
+ throw e;
+ }
}
-
Map<Short, ServerState> states1 = domain1.getReplicaStates();
ServerState state2 = states1.get(domain2ServerId);
assertNotNull(state2, "getReplicaStates is not showing DS2");
--
Gitblit v1.10.0