From b4f8838b15342670c31753a484abf0129e3c9653 Mon Sep 17 00:00:00 2001
From: jcduff <jcduff@localhost>
Date: Thu, 23 Oct 2008 14:04:24 +0000
Subject: [PATCH] The commit will bring the following features :     - An updated version of the underlying database. BDB JE 3.3 is now used.     - Attribute API refactoring providing a better abstraction and offering improved performances.     - A new GUI called the Control-Panel to replace the Status-Panel: the specifications for this       GUI are available on OpenDS Wiki and contains a link to a mockup.        See <https://www.opends.org/wiki/page/ControlPanelUISpecification>.     - Some changes in the replication protocol to implement "Assured Replication Mode". The        specifications are on OpenDS Wiki at <https://www.opends.org/wiki/page/AssuredMode> and section 7       described some of the replication changes required to support this. Assured Replication is not finished,       but the main replication protocol changes to support it are done. As explained by Gilles on an email on       the Dev mailing list (http://markmail.org/message/46rgo3meq3vriy4a), with these changes the newer versions       of OpenDS may not be able to replicate with OpenDS 1.0 instances.     - Support for Service Tags on the platforms where the functionality is available and enabled. Specifications       are published at <https://www.opends.org/wiki/page/OpenDSServiceTagEnabled>. For more information on       Service Tags see <http://wikis.sun.com/display/ServiceTag/Sun+Service+Tag+FAQ>.     - The Admin Connector service. In order to provide agentry of the OpenDS server at any time, a new service       has been added, dedicated to the administration, configuration and monitoring of the server.       An overview of the Admin Connector service and it's use is available on the       OpenDS wiki <https://www.opends.org/wiki/page/ManagingAdministrationTrafficToTheServer>     - Updates to the various command line tools to support the Admin Connector service.     - Some internal re-architecting of the server to put the foundation of future developments such as virtual       directory services. The new NetworkGroups and WorkFlow internal services which have been specified in       <https://www.opends.org/wiki/page/BasicOperationRoutingThroughNetworkGroup> are now implemented.     - Many bug fixes...

---
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java |   99 +++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 82 insertions(+), 17 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java
index f30edf3..60d06c8 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ServerWriter.java
@@ -39,8 +39,9 @@
 
 import org.opends.server.api.DirectoryThread;
 import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.replication.common.ServerStatus;
 import org.opends.server.replication.protocol.ProtocolSession;
-import org.opends.server.replication.protocol.UpdateMessage;
+import org.opends.server.replication.protocol.UpdateMsg;
 
 
 /**
@@ -58,6 +59,7 @@
   private ServerHandler handler;
   private ReplicationServerDomain replicationServerDomain;
   private short serverId;
+  private short protocolVersion = -1;
 
   /**
    * Create a ServerWriter.
@@ -74,12 +76,15 @@
                       ServerHandler handler,
                       ReplicationServerDomain replicationServerDomain)
   {
-    super(handler.toString() + " writer");
+    super("Replication Writer for " + handler.toString() + " in RS " +
+      replicationServerDomain.getReplicationServer().getServerId());
 
     this.serverId = serverId;
     this.session = session;
     this.handler = handler;
     this.replicationServerDomain = replicationServerDomain;
+    // Keep protocol version locally for efficiency
+    this.protocolVersion = handler.getProtocolVersion();
   }
 
   /**
@@ -104,24 +109,70 @@
     {
       while (true)
       {
-        UpdateMessage update = replicationServerDomain.take(this.handler);
+        UpdateMsg update = replicationServerDomain.take(this.handler);
         if (update == null)
           return;       /* this connection is closing */
 
