From 1fbc9df5d0c44ae72c76dacc3c945d4f0d641ee6 Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Tue, 22 Dec 2009 05:55:54 +0000
Subject: [PATCH] Initial implementation of fail over connection factory

---
 sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java |  109 ++++++++++++++----------------------------------------
 1 files changed, 28 insertions(+), 81 deletions(-)

diff --git a/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java b/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
index 285633c..3d426cd 100644
--- a/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
+++ b/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
@@ -32,13 +32,13 @@
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.TimeUnit;
 
 import org.opends.sdk.requests.*;
 import org.opends.sdk.responses.*;
 import org.opends.sdk.schema.Schema;
 
 import com.sun.opends.sdk.util.FutureResultTransformer;
+import com.sun.opends.sdk.util.Validator;
 
 
 
@@ -46,47 +46,20 @@
  * An heart beat connection factory can be used to create connections
  * that sends a periodic search request to a Directory Server.
  */
-final class HeartBeatConnectionFactory extends
+public class HeartBeatConnectionFactory extends
     AbstractConnectionFactory<AsynchronousConnection>
 {
-  private final SearchRequest heartBeat;
-
-  private final long interval;
+  private final int interval;
 
   private final List<AsynchronousConnectionImpl> activeConnections;
 
   private final ConnectionFactory<?> parentFactory;
 
-  private volatile boolean stopRequested;
-
 
 
   // FIXME: use a single global scheduler?
 
-  /**
-   * Creates a new heart-beat connection factory which will create
-   * connections using the provided connection factory and periodically
-   * ping any created connections in order to detect that they are still
-   * alive.
-   *
-   * @param connectionFactory
-   *          The connection factory to use for creating connections.
-   * @param timeout
-   *          The time to wait between keepalive pings.
-   * @param unit
-   *          The time unit of the timeout argument.
-   */
-  HeartBeatConnectionFactory(ConnectionFactory<?> connectionFactory,
-      long timeout, TimeUnit unit)
-  {
-    this(connectionFactory, timeout, unit, DEFAULT_SEARCH);
-  }
-
-
-
-  private static final SearchRequest DEFAULT_SEARCH = Requests
-      .newSearchRequest("", SearchScope.BASE_OBJECT, "(objectClass=*)",
-          "1.1");
+  // FIXME: change timeout parameters to long+TimeUnit.
 
 
 
@@ -98,30 +71,18 @@
    *
    * @param connectionFactory
    *          The connection factory to use for creating connections.
-   * @param timeout
-   *          The time to wait between keepalive pings.
-   * @param unit
-   *          The time unit of the timeout argument.
-   * @param heartBeat
-   *          The search request to use when pinging connections.
+   * @param interval
+   *          The period between keepalive pings.
    */
-  HeartBeatConnectionFactory(ConnectionFactory<?> connectionFactory,
-      long timeout, TimeUnit unit, SearchRequest heartBeat)
+  public HeartBeatConnectionFactory(
+      ConnectionFactory<?> connectionFactory,
+      int interval)
   {
-    this.heartBeat = heartBeat;
-    this.interval = unit.toMillis(timeout);
+    Validator.ensureNotNull(connectionFactory);
+    this.interval = interval;
     this.activeConnections = new LinkedList<AsynchronousConnectionImpl>();
     this.parentFactory = connectionFactory;
 
-    Runtime.getRuntime().addShutdownHook(new Thread()
-    {
-      @Override
-      public void run()
-      {
-        stopRequested = true;
-      }
-    });
-
     new HeartBeatThread().start();
   }
 
@@ -132,13 +93,11 @@
    * operations.
    */
   private final class AsynchronousConnectionImpl implements
-      AsynchronousConnection, ConnectionEventListener,
-      ResultHandler<Result>
+      AsynchronousConnection, ConnectionEventListener
   {
     private final AsynchronousConnection connection;
 
 
-
     private AsynchronousConnectionImpl(AsynchronousConnection connection)
     {
       this.connection = connection;
@@ -352,7 +311,15 @@
       return connection.isClosed();
     }
 
-
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValid()
+    {
+      // Avoid extra pings... Let the next ping find out if this connection
+      // is still valid.
+      return connection.isValid();
+    }
 
     public void connectionReceivedUnsolicitedNotification(
         GenericExtendedResult notification)
@@ -371,31 +338,6 @@
         activeConnections.remove(this);
       }
     }
-
-
-
-    public void handleErrorResult(ErrorResultException error)
-    {
-      // TODO: I18N
-      if (error instanceof TimeoutResultException)
-      {
-        close(Requests.newUnbindRequest(), "Heart beat timed out");
-      }
-    }
-
-
-
-    public void handleResult(Result result)
-    {
-      // Do nothing
-    }
-
-
-
-    private void sendHeartBeat()
-    {
-      search(heartBeat, this, null);
-    }
   }
 
 
@@ -405,19 +347,24 @@
     private HeartBeatThread()
     {
       super("Heart Beat Thread");
+      this.setDaemon(true);
     }
 
 
 
     public void run()
     {
-      while (!stopRequested)
+      while(true)
       {
         synchronized (activeConnections)
         {
           for (AsynchronousConnectionImpl connection : activeConnections)
           {
-            connection.sendHeartBeat();
+            if(!connection.isValid())
+            {
+              connection.close(Requests.newUnbindRequest(),
+                               "Connection no longer valid");
+            }
           }
         }
         try

--
Gitblit v1.10.0