From 19d2907f59c6a62cea36d4a1525e2aa4b8092c22 Mon Sep 17 00:00:00 2001
From: jdemendi <jdemendi@localhost>
Date: Tue, 06 Jan 2009 09:55:26 +0000
Subject: [PATCH] add support of the client connection affinity

---
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/NetworkGroupConfiguration.xml       |   92 ++++++++++++++++++++++
 opendj-sdk/opends/src/messages/messages/core.properties                                          |    5 +
 opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroupConfigManager.java |   47 +++++++++++
 opendj-sdk/opends/resource/schema/02-config.ldif                                                 |   14 +++
 opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java              |   63 +++++++++++++++
 5 files changed, 214 insertions(+), 7 deletions(-)

diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 87031c9..0af1c4a 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/opends/resource/schema/02-config.ldif
@@ -21,7 +21,7 @@
 # CDDL HEADER END
 #
 #
-#      Copyright 2006-2008 Sun Microsystems, Inc.
+#      Copyright 2006-2009 Sun Microsystems, Inc.
 #
 #
 # This file contains the attribute type and objectclass definitions for use
@@ -2377,6 +2377,16 @@
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
   SINGLE-VALUE
   X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( ds-cfg-affinity-policy-OID
+  NAME 'ds-cfg-affinity-policy'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( ds-cfg-affinity-timeout-OID
+  NAME 'ds-cfg-affinity-timeout'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
   NAME 'ds-cfg-access-control-handler'
   SUP top
@@ -3862,6 +3872,8 @@
   SUP top
   STRUCTURAL
   MUST ( ds-cfg-network-group-id $
+         ds-cfg-affinity-policy $
+         ds-cfg-affinity-timeout $
          ds-cfg-priority $
          ds-cfg-enabled )
   MAY ds-cfg-workflow
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/NetworkGroupConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/NetworkGroupConfiguration.xml
index 35c5eff..6877ce6 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/NetworkGroupConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/NetworkGroupConfiguration.xml
@@ -23,7 +23,7 @@
   ! CDDL HEADER END
   !
   !
-  !      Copyright 2007-2008 Sun Microsystems, Inc.
+  !      Copyright 2007-2009 Sun Microsystems, Inc.
   ! -->
 <adm:managed-object name="network-group" plural-name="network-groups"
   package="org.opends.server.admin.std"
@@ -175,4 +175,94 @@
       </ldap:attribute>
     </adm:profile>
   </adm:property>
+  <adm:property name="affinity-policy" mandatory="true" advanced="true">
+    <adm:synopsis>
+      Defines the client connection affinity policy.
+    </adm:synopsis>
+    <adm:description>
+      A client connection affinity allows some requests to be routed
+      to a specific data source regardless the regular routing
+      process. For example, we can requires all the requests to be
+      routed to a data source after a write has been complete on
+      that data source. That way, a read request would return data
+      that are consistent with a previous write request. By default,
+      the client connection affinity is disabled.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>none</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+      <adm:enumeration>
+        <adm:value name="none">
+          <adm:synopsis>
+            Disables the client connection affinity.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="first-read-request-after-write-request">
+          <adm:synopsis>
+            Routes the first read request to the data source to which
+            a previous write request has been routed to. This affinity
+            is useful when a client application performs a read request
+            after a write request and the read request should return
+            consistent data.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="all-requests-after-first-write-request">
+          <adm:synopsis>
+            Routes all the requests to the data source to which a
+            previous write request has been routed to.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="all-write-requests-after-first-write-request">
+          <adm:synopsis>
+            Routes all the write requests to the data source to which
+            a previous write request has been routed to. This affinity
+            policy is useful for batch update where a parent entry and
+            its subordinates must be sent to the same data source.
+          </adm:synopsis>
+        </adm:value>
+        <adm:value name="all-requests-after-first-request">
+          <adm:synopsis>
+            Routes all the requests to the data source to which a
+            previous request has been routed to. This affinity policy
+            allows to create a kind of tunnel between a client application
+            and a data source.
+          </adm:synopsis>
+        </adm:value>
+      </adm:enumeration>
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-affinity-policy</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
+  <adm:property name="affinity-timeout" mandatory="true" advanced="true">
+    <adm:synopsis>
+      The period of time by which an affinity route remains active.
+      The timeout value is a number of seconds and when the value is
+      set to 0 (default value) then the route remains active forever.
+    </adm:synopsis>
+    <adm:description>
+      When the client connection affinity is enabled, an affinity route
+      might be elected in accordance with the affinity policy. The affinity
+      route is then used until the timeout value expires unless the timeout
+      value is 0 in which case the route remains active forever.
+    </adm:description>
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>0</adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+    <adm:syntax>
+    	<adm:duration base-unit="s" lower-limit="0" />
+    </adm:syntax>
+    <adm:profile name="ldap">
+      <ldap:attribute>
+        <ldap:name>ds-cfg-affinity-timeout</ldap:name>
+      </ldap:attribute>
+    </adm:profile>
+  </adm:property>
 </adm:managed-object>
diff --git a/opendj-sdk/opends/src/messages/messages/core.properties b/opendj-sdk/opends/src/messages/messages/core.properties
index 008ca86..40448eb 100644
--- a/opendj-sdk/opends/src/messages/messages/core.properties
+++ b/opendj-sdk/opends/src/messages/messages/core.properties
@@ -1813,4 +1813,7 @@
 INFO_ERR_WORKFLOW_DOES_NOT_EXIST_718=\
 Unable to register the workflow "%s" with the network group %s because \
 the workflow does not exist
- 
\ No newline at end of file
+SEVERE_ERR_WORKFLOW_BASE_DN_DUPLICATED_IN_NG_719=\
+Unable to register the workflow because the base DN '%s' is already \
+registered with the network group '%s'
+ 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java b/opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
index ecc8e71..ba44c8b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2007-2008 Sun Microsystems, Inc.
+ *      Copyright 2007-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.core.networkgroups;
 
@@ -141,6 +141,13 @@
   // The statistics
   private NetworkGroupStatistics stats;
 
+  // The client connection affinity policy.
+  private ClientConnectionAffinityPolicy affinityPolicy = null;
+
+  // The client connection affinity timeout (number of seconds).
+  private long affinityTimeout = 0;
+
+
   /**
    * Creates a new instance of the network group.
    *
@@ -731,6 +738,34 @@
   }
 
   /**
+   * Sets the affinity policy. The client connection affinity is the ability
+   * for the server to bypass a route algorithm like "load balancing" so
+   * that a request is always sent to the same data source regardless the
+   * route algorithm.
+   *
+   * @param  affinityPolicy
+   *         The client connection affinity policy of the network group.
+   */
+  public void setAffinityPolicy(
+      ClientConnectionAffinityPolicy affinityPolicy)
+  {
+    this.affinityPolicy = affinityPolicy;
+  }
+
+  /**
+   * Sets the affinity timeout value. The client connection affinity, when
+   * set, remains active until the time out expires. When the time out
+   * value is set to 0 then an active affinity never expires.
+   *
+   * @param timeout
+   *        The affinity timeout value (0 means never expire).
+   */
+  public void setAffinityTimeout(long timeout)
+  {
+    this.affinityTimeout = timeout;
+  }
+
+  /**
    * Gets the highest priority matching network group.
    *
    * @param connection the client connection
@@ -899,6 +934,32 @@
   }
 
   /**
+   * Gets the affinity policy. The client connection affinity is the ability
+   * for the server to bypass a route algorithm like "load balancing" so
+   * that a request is always sent to the same data source regardless the
+   * route algorithm.
+   *
+   * @return the client connection affinity policy of the network group
+   */
+  public ClientConnectionAffinityPolicy getAffinityPolicy()
+  {
+    return this.affinityPolicy;
+  }
+
+  /**
+   * Gets the affinity timeout value. The client connection affinity, when
+   * set, is active for a period of time. Once that period of time has
+   * expired, the client connection affinity is reset. A value of 0 means
+   * "no limit" - when an affinity is set it remains active for ever.
+   *
+   * @return the affinity timeout value (0 means no limit).
+   */
+  public long getAffinityTimeout()
+  {
+    return this.affinityTimeout;
+  }
+
+  /**
    * Checks the request filtering policy.
    * @param operation the operation to be checked
    * @param messages the error messages
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroupConfigManager.java b/opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroupConfigManager.java
index 1f6662f..f59092d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroupConfigManager.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/networkgroups/NetworkGroupConfigManager.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.core.networkgroups;
 
@@ -32,7 +32,9 @@
 import static org.opends.server.loggers.ErrorLogger.logError;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.SortedSet;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -222,8 +224,38 @@
       NetworkGroupCfg configuration,
       List<Message>   unacceptableReasons)
   {
-    // Nothing to check.
-    return true;
+    // If the network group is disabled then there is nothing to check.
+    if (! configuration.isEnabled())
+    {
+      return true;
+    }
+
+    // Check that all the workflows in the network group have a
+    // different base DN.
+
+    boolean result = true;
+    Set<String> allBaseDNs = new HashSet<String>();
+    for (String workflowId : configuration.getWorkflow())
+    {
+      WorkflowImpl workflow =
+        (WorkflowImpl) WorkflowImpl.getWorkflow(workflowId);
+      String baseDN = workflow.getBaseDN().toNormalizedString();
+      if (allBaseDNs.contains(baseDN))
+      {
+        // This baseDN is duplicated
+        Message message = ERR_WORKFLOW_BASE_DN_DUPLICATED_IN_NG.get(
+          baseDN, configuration.getNetworkGroupId());
+        unacceptableReasons.add(message);
+        result = false;
+        break;
+      }
+      else
+      {
+        allBaseDNs.add(baseDN);
+      }
+    }
+
+    return result;
   }
 
 
@@ -424,6 +456,15 @@
               ex.getMessageObject());
     }
 
+    // Set the client connection affinity policy.
+    ClientConnectionAffinityPolicy affinityPolicy =
+      ClientConnectionAffinityPolicy.toClientConnectionAffinityPolicy(
+        networkGroupCfg.getAffinityPolicy());
+    networkGroup.setAffinityPolicy(affinityPolicy);
+
+    // Set the client connection affinity timeout
+    long affinityTimeout = networkGroupCfg.getAffinityTimeout();
+    networkGroup.setAffinityTimeout(affinityTimeout);
   }
 
 }

--
Gitblit v1.10.0