You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by sh...@locus.apache.org on 2000/02/17 11:37:42 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/service TcpConnection.java TcpEndpoint.java TcpEndpointConnector.java

shachor     00/02/17 02:37:42

  Modified:    src/share/org/apache/tomcat/service TcpConnection.java
                        TcpEndpoint.java TcpEndpointConnector.java
  Log:
  Adding a thread pool to the Tomcat TCP connectors
  
  Revision  Changes    Path
  1.2       +17 -13    jakarta-tomcat/src/share/org/apache/tomcat/service/TcpConnection.java
  
  Index: TcpConnection.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpConnection.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TcpConnection.java	1999/10/09 00:20:48	1.1
  +++ TcpConnection.java	2000/02/17 10:37:41	1.2
  @@ -1,13 +1,13 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpConnection.java,v 1.1 1999/10/09 00:20:48 duncan Exp $
  - * $Revision: 1.1 $
  - * $Date: 1999/10/09 00:20:48 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpConnection.java,v 1.2 2000/02/17 10:37:41 shachor Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/02/17 10:37:41 $
    *
    * ====================================================================
    *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -15,7 +15,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    notice, this list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
  @@ -23,15 +23,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    any, must include the following acknowlegement:
  + *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowlegement may appear in the software itself,
    *    if and wherever such third-party acknowlegements normally appear.
    *
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written 
  + *    from this software without prior written permission. For written
    *    permission, please contact apache@apache.org.
    *
    * 5. Products derived from this software may not be called "Apache"
  @@ -59,7 +59,7 @@
    *
    * [Additional notices, if required by prior licensing conditions]
    *
  - */ 
  + */
   
   
   package org.apache.tomcat.service;
  @@ -71,18 +71,18 @@
   import java.util.*;
   
   /**
  - * 
  + *
    */
   public class TcpConnection  { // implements Endpoint {
   
       public TcpConnection() {
       }
   
  -    // -------------------- Properties --------------------	
  +    // -------------------- Properties --------------------
   
       TcpEndpoint endpoint;
       Socket socket;
  -    
  +
       public void setEndpoint(TcpEndpoint endpoint) {
   	this.endpoint = endpoint;
       }
  @@ -99,6 +99,10 @@
   	return socket;
       }
   
  +    public void recycle() {
  +        endpoint = null;
  +        socket = null;
  +    }
   }
  -    
  +
   
  
  
  
  1.8       +255 -144  jakarta-tomcat/src/share/org/apache/tomcat/service/TcpEndpoint.java
  
  Index: TcpEndpoint.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpEndpoint.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- TcpEndpoint.java	2000/02/09 01:18:39	1.7
  +++ TcpEndpoint.java	2000/02/17 10:37:42	1.8
  @@ -1,13 +1,13 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpEndpoint.java,v 1.7 2000/02/09 01:18:39 costin Exp $
  - * $Revision: 1.7 $
  - * $Date: 2000/02/09 01:18:39 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpEndpoint.java,v 1.8 2000/02/17 10:37:42 shachor Exp $
  + * $Revision: 1.8 $
  + * $Date: 2000/02/17 10:37:42 $
    *
    * ====================================================================
    *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -15,7 +15,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    notice, this list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
  @@ -23,15 +23,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    any, must include the following acknowlegement:
  + *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowlegement may appear in the software itself,
    *    if and wherever such third-party acknowlegements normally appear.
    *
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written 
  + *    from this software without prior written permission. For written
    *    permission, please contact apache@apache.org.
    *
    * 5. Products derived from this software may not be called "Apache"
  @@ -59,7 +59,7 @@
    *
    * [Additional notices, if required by prior licensing conditions]
    *
  - */ 
  + */
   
   
   package org.apache.tomcat.service;
  @@ -75,14 +75,14 @@
      It should do nothing more - as soon as it get a socket ( and all socket options
      are set, etc), it just handle the stream to ConnectionHandler.processConnection. (costin)
   */
  -   
  -   
  +
  +
   
   /**
    * Handle incoming TCP connections.
  - * 
  + *
    * This class implement a simple server model: one listener thread accepts on a socket and
  - * creates a new worker thread for each incoming connection. 
  + * creates a new worker thread for each incoming connection.
    *
    * More advanced Endpoints will reuse the threads, use queues, etc.
    *
  @@ -90,83 +90,114 @@
    * @author Jason Hunter [jch@eng.sun.com]
    * @author James Todd [gonzo@eng.sun.com]
    * @author Costin@eng.sun.com
  + * @author Gal Shachor [shachor@il.ibm.com]
    */
   public class TcpEndpoint  { // implements Endpoint {
   
  -    private StringManager sm =StringManager.getManager("org.apache.tomcat.service");
  +    private StringManager sm = StringManager.getManager("org.apache.tomcat.service");
   
  -    private static final int BACKLOG = 50;
  +    private static final int BACKLOG = 100;
       private static final int TIMEOUT = 1000;
   
  +    private boolean isPool = true;
  +
       private int backlog = BACKLOG;
       private int timeout = TIMEOUT;
  -    
  -    //    private EndpointManager manager;
   
  -    String handlerClassName;
       TcpConnectionHandler handler;
  -    
  +
       private InetAddress inet;
       private int port;
   
       private ServerSocketFactory factory;
       private ServerSocket serverSocket;
   
  -    TcpListenerThread listener;
  +    Runnable listener;
       boolean running = true;
  -    
  +
  +    ThreadPool tp;
  +
       public TcpEndpoint() {
  +        tp = new ThreadPool();
       }
   
  -    // -------------------- Configuration --------------------	
  +    // -------------------- Configuration --------------------
   
  -//     public void setEndpointManager( EndpointManager manager ) {
  -// 	this.manager=manager;
  -//     }
  +    public void setPoolOn(boolean isPool) {
  +        this.isPool = isPool;
  +    }
  +
  +    public boolean isPoolOn() {
  +        return isPool;
  +    }
  +
  +    public void setMaxThreads(int maxThreads) {
  +        tp.setMaxThreads(maxThreads);
  +    }
  +
  +    public int getMaxThreads() {
  +        return tp.getMaxThreads();
  +    }
  +
  +    public void setMaxSpareThreads(int maxThreads) {
  +        tp.setMaxSpareThreads(maxThreads);
  +    }
   
  +    public int getMaxSpareThreads() {
  +        return tp.getMaxSpareThreads();
  +    }
  +
  +    public void setMinSpareThreads(int minThreads) {
  +        tp.setMinSpareThreads(minThreads);
  +    }
  +
  +    public int getMinSpareThreads() {
  +        return tp.getMinSpareThreads();
  +    }
  +
       public int getPort() {
  -	return port;
  +	    return port;
       }
   
       public void setPort(int port ) {
  -	this.port=port;
  +	    this.port=port;
       }
   
       public InetAddress getAddress() {
  -	return inet;
  +	    return inet;
       }
   
       public void setAddress(InetAddress inet) {
  -	this.inet=inet;
  +	    this.inet=inet;
       }
   
       public void setServerSocket(ServerSocket ss) {
  -	serverSocket = ss;
  +	    serverSocket = ss;
       }
   
       public void setServerSocketFactory(  ServerSocketFactory factory ) {
  -	this.factory=factory;
  -    }
  -
  -    public void setConnectionHandlerClassName( String classN ) {
  -
  +	    this.factory=factory;
       }
   
       public void setConnectionHandler( TcpConnectionHandler handler ) {
  -	this.handler=handler;
  +    	this.handler=handler;
       }
   
       public TcpConnectionHandler getConnectionHandler() {
  -	return handler;
  +	    return handler;
       }
  -    
  +
       /**
        * Allows the server developer to specify the backlog that
        * should be used for server sockets. By default, this value
  -     * is 50.
  +     * is 100.
        */
       public void setBacklog(int backlog) {
  -	this.backlog = backlog;
  +	    this.backlog = backlog;
  +    }
  +
  +    public int getBacklog() {
  +        return backlog;
       }
   
       /**
  @@ -178,150 +209,230 @@
        * <p>By default this value is 1000ms.
        */
       public void setTimeout(int timeout) {
  -	this.timeout = timeout;
  +	    this.timeout = timeout;
       }
   
       // -------------------- Public methods --------------------
  -    
  +
       public void startEndpoint() throws IOException, InstantiationException {
  -	try {
  -	    if(factory==null)
  -		factory=ServerSocketFactory.getDefault();
  -	    if(serverSocket==null) {
  -		if (inet != null) {
  -		    serverSocket = factory.createSocket(port, backlog);
  -		} else {
  -		    serverSocket = factory.createSocket(port, backlog, inet);
  -		}
  -	    }
  -	} catch( IOException ex ) {
  -	    // throw?
  -	    // ex.printStackTrace();
  -	    running=false;
  +	    try {
  +	        if(factory==null)
  +		        factory=ServerSocketFactory.getDefault();
  +	        if(serverSocket==null) {
  +		        if (inet != null) {
  +		            serverSocket = factory.createSocket(port, backlog);
  +    		    } else {
  +	    	        serverSocket = factory.createSocket(port, backlog, inet);
  +		        }
  +	        }
  +	        if(isPool) {
  +    	        tp.start();
  +    	    }
  +	    } catch( IOException ex ) {
  +	        // throw?
  +	        // ex.printStackTrace();
  +	        running=false;
               throw ex;
  -	    //	    throw new HttpServerException(msg);
  -	} catch( InstantiationException ex1 ) {
  -	    // throw?
  -	    // ex1.printStackTrace();
  -	    running=false;
  +	        // throw new HttpServerException(msg);
  +	    } catch( InstantiationException ex1 ) {
  +	        // throw?
  +	        // ex1.printStackTrace();
  +	        running=false;
               throw ex1;
  -	    //	    throw new HttpServerException(msg);
  -	}
  -	running=true;
  -	System.out.println("Starting tcp endpoint on " + port + " with " + handler.getClass().getName());
  -	listener=new TcpListenerThread( this );
  -	Thread thread = new Thread(listener);
  -	thread.start();
  +	        // throw new HttpServerException(msg);
  +	    }
  +	    running=true;
  +	    System.out.println("Starting tcp endpoint on " + port + " with " + handler.getClass().getName());
  +        if(isPool) {
  +    	    listener = new TcpWorkerThread(this);
  +            tp.runIt(listener);
  +        } else {
  +    	    listener = new TcpListenerThread( this );
  +	        Thread thread = new Thread(listener);
  +	        thread.start();
  +	    }
       }
   
  -    
       public void stopEndpoint() {
  -	running=false;
  -	try {
  -	    serverSocket.close(); // XXX?
  -	} catch(Exception e) {
  -	}
  -	serverSocket = null;
  -
  +        tp.shutdown();
  +	    running=false;
  +	    try {
  +	        serverSocket.close(); // XXX?
  +	    } catch(Exception e) {
  +	    }
  +	    serverSocket = null;
       }
   
  -
  -
       // -------------------- Private methods
   
  -    void processSocket( Socket s )
  -	throws IOException
  +    void processSocket(Socket s) throws IOException
       {
  -	// XXX reuse, pools, etc
  +    	// XXX reuse, pools, etc
  +
  +    	// XXX set socket options
  +    	// 	s.setSoLinger( true, 100);
  +    	//	s.setSoTimeout( 1000 );
  +
  +    	TcpConnection con=new TcpConnection();
  +    	con.setEndpoint(this);
  +    	con.setSocket( s );
  +    	TcpConnectionHandler handler = getConnectionHandler();
  +    	TcpConnectionThread handlerThread=new TcpConnectionThread(handler, con);
   
  -	// XXX set socket options
  -	// 	s.setSoLinger( true, 100);
  -	//	s.setSoTimeout( 1000 );
  -	
  -	TcpConnection con=new TcpConnection();
  -	con.setEndpoint(this);
  -	con.setSocket( s );
  -	TcpConnectionHandler handler = getConnectionHandler();
  -	TcpConnectionThread handlerThread=new TcpConnectionThread(handler, con);
  -	
  -	new Thread(handlerThread).start();
  +   	    new Thread(handlerThread).start();
       }
  -    
  +
       void acceptConnections() {
  -	try {
  -	    if (running == false)
  -		return;
  -
  -	    if( null!= serverSocket) {
  -		Socket socket = serverSocket.accept();
  -		if (running == false) {
  -		    socket.close();  // rude, but unlikely!
  -		}
  -		processSocket(socket);
  -	    }
  -	} catch (InterruptedIOException iioe) {
  -	    // normal part -- should happen regularly so
  -	    // that the endpoint can release if the server
  -	    // is shutdown.
  -	    // you know, i really wish that there was a
  -	    // way for the socket to timeout without
  -	    // tripping an exception. Exceptions are so
  -	    // 'spensive.
  -	} catch (SocketException e) {
  -	    if (running != false) {
  -		running = false;
  -		String msg = sm.getString("endpoint.err.fatal",
  -					  serverSocket, e);
  -		e.printStackTrace(); // something very wrong happened - better know what
  -		System.err.println(msg);
  -	    }
  -	} catch (Exception e) {
  -	    running = false;
  -	    String msg = sm.getString("endpoint.err.fatal",
  -				      serverSocket, e);
  -	    e.printStackTrace(); // something very wrong happened - better know what
  -	    System.err.println(msg);
  -	}
  -    }
  +    	try {
  +    	    if(running == false)
  +        		return;
  +
  +    	    if(null!= serverSocket) {
  +        		Socket socket = acceptSocket();
  +    	    	if(running != false) {
  +        		    processSocket(socket);
  +        		}
  +    	    }
  +    	} catch(Throwable e) {
  +    	    running = false;
  +    	    String msg = sm.getString("endpoint.err.fatal",
  +    				                  serverSocket, e);
  +    	    e.printStackTrace(); // something very wrong happened - better know what
  +    	    System.err.println(msg);
  +    	}
  +    }
  +
  +    Socket acceptSocket() {
  +        Socket accepted = null;
  +    	try {
  +    	    if(running == true) {
  +        	    if(null!= serverSocket) {
  +            		accepted = serverSocket.accept();
  +    	        	if(running == false) {
  +    	        	    if(null != accepted) {
  +        		            accepted.close();  // rude, but unlikely!
  +        		            accepted = null;
  +        		        }
  +    		        }
  +    	        }
  +    	    }
  +    	} catch(InterruptedIOException iioe) {
  +    	    // normal part -- should happen regularly so
  +    	    // that the endpoint can release if the server
  +    	    // is shutdown.
  +    	    // you know, i really wish that there was a
  +    	    // way for the socket to timeout without
  +    	    // tripping an exception. Exceptions are so
  +    	    // 'spensive.
  +    	} catch (SocketException e) {
  +    	    if (running != false) {
  +        		running = false;
  +        		String msg = sm.getString("endpoint.err.fatal",
  +    					                  serverSocket, e);
  +    	    	e.printStackTrace(); // something very wrong happened - better know what
  +    		    System.err.println(msg);
  +    	    }
  +    	} catch(Throwable e) {
  +    	    running = false;
  +    	    String msg = sm.getString("endpoint.err.fatal",
  +    				                  serverSocket, e);
  +    	    e.printStackTrace(); // something very wrong happened - better know what
  +    	    System.err.println(msg);
  +    	}
   
  +    	return accepted;
  +    }
   }
   
  -// -------------------- Threads -------------------- 
  +// -------------------- Threads --------------------
   // XXX add a more efficient model - use thread pools, use a Queue, etc
   
   // Keep the thread model in one place !
   
  +/*
  + * I switched the threading model here.
  + *
  + * We used to have a "listener" thread and a "connection"
  + * thread, this results in code simplicity but also a needless
  + * thread switch.
  + *
  + * Instead I am now using a pool of threads, all the threads are
  + * simmetric in their execution and no thread switch is needed.
  + */
  +class TcpWorkerThread implements Runnable {
  +    TcpEndpoint endpoint;
  +    Vector connectionCache;
  +
  +    public TcpWorkerThread(TcpEndpoint endpoint) {
  +	    this.endpoint = endpoint;
  +	    connectionCache = new Vector(endpoint.getMaxThreads());
  +	    for(int i = 0 ; i < endpoint.getMaxThreads()/2 ; i++) {
  +	        connectionCache.addElement(new TcpConnection());
  +	    }
  +    }
  +
  +    public void run() {
  +	    while(endpoint.running) {
  +	        Socket s = endpoint.acceptSocket();
  +	        if(null != s) {
  +	            // Continue accepting on another thread...
  +	            endpoint.tp.runIt(this);
  +
  +	            TcpConnection con = null;
  +	            try {
  +                	// XXX set socket options
  +                	// 	s.setSoLinger( true, 100);
  +                	//	s.setSoTimeout( 1000 );
  +                    try {
  +                        con = (TcpConnection)connectionCache.lastElement();
  +                        connectionCache.removeElementAt(connectionCache.size() - 1);
  +                    } catch(Throwable t) {
  +                        con = new TcpConnection();
  +                    }
  +
  +                	con.setEndpoint(endpoint);
  +                	con.setSocket(s);
  +                	endpoint.getConnectionHandler().processConnection(con, null);
  +                } finally {
  +                    con.recycle();
  +                    connectionCache.addElement(con);
  +                }
  +
  +                break;
  +	        }
  +	    }
  +    }
  +}
  +
   // Listener thread
   class TcpListenerThread implements Runnable {
       TcpEndpoint endpoint;
  -    
  +
       public TcpListenerThread( TcpEndpoint endpoint) {
  -	this.endpoint=endpoint;
  +    	this.endpoint=endpoint;
       }
  -    
  +
       public void run() {
  -	while (endpoint.running) {
  -	    endpoint.acceptConnections();
  -	}
  -	//endpoint.manager.notifyEndpointDown(this);
  +	    while (endpoint.running) {
  +	        endpoint.acceptConnections();
  +    	}
  +	    //endpoint.manager.notifyEndpointDown(this);
       }
   }
   
  -// Worker Thread 
  +// Worker Thread
   // call handleConnection() in a new thread
   // XXX thread reuse!
   class TcpConnectionThread implements Runnable {
       TcpConnectionHandler handler;
       TcpConnection connection;
  -    
  +
       public TcpConnectionThread( TcpConnectionHandler handler, TcpConnection connection) {
  -	this.handler=handler;
  -	this.connection=connection;
  +    	this.handler=handler;
  +	    this.connection=connection;
       }
  -    
  +
       public void run() {
  -	handler.processConnection(connection, null);
  +	    handler.processConnection(connection, null);
       }
   }
  -    
  -
  
  
  
  1.4       +106 -70   jakarta-tomcat/src/share/org/apache/tomcat/service/TcpEndpointConnector.java
  
  Index: TcpEndpointConnector.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpEndpointConnector.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TcpEndpointConnector.java	2000/02/09 23:26:28	1.3
  +++ TcpEndpointConnector.java	2000/02/17 10:37:42	1.4
  @@ -1,13 +1,13 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpEndpointConnector.java,v 1.3 2000/02/09 23:26:28 costin Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/02/09 23:26:28 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/TcpEndpointConnector.java,v 1.4 2000/02/17 10:37:42 shachor Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/02/17 10:37:42 $
    *
    * ====================================================================
    *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -15,7 +15,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    notice, this list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
  @@ -23,15 +23,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    any, must include the following acknowlegement:
  + *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowlegement may appear in the software itself,
    *    if and wherever such third-party acknowlegements normally appear.
    *
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written 
  + *    from this software without prior written permission. For written
    *    permission, please contact apache@apache.org.
    *
    * 5. Products derived from this software may not be called "Apache"
  @@ -59,7 +59,7 @@
    *
    * [Additional notices, if required by prior licensing conditions]
    *
  - */ 
  + */
   
   
   package org.apache.tomcat.service;
  @@ -78,8 +78,8 @@
      It should do nothing more - as soon as it get a socket ( and all socket options
      are set, etc), it just handle the stream to ConnectionHandler.processConnection. (costin)
   */
  -   
  -   
  +
  +
   
   /**
    * Connector for a TCP-based connector using the API in tomcat.service.
  @@ -87,6 +87,7 @@
    * the TCP connection handler
    *
    * @author costin@eng.sun.com
  + * @author Gal Shachor [shachor@il.ibm.com]
    */
   public class TcpEndpointConnector  implements ServerConnector {
       // Attributes we accept ( to support the old model of
  @@ -99,6 +100,19 @@
       public static final String VHOST_ADDRESS="vhost_address";
       public static final String SOCKET_FACTORY="socketFactory";
   
  +
  +    public static final String PORT = "port";
  +    public static final String HANDLER = "handler";
  +
  +    /*
  +     * Threading and mod_mpm style properties.
  +     */
  +    public static final String THREAD_POOL = "thread_pool";
  +    public static final String MAX_THREADS = "max_threads";
  +    public static final String MAX_SPARE_THREADS = "max_spare_threads";
  +    public static final String MIN_SPARE_THREADS = "min_spare_threads";
  +    public static final String BACKLOG = "backlog";
  +
       // XXX define ConnectorException
       // XXX replace strings with sm.get...
       // XXX replace static strings with constants
  @@ -107,109 +121,131 @@
       TcpConnectionHandler con;
   
       ContextManager cm;
  -    
  +
       private InetAddress address;
       private int port;
   
  +    private int backlog = -1;
  +    private boolean usePools = true;
  +    private int maxThreads = -1;
  +    private int maxSpareThreads = -1;
  +    private int minSpareThreads = -1;
  +
       int vport;
   
       private ServerSocketFactory socketFactory;
       private ServerSocket serverSocket;
   
       boolean running = true;
  -    
  +
       public TcpEndpointConnector() {
  -	ep=new TcpEndpoint();
  +    	ep = new TcpEndpoint();
       }
   
       public void start() throws Exception {
  -	if( con==null) throw new Exception( "Invalid ConnectionHandler");
  -	con.setAttribute("context.manager",cm );
  -	ep.setPort(port);
  -	if( socketFactory != null) {
  -	    ep.setServerSocketFactory( socketFactory );
  -	}
  -	ep.setConnectionHandler( con );
  -	ep.startEndpoint();
  +    	if(con==null)
  +    	    throw new Exception( "Invalid ConnectionHandler");
  +
  +	    con.setAttribute("context.manager",cm );
  +    	ep.setPort(port);
  +    	ep.setPoolOn(usePools);
  +    	if(backlog > 0) {
  +    	    ep.setBacklog(backlog);
  +    	}
  +    	if(maxThreads > 0) {
  +    	    ep.setMaxThreads(maxThreads);
  +    	}
  +    	if(maxSpareThreads > 0) {
  +    	    ep.setMaxSpareThreads(maxSpareThreads);
  +    	}
  +    	if(minSpareThreads > 0) {
  +    	    ep.setMinSpareThreads(minSpareThreads);
  +    	}
  +
  +	    if(socketFactory != null) {
  +	        ep.setServerSocketFactory( socketFactory );
  +	    }
  +	    ep.setConnectionHandler( con );
  +	    ep.startEndpoint();
       }
   
       public void stop() throws Exception {
  -	ep.stopEndpoint();
  +    	ep.stopEndpoint();
       }
   
       public void setContextManager( ContextManager ctx ) {
  -	this.cm=ctx;
  +	    this.cm=ctx;
       }
   
       public void setTcpConnectionHandler( TcpConnectionHandler handler) {
  -	this.con=handler;
  +    	this.con=handler;
       }
   
       public TcpConnectionHandler getTcpConnectionHandler() {
  -	return con;
  +	    return con;
       }
   
       public void setPort( int port ) {
  -	this.port=port;
  +    	this.port=port;
       }
   
       public void setPort(  String portS ) {
  -	this.port=string2Int( portS );
  +	    this.port=string2Int( portS );
       }
   
       public int getPort() {
  -	return port;
  +    	return port;
       }
  -    
  +
       public void setProperty( String prop, String value) {
  -	if("port".equals(prop) ) {
  -	    setPort( value );
  -	}
  -	if("handler".equals(prop)) {
  -	    try {
  -		Class chC=Class.forName( value );
  -		con=(TcpConnectionHandler)chC.newInstance();
  -	    } catch( Exception ex) {
  -		ex.printStackTrace();
  -	    }
  -	    
  -	}
  +    	if(PORT.equals(prop) ) {
  +    	    setPort( value );
  +    	} else if(HANDLER.equals(prop)) {
  +    	    try {
  +        		Class chC=Class.forName( value );
  +    	    	con=(TcpConnectionHandler)chC.newInstance();
  +    	    } catch( Exception ex) {
  +        		ex.printStackTrace();
  +    	    }
  +    	} else if(THREAD_POOL.equals(prop)) {
  +    	    if(value.equalsIgnoreCase("off")) {
  +    	        usePools = false;
  +    	    }
  +    	} else if(MAX_THREADS.equals(prop)) {
  +    	    maxThreads = string2Int(value);
  +    	} else if(MAX_SPARE_THREADS.equals(prop)) {
  +    	    maxSpareThreads = string2Int(value);
  +    	} else if(MIN_SPARE_THREADS.equals(prop)) {
  +    	    minSpareThreads = string2Int(value);
  +    	} else if(BACKLOG.equals(prop)) {
  +    	    backlog = string2Int(value);
  +    	}
       }
   
       // XXX use constants, remove dep on HttpServer
       public void setAttribute( String prop, Object value) {
  -	if(VHOST_NAME.equals(prop) ) {
  -	    //vhost=(String)value;
  -	}
  -	if(VHOST_PORT.equals(prop) ) {
  -	    vport=((Integer)value).intValue();
  -	}
  -
  -	if(VHOST_ADDRESS.equals(prop)) {
  -	    address=(InetAddress)value;
  -	}
  -	if(SERVER.equals(prop)) {
  -	    //server=(HttpServer)value;
  -	}
  -	if(SOCKET_FACTORY.equals(prop)) {
  -	    socketFactory=(ServerSocketFactory)value;
  -	}
  +    	if(VHOST_NAME.equals(prop) ) {
  +	        //vhost=(String)value;
  +	    } else if(VHOST_PORT.equals(prop) ) {
  +	        vport=((Integer)value).intValue();
  +	    } else if(VHOST_ADDRESS.equals(prop)) {
  +	        address=(InetAddress)value;
  +	    } else if(SERVER.equals(prop)) {
  +    	    //server=(HttpServer)value;
  +	    } else if(SOCKET_FACTORY.equals(prop)) {
  +    	    socketFactory=(ServerSocketFactory)value;
  +	    }
       }
   
       public Object getAttribute( String prop ) {
  -	return null;
  +	    return null;
       }
   
       private int string2Int( String val) {
  -	try {
  -	    return Integer.parseInt(val);
  -	} catch (NumberFormatException nfe) {
  -	    return 0;
  -	}
  +    	try {
  +	        return Integer.parseInt(val);
  +    	} catch (NumberFormatException nfe) {
  +	        return 0;
  +    	}
       }
  -
  -
  -    
  -}
  -    
  -
  +}
  \ No newline at end of file