>From bc5ab07c3dce7fd74e6d30d7f35be6084aa341eb Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Mon, 24 Mar 2014 09:20:48 -0700
Subject: [PATCH] trac ticket#862 addendum - support multi-uri in
 HttpConnFactory

---
 .../certsrv/connector/IHttpConnection.java         |   7 ++
 .../cmscore/connector/HttpConnFactory.java         | 101 +++++++++++++++++----
 .../netscape/cmscore/connector/HttpConnection.java |   7 ++
 3 files changed, 95 insertions(+), 20 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/connector/IHttpConnection.java b/base/common/src/com/netscape/certsrv/connector/IHttpConnection.java
index 2e87185..be5f7fc 100644
--- a/base/common/src/com/netscape/certsrv/connector/IHttpConnection.java
+++ b/base/common/src/com/netscape/certsrv/connector/IHttpConnection.java
@@ -49,4 +49,11 @@ public interface IHttpConnection {
      */
     public HttpResponse send(String msg)
             throws EBaseException;
+
+    /**
+     * returns op associated with this HttpConnection
+     *
+     * @return String op string
+     */
+    public String getOp();
 }
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnFactory.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnFactory.java
index be727a5..5743bfc 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnFactory.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnFactory.java
@@ -17,6 +17,8 @@
 // --- END COPYRIGHT BLOCK ---
 package com.netscape.cmscore.connector;
 
+import java.util.Vector;
+
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authority.IAuthority;
 import com.netscape.certsrv.base.EBaseException;
