[jboss-cvs] JBossRemoting/src/main/org/jboss/remoting/transport/http ...

Ron Sigal ron_sigal at yahoo.com
Thu Feb 22 04:36:58 EST 2007


  User: rsigal  
  Date: 07/02/22 04:36:58

  Modified:    src/main/org/jboss/remoting/transport/http  Tag:
                        remoting_2_x HTTPClientInvoker.java
  Log:
  JBREM-657, JBREM-701:  Implemented per invocation timeouts for jdk 1.4.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.31.2.3  +250 -50   JBossRemoting/src/main/org/jboss/remoting/transport/http/HTTPClientInvoker.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: HTTPClientInvoker.java
  ===================================================================
  RCS file: /cvsroot/jboss/JBossRemoting/src/main/org/jboss/remoting/transport/http/HTTPClientInvoker.java,v
  retrieving revision 1.31.2.2
  retrieving revision 1.31.2.3
  diff -u -b -r1.31.2.2 -r1.31.2.3
  --- HTTPClientInvoker.java	15 Feb 2007 16:54:08 -0000	1.31.2.2
  +++ HTTPClientInvoker.java	22 Feb 2007 09:36:58 -0000	1.31.2.3
  @@ -24,7 +24,6 @@
   
   import org.jboss.logging.Logger;
   import org.jboss.remoting.CannotConnectException;
  -import org.jboss.remoting.Client;
   import org.jboss.remoting.ConnectionFailedException;
   import org.jboss.remoting.InvocationRequest;
   import org.jboss.remoting.InvocationResponse;
  @@ -40,6 +39,11 @@
   import org.jboss.remoting.serialization.ClassLoaderUtility;
   import org.jboss.remoting.transport.web.WebUtil;
   import org.jboss.util.Base64;
  +import org.jboss.util.threadpool.BasicThreadPool;
  +import org.jboss.util.threadpool.BlockingMode;
  +import org.jboss.util.threadpool.RunnableTaskWrapper;
  +import org.jboss.util.threadpool.Task;
  +import org.jboss.util.threadpool.ThreadPool;
   
   import java.io.IOException;
   import java.io.InputStream;
  @@ -51,6 +55,7 @@
   import java.net.HttpURLConnection;
   import java.net.InetSocketAddress;
   import java.net.SocketAddress;
  +import java.net.SocketTimeoutException;
   import java.net.URL;
   import java.util.HashMap;
   import java.util.Iterator;
  @@ -65,9 +70,29 @@
    */
   public class HTTPClientInvoker extends RemoteClientInvoker
   {
  +   /**
  +    * Key for the configuration map that determines the threadpool size for 
  +    * simulated timeouts when using jdk 1.4.
  +    */
  +   public static final String MAX_NUM_TIMEOUT_THREADS = "maxNumTimeoutThreads";
  +
  +   /**
  +    * Key for the configuration map that determines the queue size for simulated
  +    * timeout threadpool when using jdk 1.4.
  +    */
  +   public static final String MAX_TIMEOUT_QUEUE_SIZE = "maxTimeoutQueueSize";
  +   
  +   /**
  +    * Specifies the default number of work threads in the thread pool for 
  +    * simulating timeouts when using jdk 1.4.
  +    */
  +   public static final int MAX_NUM_TIMEOUT_THREADS_DEFAULT = 10;
   
      protected final Logger log = Logger.getLogger(getClass());
   
  +   private Object timeoutThreadPoolLock = new Object();
  +   private ThreadPool timeoutThreadPool;
  +
      public HTTPClientInvoker(InvokerLocator locator)
      {
         super(locator);
  @@ -87,36 +112,90 @@
       * @throws org.jboss.remoting.ConnectionFailedException
       *
       */
  -   protected Object transport(String sessionId, Object invocation, Map metadata,
  -                              Marshaller marshaller, UnMarshaller unmarshaller)
  +   protected Object transport(String sessionId, final Object invocation, Map metadata,
  +                              final Marshaller marshaller, final UnMarshaller unmarshaller)
            throws IOException, ConnectionFailedException
      {
  -      String targetURL = getLocator().getLocatorURI();
  -      Object httpResponse = useHttpURLConnection(targetURL, invocation, metadata, marshaller, unmarshaller);
  +      // need to check the url and make sure it compatible protocol
  +      String validatedUrl = validateURL(getLocator().getLocatorURI());
   
  -      return httpResponse;
  +      if (metadata == null)
  +      {
  +         metadata = new HashMap();
      }
   
  -   private Object useHttpURLConnection(String url, Object invocation, Map metadata,
  -                                       Marshaller marshaller, UnMarshaller unmarshaller) throws WebServerError
  +      final HttpURLConnection conn = createURLConnection(validatedUrl, metadata);
  +      
  +      int simulatedTimeout = getSimulatedTimeout(configuration, metadata, conn);
  +      
  +      if (simulatedTimeout < 0)
      {
  -      Object result = null;
  -      int responseCode = -1;
  +         return useHttpURLConnection(conn, invocation, metadata, marshaller, unmarshaller);
  +      }
  +      else
  +      {
  +         if (log.isTraceEnabled()) log.trace("using simulated timeout: " + simulatedTimeout);
  +         class Holder {public Object value;}
  +         final Holder resultHolder = new Holder();
  +         final Map finalMetadata = metadata;
   
  +         Runnable r = new Runnable()
  +         {
  +            public void run()
  +            {
         try
         {
  -         // need to check the url and make sure it compatible protocol
  -         String validatedUrl = validateURL(url);
  -
  -         if (metadata == null)
  +                  resultHolder.value = useHttpURLConnection(conn, invocation, finalMetadata, marshaller, unmarshaller);
  +                  if (log.isTraceEnabled()) log.trace("result: " + resultHolder.value);
  +               }
  +               catch (Exception e)
            {
  -            metadata = new HashMap();
  +                  resultHolder.value = e;
  +                  if (log.isTraceEnabled()) log.trace("exception: " + e); 
  +               }
            }
  +         };
  +         
  +         // BasicThreadPool timeout mechanism depends on the interrupted status of
  +         // the running thread.
  +         Thread.interrupted();
  +         
  +         ThreadPool pool = getTimeoutThreadPool();
  +         WaitingTaskWrapper wrapper = new WaitingTaskWrapper(r, simulatedTimeout);
  +         if (log.isTraceEnabled()) log.trace("starting task in thread pool");
  +         pool.runTaskWrapper(wrapper);
  +         if (log.isTraceEnabled()) log.trace("task finished in thread pool");
   
  -         HttpURLConnection conn = createURLConnection(validatedUrl, metadata);
  +         Object result = resultHolder.value;
  +         if (result == null)
  +         {
  +            if (log.isDebugEnabled()) log.debug("invocation timed out");
  +            throw new SocketTimeoutException("timed out");
  +         }
  +         else if (result instanceof IOException)
  +         {
  +            throw (IOException) result;
  +         }
  +         else if (result instanceof RuntimeException)
  +         {
  +            throw (RuntimeException) result;
  +         }
  +         else
  +         {
  +            if (log.isTraceEnabled()) log.trace("returning result: " + result);
  +            return result;
  +         }
  +      }
  +   }
   
  -         setTimeout(configuration, conn);
  +   private Object useHttpURLConnection(HttpURLConnection conn, Object invocation, Map metadata,
  +                                       Marshaller marshaller, UnMarshaller unmarshaller) throws WebServerError
  +   {
  +      Object result = null;
  +      int responseCode = -1;
   
  +      try
  +      {
            setChunked(configuration, conn);
   
            // check to see if basic auth required
  @@ -429,14 +508,40 @@
      }
   
   
  -   private void setTimeout(Map metadata, HttpURLConnection conn)
  +   private int getSimulatedTimeout(Map configuration, Map metadata, HttpURLConnection conn)
  +   {
  +      int simulatedTimeout = -1;
  +      int timeout = -1;
  +      String connectionTimeout = (String) configuration.get("timeout");
  +      String invocationTimeout = (String) metadata.get("timeout");
  +      
  +      if (invocationTimeout != null && invocationTimeout.length() > 0)
  +      {
  +         try
  +         {
  +            timeout = Integer.parseInt(invocationTimeout);
  +         }
  +         catch (NumberFormatException e)
      {
  -      String timeoutValue = (String) metadata.get("timeout");
  -      if (timeoutValue != null && timeoutValue.length() > 0)
  +            log.error("Could not set timeout for current invocation because value (" + invocationTimeout + ") is not a number.");
  +         }
  +      }
  +      
  +      if (timeout < 0 && connectionTimeout != null && connectionTimeout.length() > 0)
         {
            try
            {
  -            int timeout = Integer.parseInt(timeoutValue);
  +            timeout = Integer.parseInt(connectionTimeout);
  +         }
  +         catch (NumberFormatException e)
  +         {
  +            log.error("Could not set timeout for http client connection because value (" + connectionTimeout + ") is not a number.");
  +         }
  +      }
  +      
  +      if (timeout < 0)
  +         return -1;
  +
               /**
                * Since URLConnection in jdk 1.4 does NOT have a setConnectTimeout() method and
                * the one in jdk 1.5 does, will have to use reflection to see if it exists before
  @@ -451,24 +556,23 @@
               }
               catch (NoSuchMethodException e)
               {
  -               log.warn("Could not set timeout (" + timeout + ") on http client transport as method not available with JDK 1.4 (only JDK 1.5 or higher)");
  +         simulatedTimeout = timeout;
  +         log.debug("Using older JDK (prior to 1.5): will simulate timeout");
               }
               catch (IllegalAccessException e)
               {
  +         simulatedTimeout = timeout;
                  log.error("Error setting http client connection timeout.");
                  log.debug(e);
               }
               catch (InvocationTargetException e)
               {
  +         simulatedTimeout = timeout;
                  log.error("Error setting http client connection timeout.");
                  log.debug(e);
               }
  -         }
  -         catch (NumberFormatException e)
  -         {
  -            log.error("Could not set timeout for http client connection because value (" + timeoutValue + ") is not a number.");
  -         }
  -      }
  +      
  +      return simulatedTimeout;
      }
   
      protected String validateURL(String url)
  @@ -692,4 +796,100 @@
         return HTTPMarshaller.DATATYPE;
      }
   
  +
  +   /**
  +    * Sets the thread pool to be used for simulating timeouts with jdk 1.4.
  +    */
  +   public void setTimeoutThreadPool(ThreadPool pool)
  +   {
  +      this.timeoutThreadPool = pool;
  +   }
  +   
  +   /**
  +    * Gets the thread pool being used for simulating timeouts with jdk 1.4. If one has
  +    * not be specifically set via configuration or call to set it, will always return
  +    * instance of org.jboss.util.threadpool.BasicThreadPool.
  +    */
  +   public ThreadPool getTimeoutThreadPool()
  +   {
  +      synchronized (timeoutThreadPoolLock)
  +      {
  +         if (timeoutThreadPool == null)
  +         {
  +            int maxNumberThreads = MAX_NUM_TIMEOUT_THREADS_DEFAULT;
  +            int maxTimeoutQueueSize = -1;
  +            
  +            BasicThreadPool pool = new BasicThreadPool("HTTP timeout");
  +            log.debug("created new thread pool: " + pool);
  +            Object param = configuration.get(MAX_NUM_TIMEOUT_THREADS);
  +            if (param instanceof String)
  +            {
  +               try
  +               {
  +                  maxNumberThreads = Integer.parseInt((String) param);
  +               }
  +               catch (NumberFormatException  e)
  +               {
  +                  log.error("maxNumberThreads parameter has invalid format: " + param);
  +               }
  +            }
  +            else if (param != null)
  +            {
  +               log.error("maxNumberThreads parameter must be a string in integer format: " + param);
  +            }
  +
  +            param = configuration.get(MAX_TIMEOUT_QUEUE_SIZE);
  +
  +            if (param instanceof String)
  +            {
  +               try
  +               {
  +                  maxTimeoutQueueSize = Integer.parseInt((String) param);
  +               }
  +               catch (NumberFormatException  e)
  +               {
  +                  log.error("maxTimeoutQueueSize parameter has invalid format: " + param);
  +               }
  +            }
  +            else if (param != null)
  +            {
  +               log.error("maxTimeoutQueueSize parameter must be a string in integer format: " + param);
  +            }
  +
  +            pool.setMaximumPoolSize(maxNumberThreads);
  +
  +            if (maxTimeoutQueueSize > 0)
  +            {
  +               pool.setMaximumQueueSize(maxTimeoutQueueSize);
  +            }
  +            pool.setBlockingMode(BlockingMode.RUN);
  +            timeoutThreadPool = pool;
  +         }
  +      }
  +      return timeoutThreadPool;
  +   }
  +   
  +   
  +   /**
  +    * When a WaitingTaskWrapper is run in a BasicThreadPool, the calling thread
  +    * will block for the designated timeout period.
  +    */
  +   static class WaitingTaskWrapper extends RunnableTaskWrapper
  +   {
  +      long completeTimeout;
  +      
  +      public WaitingTaskWrapper(Runnable runnable, long completeTimeout)
  +      {
  +         super(runnable, 0, completeTimeout);
  +         this.completeTimeout = completeTimeout;
  +      }
  +      public int getTaskWaitType()
  +      {
  +         return Task.WAIT_FOR_COMPLETE;
  +      }
  +      public String toString()
  +      {
  +         return "WaitingTaskWrapper[" + completeTimeout + "]";
  +      }
  +   }
   }
  \ No newline at end of file
  
  
  



More information about the jboss-cvs-commits mailing list