From 480d1e397ffc67edd17eb505ccb292ae5ef6b6c9 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Mon, 23 Jan 2012 14:51:36 +0000
Subject: [PATCH] Fix OPENDJ-410: Frequent corruption in ds-sync-hist ordering index

---
 opendj-sdk/opends/src/messages/messages/replication.properties                                           |    4 +
 opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java |   50 ++++++++++++++----------
 opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java            |   26 ------------
 3 files changed, 33 insertions(+), 47 deletions(-)

diff --git a/opendj-sdk/opends/src/messages/messages/replication.properties b/opendj-sdk/opends/src/messages/messages/replication.properties
index 8e31ab8..928d4df 100644
--- a/opendj-sdk/opends/src/messages/messages/replication.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication.properties
@@ -21,7 +21,7 @@
 # CDDL HEADER END
 #
 #      Copyright 2006-2010 Sun Microsystems, Inc.
-#      Portions copyright 2011 ForgeRock AS
+#      Portions copyright 2011-2012 ForgeRock AS
 #
 #
 # This file contains the primary Directory Server configuration.  It must not
@@ -541,3 +541,5 @@
 NOTICE_LOAD_BALANCE_REPLICATION_SERVER_213=Directory Server DS(%d) is disconnecting \
  from replication server RS(%d) at %s for domain "%s" in order to find another \
  replication server in the topology and distribute load more equally
+SEVERE_WARN_INVALID_SYNC_HIST_VALUE_214=The attribute value '%s' is not a valid \
+ synchronization history value
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java
index 6c754e6..5949680 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java
@@ -23,15 +23,19 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
+ *      Portions copyright 2012 ForgeRock AS.
  */
 package org.opends.server.replication.plugin;
 
+import static org.opends.messages.ReplicationMessages.*;
+import static org.opends.server.util.StaticUtils.hexStringToByteArray;
+
 import java.util.Collection;
 import java.util.Collections;
+
 import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
-import org.opends.server.types.ByteString;
-import org.opends.server.types.ByteSequence;
+import org.opends.server.types.*;
 
 /**
  * Used to establish an order between historical information and index them.
@@ -122,30 +126,34 @@
   }
 
   /**
-   * Normalize historical information representation.
-   * @param value the value that must be normalized
-   * @return The String form that must be used for historical information
-   * comparison
+   * {@inheritDoc}
    */
   @Override
   public ByteString normalizeValue(ByteSequence value)
+      throws DirectoryException
   {
-    String[] token = value.toString().split(":", 3);
-
-    /* Change the format of the value to index and start
-     * with the serverId. In that manner, the search response
-     * time is optimised for a particulare serverId.
-     * The format of the key is now :
-     * serverId + timestamp + seqNum
+    /*
+     * Change the format of the value to index and start with the serverId. In
+     * that manner, the search response time is optimised for a particular
+     * serverId. The format of the key is now : serverId + timestamp + seqNum
      */
-    String timestamp = token[1].substring(0,16);
-    String serverId = token[1].substring(16,20);
-    String seqNumber = token[1].substring(20, 28);
-
-    if (MultimasterReplication.isLocalServerId(Integer.parseInt(serverId, 16)))
-      return ByteString.valueOf(serverId + timestamp + seqNumber);
-    else
-      return (ByteString.valueOf("0"));
+    try
+    {
+      int csnIndex = value.toString().indexOf(':') + 1;
+      String csn = value.subSequence(csnIndex, csnIndex + 28).toString();
+      ByteStringBuilder builder = new ByteStringBuilder(14);
+      builder.append(hexStringToByteArray(csn.substring(16, 20)));
+      builder.append(hexStringToByteArray(csn.substring(00, 16)));
+      builder.append(hexStringToByteArray(csn.substring(20, 28)));
+      return builder.toByteString();
+    }
+    catch (Exception e)
+    {
+      // This should never occur in practice since these attributes are managed
+      // internally.
+      throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
+          WARN_INVALID_SYNC_HIST_VALUE.get(String.valueOf(value)), e);
+    }
   }
 
   /**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
index 80acfb0..304a757 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
@@ -23,7 +23,7 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2011 ForgeRock AS
+ *      Portions Copyright 2011-2012 ForgeRock AS
  */
 package org.opends.server.replication.plugin;
 
@@ -120,8 +120,6 @@
 
   private boolean isRegistered = false;
 
-  private static boolean initializationCompleted = true;
-
   /**
    * The configurable connection/handshake timeout.
    */
@@ -276,7 +274,6 @@
       ReplicationSynchronizationProviderCfg configuration)
   throws ConfigException
   {
-    initializationCompleted = false;
     domains.clear();
     replicationServerListener = new ReplicationServerListener(configuration);
 
@@ -318,8 +315,6 @@
 
     DirectoryServer.registerSupportedControl(
         ReplicationRepairRequestControl.OID_REPLICATION_REPAIR_CONTROL);
-
-    initializationCompleted = true;
   }
 
   /**
@@ -874,25 +869,6 @@
   }
 
   /**
-   * Checks if a given serverID is used by a local Replication Domain.
-   *
-   * @param serverId   The serverID that should be checked.
-   * @return           true if the serverID is local, false otherwise.
-   */
-  public static boolean isLocalServerId(Integer serverId)
-  {
-    if (!initializationCompleted)
-      return true;
-
-    for (LDAPReplicationDomain domain : domains.values())
-    {
-      if (domain.getServerId() == serverId)
-        return true;
-    }
-    return false;
-  }
-
-  /**
    * Returns the connection timeout in milli-seconds.
    *
    * @return The connection timeout in milli-seconds.

--
Gitblit v1.10.0