From d408e72de6b31ec6e44a073beb47c067f09fea78 Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Wed, 12 Jul 2006 09:23:19 +0000
Subject: [PATCH] - pre-operation plugins are not called anymore when processing synchronization operations   for ADD,DELELTE and MODIFYDN as it was already the case for MODIFY operation   This is necessary to make sure that entries use the same unique ID everywhere.

---
 opends/src/server/org/opends/server/synchronization/ServerState.java |  134 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/opends/src/server/org/opends/server/synchronization/ServerState.java b/opends/src/server/org/opends/server/synchronization/ServerState.java
index 91b7091..3dd71f2 100644
--- a/opends/src/server/org/opends/server/synchronization/ServerState.java
+++ b/opends/src/server/org/opends/server/synchronization/ServerState.java
@@ -38,8 +38,10 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
+import java.util.zip.DataFormatException;
 
 import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
 
 import org.opends.server.core.AddOperation;
 import org.opends.server.types.Control;
@@ -72,16 +74,21 @@
  * from each server.
  * It is exchanged with the changelog servers at connection establishment time
  * It is locally saved in the database
+ * TODO : should extract from this object the code that read/save
+ * from/to the database on the LDAP server side and put it in a new class
+ * that is only used on the LDAP server side and that encapsulate this class.
  */
 public class ServerState implements Serializable
 {
   private static final long serialVersionUID = 314772980474416183L;
-  private static final String SYNCHRONIZATION_STATE = "ds-sync-state";
+
   private HashMap<Short, ChangeNumber> list;
+  transient private static final String
+                                  SYNCHRONIZATION_STATE = "ds-sync-state";
   transient private DN baseDn;
   transient boolean savedStatus = true;
   transient private InternalClientConnection conn =
-    new InternalClientConnection();
+                                              new InternalClientConnection();
   transient private ASN1OctetString serverStateAsn1Dn;
   transient private DN serverStateDn;
 
@@ -106,6 +113,74 @@
   }
 
   /**
+   * Creates a new ServerState object from its encoded form.
+   *
+   * @param in The byte array containing the encoded ServerState form.
+   * @param pos The position in the byte array where the encoded ServerState
+   *            starts.
+   * @param endpos The position in the byte array where the encoded ServerState
+   *               ends.
+   * @throws DataFormatException If the encoded form was not correct.
+   */
+  public ServerState(byte[] in, int pos, int endpos)
+         throws DataFormatException
+  {
+    try
+    {
+      list = new HashMap<Short, ChangeNumber>();
+
+      while (endpos > pos)
+      {
+        /*
+         * read the ServerId
+         */
+        int length = getNextLength(in, pos);
+        String serverIdString = new String(in, pos, length, "UTF-8");
+        short serverId = Short.valueOf(serverIdString);
+        pos += length +1;
+
+        /*
+         * read the ChangeNumber
+         */
+        length = getNextLength(in, pos);
+        String cnString = new String(in, pos, length, "UTF-8");
+        ChangeNumber cn = new ChangeNumber(cnString);
+        pos += length +1;
+
+        /*
+         * Add the serverid
+         */
+        list.put(serverId, cn);
+      }
+
+    } catch (UnsupportedEncodingException e)
+    {
+      throw new DataFormatException("UTF-8 is not supported by this jvm.");
+    }
+  }
+
+  /**
+   * Get the length of the next String encoded in the in byte array.
+   *
+   * @param in the byte array where to calculate the string.
+   * @param pos the position whre to start from in the byte array.
+   * @return the length of the next string.
+   * @throws DataFormatException If the byte array does not end with null.
+   */
+  private int getNextLength(byte[] in, int pos) throws DataFormatException
+  {
+    int offset = pos;
+    int length = 0;
+    while (in[offset++] != 0)
+    {
+      if (offset >= in.length)
+        throw new DataFormatException("byte[] is not a valid modify msg");
+      length++;
+    }
+    return length;
+  }
+
+  /**
    * Update the Server State with a ChangeNumber.
    * All operations with smaller CSN and the same serverID must be committed
    * before calling this method.
@@ -197,7 +272,7 @@
    */
   public void save()
   {
-    if (list.size() == 0)
+    if ((list.size() == 0) || savedStatus)
       return;
 
     ArrayList<ASN1OctetString> values = new ArrayList<ASN1OctetString>();
@@ -208,6 +283,7 @@
         ASN1OctetString value = new ASN1OctetString(list.get(id).toString());
         values.add(value);
       }
+      savedStatus = true;
     }
     LDAPAttribute attr = new LDAPAttribute(SYNCHRONIZATION_STATE, values);
     LDAPModification mod = new LDAPModification(ModificationType.REPLACE, attr);
@@ -239,6 +315,7 @@
         }
         else
         {
+          savedStatus = false;
           int msgID = MSGID_ERROR_UPDATING_RUV;
           String message = getMessage(msgID,
               op.getResultCode().getResultCodeName(),
@@ -388,4 +465,55 @@
     return serverStateDn;
   }
 
+  /**
+   * Add the tail into resultByteArray at position pos.
+   */
+  private int addByteArray(byte[] tail, byte[] resultByteArray, int pos)
+  {
+    for (int i=0; i<tail.length; i++,pos++)
+    {
+      resultByteArray[pos] = tail[i];
+    }
+    resultByteArray[pos++] = 0;
+    return pos;
+  }
+
+  /**
+   * Encode this ServerState object and return its byte array representation.
+   *
+   * @return a byte array with an encoded representation of this object.
+   * @throws UnsupportedEncodingException if UTF8 is not supported by the JVM.
+   */
+  public byte[] getBytes() throws UnsupportedEncodingException
+  {
+    synchronized (this)
+    {
+      int length = 0;
+      List<String> idList = new ArrayList<String>(list.size());
+      for (short id : list.keySet())
+      {
+        String temp = String.valueOf(id);
+        idList.add(temp);
+        length += temp.length() + 1;
+      }
+      List<String> cnList = new ArrayList<String>(list.size());
+      for (ChangeNumber cn : list.values())
+      {
+        String temp = cn.toString();
+        cnList.add(temp);
+        length += temp.length() + 1;
+      }
+      byte[] result = new byte[length];
+
+      int pos = 0;
+      for (int i=0; i< list.size(); i++)
+      {
+        String str = idList.get(i);
+        pos = addByteArray(str.getBytes("UTF-8"), result, pos);
+        str = cnList.get(i);
+        pos = addByteArray(str.getBytes("UTF-8"), result, pos);
+      }
+      return result;
+    }
+  }
 }

--
Gitblit v1.10.0