@@ -38,7 +40,7 @@ public class HttpConnFactory {
 
     private int mNumConns = 0; // number of available conns in array
     private int mTotal = 0; // total num conns
-    private IHttpConnection mConns[];
+    private Vector<IHttpConnection> mConns;
     @SuppressWarnings("unused")
     private IAuthority mSource;
     private IRemoteAuthority mDest = null;
@@ -56,7 +58,7 @@ public class HttpConnFactory {
      * Constructor for HttpConnFactory
      *
      * @param minConns minimum number of connections to have available
-     * @param maxConns max number of connections to have available. This is
+     * @param maxConns max number of connections to have available. It is a soft limit for multi-uri mode
      * @param serverInfo server connection info - host, port, etc.
      */
     public HttpConnFactory(int minConns, int maxConns, IAuthority source, IRemoteAuthority dest, String nickname,
@@ -97,7 +99,7 @@ public class HttpConnFactory {
 
         CMS.debug("before creating httpconn array");
 
-        mConns = new IHttpConnection[mMaxConns];
+        mConns = new Vector<IHttpConnection>();
 
         // Create connection handle and make initial connection
 
@@ -134,6 +136,8 @@ public class HttpConnFactory {
                 } else {
                     retConn = CMS.getHttpConnection(mDest, tFactory, mTimeout, op);
                 }
+                if (retConn != null)
+                    CMS.debug("createConnection: connection created for op="+ op);
             }
 
         } catch (Exception e) {
@@ -149,28 +153,36 @@ public class HttpConnFactory {
 
     /**
      * makes the minumum number of connections
+     * if (op != null), mMaxConns is a soft limit
      */
     private void makeMinimum(String op) throws EBaseException {
 
         CMS.debug("In HttpConnFactory.makeMinimum.");
         int increment;
 
-        if (mNumConns < mMinConns && mTotal <= mMaxConns) {
+        if ((isConnForOp(op)== false) ||
+                (mNumConns < mMinConns && mTotal <= mMaxConns)) {
 
             increment = Math.min(mMinConns - mNumConns, mMaxConns - mTotal);
 
-            if (increment == 0)
+            if (isConnForOp(op)== false) {
+                increment = mMinConns;
+            } else if (increment == 0) {
                 return;
+            }
 
             CMS.debug(
-                    "increasing minimum connections by " + increment);
+                    "HttpConnFactory:makeMinimum: increasing minimum connections by " + increment);
             for (int i = increment - 1; i >= 0; i--) {
-                mConns[i] = createConnection(op);
+                IHttpConnection newConn = createConnection(op);
+                if (newConn != null) {
+                    mConns.add(newConn);
+                    mNumConns++;
+                    mTotal++;
+                }
             }
-            mTotal += increment;
-            mNumConns += increment;
-            CMS.debug("new total available http connections " + mTotal);
-            CMS.debug("new number of http connections " + mNumConns);
+            CMS.debug("HttpConnFactory:makeMinimum: new total available http connections " + mTotal);
+            CMS.debug("HttpConnFactory:makeMinimum: new number of http connections " + mNumConns);
         }
     }
 
@@ -243,11 +255,13 @@ public class HttpConnFactory {
         boolean waited = false;
 
         CMS.debug("In HttpConnFactory.getConn");
-        if (mNumConns == 0)
+        if ((mNumConns == 0) || (isConnForOp(op) == false))
             makeMinimum(op);
-        if (mNumConns == 0) {
-            if (!waitForConn)
+        if (mNumConns == 0){
+            if (!waitForConn) {
+                CMS.debug("getConn: out of http connections. no wait, get out.");
                 return null;
+            }
             try {
                 CMS.debug("getConn: out of http connections");
                 log(ILogger.LL_WARN,
@@ -261,10 +275,7 @@ public class HttpConnFactory {
             } catch (InterruptedException e) {
             }
         }
-        mNumConns--;
-        IHttpConnection conn = mConns[mNumConns];
-
-        mConns[mNumConns] = null;
+        IHttpConnection conn = getConnForOp(op);
 
         if (waited) {
             CMS.debug("HttpConn:had to wait for an available connection from pool");
@@ -276,6 +287,56 @@ public class HttpConnFactory {
         return conn;
     }
 
+    private boolean isConnForOp(String op) {
+        if (op == null)
+            return true;
+        for (int i = 0; i < mNumConns; i++) {
+            if (op.equals(mConns.elementAt(i).getOp())) {
+                CMS.debug("HttpConnFactory: isConnForOp: found conn for op:"
+                    + op);
+                return true;
+            } else {
+                CMS.debug("HttpConnFactory: isConnForOp: found conn for op:"
+                    + mConns.elementAt(i).getOp());
+            }
+        }
+        CMS.debug("HttpConnFactory: isConnForOp: found no conn for op");
+        return false;
+    }
+
+    /**
+     * getConnForOp returns an HttpConnection for an op, if it exists,
+     *     null otherwise
+     */
+    private IHttpConnection getConnForOp(String op) {
+        mNumConns--;
+        IHttpConnection retConn = null;
+        if (op == null) {
+            retConn =  mConns.elementAt(mNumConns);
+            mConns.removeElementAt(mNumConns);
+        } else {
+            CMS.debug("getConnForOp: op ="+ op);
+            for (int i = 0; i <= mNumConns; i++) {
+                if ((mConns.elementAt(i).getOp() != null) && op.equals(mConns.elementAt(i).getOp())) {
+                    CMS.debug(
+                        "HttpConnFactory: getConnForOp: found HttpConnection with matching op: " + op);
+                    retConn = mConns.elementAt(i);
+                    mConns.removeElementAt(i);
+                    break;
+                } else {
+                    if (mConns.elementAt(i).getOp() != null) {
+                        CMS.debug(
+                            "HttpConnFactory: getConnForOp: found non-matching HttpConnection with op="+mConns.elementAt(i).getOp());
+                    } else {
+                        CMS.debug(
+                            "HttpConnFactory: getConnForOp: HttpConnection getOp returned null");
+                    }
+                }
+            }
+        }
+        return retConn;
+    }
+
     /**
      * Return connection to the factory.
      * This is mandatory after a getConn().
@@ -303,13 +364,13 @@ public class HttpConnFactory {
         IHttpConnection boundconn = conn;
 
         for (int i = 0; i < mNumConns; i++) {
-            if (mConns[i] == conn) {
+            if (mConns.elementAt(i) == conn) {
                 CMS.debug(
                         "returnConn: previously returned connection. " + conn);
 
             }
         }
-        mConns[mNumConns++] = boundconn;
+        mConns.add(mNumConns++, boundconn);
         CMS.debug("HttpreturnConn: mNumConns now " + mNumConns);
         notify();
     }
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java
index 30d70be..d1f67d5 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java
@@ -35,6 +35,7 @@ import com.netscape.cmsutil.net.ISocketFactory;
 public class HttpConnection implements IHttpConnection {
     protected IRemoteAuthority mDest = null;
     protected HttpRequest mHttpreq = new HttpRequest();
+    protected String mOp = null;
     protected IRequestEncoder mReqEncoder = null;
     protected HttpClient mHttpClient = null;
 
@@ -64,6 +65,10 @@ public class HttpConnection implements IHttpConnection {
         this(dest, factory, null);
     }
 
+    public String getOp() {
+        return mOp;
+    }
+
     /*
      * @param op operation to determine the receiving servlet (multi-uri support)
      */
@@ -71,6 +76,7 @@ public class HttpConnection implements IHttpConnection {
         mDest = dest;
         mReqEncoder = new HttpRequestEncoder();
         mHttpClient = new HttpClient(factory);
+        mOp = op;
         if (Debug.ON)
             Debug.trace("Created HttpClient");
         try {
@@ -122,6 +128,7 @@ public class HttpConnection implements IHttpConnection {
         mDest = dest;
         mReqEncoder = new HttpRequestEncoder();
         mHttpClient = new HttpClient(factory);
+        mOp = op;
         CMS.debug("HttpConn:Created HttpConnection: factory " + factory + "client " + mHttpClient);
         try {
             mHttpreq.setMethod("POST");
-- 
1.8.4.2

