From b5acb25ee2ad9bf8b166b9de1a34e6aab6ea23b7 Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Fri, 01 Sep 2006 12:04:47 +0000
Subject: [PATCH] issue 604 : solve the naming conflict that might happen when several masters are used there are 3 main parts in this commit : - attach the replication context in an OperationContext - if operation replay fails then fix the problem  - in the pre-op checks for conflict and cause failure if necessary most of the time there should be no conflict and the operation should be processed normally

---
 opends/src/server/org/opends/server/synchronization/AddMsg.java |  121 ++++++++++++++++++----------------------
 1 files changed, 54 insertions(+), 67 deletions(-)

diff --git a/opends/src/server/org/opends/server/synchronization/AddMsg.java b/opends/src/server/org/opends/server/synchronization/AddMsg.java
index 31aa4c9..d177029 100644
--- a/opends/src/server/org/opends/server/synchronization/AddMsg.java
+++ b/opends/src/server/org/opends/server/synchronization/AddMsg.java
@@ -45,7 +45,7 @@
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeValue;
 
-import static org.opends.server.synchronization.SynchMessages.*;
+import static org.opends.server.synchronization.OperationContext.*;
 import static org.opends.server.util.StaticUtils.toLowerCase;
 
 /**
@@ -55,8 +55,8 @@
 public class AddMsg extends UpdateMessage
 {
   private static final long serialVersionUID = -4905520652801395185L;
-  private String dn;
   private byte[] encodedAttributes ;
+  private String parentUniqueId;
 
   /**
    * Creates a new AddMessage.
@@ -64,6 +64,12 @@
    */
   public AddMsg(AddOperation op)
   {
+    super((AddContext) op.getAttachment(SYNCHROCONTEXT),
+          op.getRawEntryDN().stringValue());
+
+    AddContext ctx = (AddContext) op.getAttachment(SYNCHROCONTEXT);
+    this.parentUniqueId = ctx.getParentUid();
+
     // Encode the object classes (SET OF LDAPString).
     LinkedHashSet<AttributeValue> ocValues =
       new LinkedHashSet<AttributeValue>(op.getObjectClasses().size());
@@ -99,12 +105,8 @@
       }
     }
 
-    dn = op.getRawEntryDN().stringValue();
-
     // Encode the sequence.
     encodedAttributes = ASN1Element.encodeValue(elems);
-
-    changeNumber = (ChangeNumber) op.getAttachment(SYNCHRONIZATION);
   }
 
   /**
@@ -112,18 +114,22 @@
    *
    * @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)
   {
-    this.dn = dn;
-    this.changeNumber = cn;
+    super (new AddContext(cn, uniqueId, parentId), dn);
+    this.parentUniqueId = parentId;
 
     ArrayList<ASN1Element> elems = new ArrayList<ASN1Element>();
     elems.add(new LDAPAttribute(objectClass).encode());
@@ -142,40 +148,29 @@
    *
    * @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
+  public AddMsg(byte[] in) throws DataFormatException,
+                                  UnsupportedEncodingException
   {
-    /* first byte is the type */
-    if (in[0] != MSG_TYPE_ADD_REQUEST)
-      throw new DataFormatException("byte[] is not a valid add msg");
-    int pos = 1;
+    super(in);
 
-    /* read the dn
-     * first calculate the length then construct the string
-     */
-    int length = 0;
-    int offset = pos;
-    while (in[pos++] != 0)
+    int  pos = decodeHeader(MSG_TYPE_ADD_REQUEST, in);
+
+    // read the parent unique Id
+    int length = getNextLength(in, pos);
+    if (length != 0)
     {
-      if (pos > in.length)
-        throw new DataFormatException("byte[] is not a valid add msg");
-      length++;
+      parentUniqueId = new String(in, pos, length, "UTF-8");
+      pos += length + 1;
     }
-    try
+    else
     {
-      dn = new String(in, offset, length, "UTF-8");
-
-      /* read the changeNumber
-       * it is always 24 characters long
-       */
-      String changenumberStr = new  String(in, pos, 24, "UTF-8");
-      changeNumber = new ChangeNumber(changenumberStr);
-      pos +=24;
-    } catch (UnsupportedEncodingException e ) {
-      throw new DataFormatException("UTF-8 is not supported by this jvm.");
+      parentUniqueId = null;
+      pos += 1;
     }
 
-    /* Read the attributes : all the remaining bytes */
+    // Read the attributes : all the remaining bytes
     encodedAttributes = new byte[in.length-pos];
     int i =0;
     while (pos<in.length)
@@ -185,14 +180,11 @@
   }
 
   /**
-   * Create and return an AddOperation from a received ADD message.
-   * @param connection The connection where we received the message.
-   * @return The created operation.
-   * @throws LDAPException In case msg encoding was not valid.
-   * @throws ASN1Exception In case msg encoding was not valid.
+   * {@inheritDoc}
    */
   @Override
-  public AddOperation createOperation(InternalClientConnection connection)
+  public AddOperation createOperation(InternalClientConnection connection,
+                                      String newDn)
                       throws LDAPException, ASN1Exception
   {
     ArrayList<LDAPAttribute> attr = new ArrayList<LDAPAttribute>();
@@ -207,9 +199,10 @@
     AddOperation add =  new AddOperation(connection,
                             InternalClientConnection.nextOperationID(),
                             InternalClientConnection.nextMessageID(), null,
-                            new ASN1OctetString(dn), attr);
-
-    add.setAttachment(SYNCHRONIZATION, getChangeNumber());
+                            new ASN1OctetString(newDn), attr);
+    AddContext ctx = new AddContext(getChangeNumber(), getUniqueId(),
+                                    parentUniqueId);
+    add.setAttachment(SYNCHROCONTEXT, ctx);
     return add;
   }
 
@@ -220,36 +213,30 @@
   @Override
   public byte[] getBytes()
   {
-    byte[] byteDn;
     try
     {
-      byteDn = dn.getBytes("UTF-8");
-
-      /* The ad message is stored in the form :
-       * <operation type><dn><changenumber><attributes>
-       * the length of result byte array is therefore :
-       *   1 + dn length + 1 + 24 + attribute length
-       */
-      int length = 1 + byteDn.length + 1  + 24 + encodedAttributes.length;
-      byte[] resultByteArray = new byte[length];
-      int pos = 1;
-
-      /* put the type of the operation */
-      resultByteArray[0] = MSG_TYPE_ADD_REQUEST;
-      /* put the DN and a terminating 0 */
-      for (int i = 0; i< byteDn.length; i++,pos++)
+      int length = encodedAttributes.length;
+      byte[] byteParentId = null;
+      if (parentUniqueId != null)
       {
-        resultByteArray[pos] = byteDn[i];
+        byteParentId = parentUniqueId.getBytes("UTF-8");
+        length += byteParentId.length + 1;
       }
-      resultByteArray[pos++] = 0;
-      /* put the ChangeNumber */
-      byte[] changeNumberByte =
-                      this.getChangeNumber().toString().getBytes("UTF-8");
-      for (int i=0; i<24; i++,pos++)
+      else
       {
-        resultByteArray[pos] = changeNumberByte[i];
+        length += 1;
       }
 
+      /* encode the header in a byte[] large enough to also contain the mods */
+      byte [] resultByteArray = encodeHeader(MSG_TYPE_ADD_REQUEST, 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++)
       {
@@ -271,6 +258,6 @@
   @Override
   public String toString()
   {
-    return ("ADD " + dn + " " + getChangeNumber());
+    return ("ADD " + getDn() + " " + getChangeNumber());
   }
 }

--
Gitblit v1.10.0