-        // Ignore update to be sent to a replica with a bad generation ID
-        long referenceGenerationId = replicationServerDomain.getGenerationId();
-        if ((referenceGenerationId != handler.getGenerationId())
-            || (referenceGenerationId == -1)
-            || (handler.getGenerationId() == -1))
+        /* Ignore updates in some cases */
+        if (handler.isLDAPserver())
         {
-          logError(ERR_IGNORING_UPDATE_TO.get(
-              this.replicationServerDomain.getReplicationServer().
-                getMonitorInstanceName(),
-              update.getDn(),
-              this.handler.getMonitorInstanceName(),
+          /**
+           * Ignore updates to DS in bad BAD_GENID_STATUS or FULL_UPDATE_STATUS
+           *
+           * The RSD lock should not be taken here as it is acceptable to have a
+           * delay between the time the server has a wrong status and the fact
+           * we detect it: the updates that succeed to pass during this time
+           * will have no impact on remote server. But it is interesting to not
+           * saturate uselessly the network if the updates are not necessary so
+           * this check to stop sending updates is interesting anyway. Not
+           * taking the RSD lock allows to have better performances in normal
+           * mode (most of the time).
+           */
+          ServerStatus dsStatus = handler.getStatus();
+          if ((dsStatus == ServerStatus.BAD_GEN_ID_STATUS) ||
+            (dsStatus == ServerStatus.FULL_UPDATE_STATUS))
+          {
+            long referenceGenerationId =
+              replicationServerDomain.getGenerationId();
+            if (dsStatus == ServerStatus.BAD_GEN_ID_STATUS)
+              logError(ERR_IGNORING_UPDATE_TO_DS_BADGENID.get(
+                Short.toString(replicationServerDomain.getReplicationServer().
+                getServerId()),
+                replicationServerDomain.getBaseDn().toNormalizedString(),
+                update.getChangeNumber().toString(),
+                Short.toString(handler.getServerId()),
+                Long.toString(handler.getGenerationId()),
+                Long.toString(referenceGenerationId)));
+            if (dsStatus == ServerStatus.FULL_UPDATE_STATUS)
+              logError(ERR_IGNORING_UPDATE_TO_DS_FULLUP.get(
+                Short.toString(replicationServerDomain.getReplicationServer().
+                getServerId()),
+                replicationServerDomain.getBaseDn().toNormalizedString(),
+                update.getChangeNumber().toString(),
+                Short.toString(handler.getServerId())));
+            continue;
+          }
+        } else
+        {
+          /**
+           * Ignore updates to RS with bad gen id
+           * (no system managed status for a RS)
+           */
+          long referenceGenerationId =
+            replicationServerDomain.getGenerationId();
+          if ((referenceGenerationId != handler.getGenerationId()) ||
+            (referenceGenerationId == -1) || (handler.getGenerationId() == -1))
+          {
+            logError(ERR_IGNORING_UPDATE_TO_RS.get(
+              Short.toString(replicationServerDomain.getReplicationServer().
+              getServerId()),
+              replicationServerDomain.getBaseDn().toNormalizedString(),
+              update.getChangeNumber().toString(),
+              Short.toString(handler.getServerId()),
               Long.toString(handler.getGenerationId()),
               Long.toString(referenceGenerationId)));
-          continue;
+            continue;
+          }
         }
 
         /*
@@ -137,7 +188,17 @@
             " generationId=" + handler.getGenerationId());
         }
         */
-        session.publish(update);
+
+        // Publish the update to the remote server using a protocol version he
+        // it supports
+        short pduProtocolVersion = update.getVersion();
+        if (protocolVersion < pduProtocolVersion)
+        { // The remote server wants a lower protocol version than the PDU one,
+          // send it the PDU, serializing it with the supported older version
+          session.publish(update, protocolVersion);
+        } else {
+          session.publish(update);
+        }
       }
     }
     catch (NoSuchElementException e)
@@ -146,7 +207,9 @@
        * The remote host has disconnected and this particular Tree is going to
        * be removed, just ignore the exception and let the thread die as well
        */
-      Message message = NOTE_SERVER_DISCONNECT.get(handler.toString());
+      Message message = NOTE_SERVER_DISCONNECT.get(handler.toString(),
+        Short.toString(replicationServerDomain.
+        getReplicationServer().getServerId()));
       logError(message);
     }
     catch (SocketException e)
@@ -155,7 +218,9 @@
        * The remote host has disconnected and this particular Tree is going to
        * be removed, just ignore the exception and let the thread die as well
        */
-      Message message = NOTE_SERVER_DISCONNECT.get(handler.toString());
+      Message message = NOTE_SERVER_DISCONNECT.get(handler.toString(),
+        Short.toString(replicationServerDomain.
+        getReplicationServer().getServerId()));
       logError(message);
     }
     catch (Exception e)

--
Gitblit v1.10.0