FileDocCategorySizeDatePackage
PoolTcpEndpoint.javaAPI DocGlassfish v2 API17835Fri May 04 22:33:16 BST 2007org.apache.tomcat.util.net

PoolTcpEndpoint

public class PoolTcpEndpoint extends Object
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. More advanced Endpoints will reuse the threads, use queues, etc.
author
James Duncan Davidson [duncan@eng.sun.com]
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]

Fields Summary
private org.apache.tomcat.util.res.StringManager
sm
private static final int
BACKLOG
private static final int
TIMEOUT
private final Object
threadSync
private boolean
isPool
private int
backlog
private int
serverTimeout
TcpConnectionHandler
handler
private InetAddress
inet
private int
port
private ServerSocketFactory
factory
private ServerSocket
serverSocket
org.apache.tomcat.util.threads.ThreadPoolRunnable
listener
private volatile boolean
running
private boolean
initialized
private boolean
reinitializing
static final int
debug
org.apache.tomcat.util.threads.ThreadPool
tp
static com.sun.org.apache.commons.logging.Log
log
protected boolean
tcpNoDelay
protected int
linger
protected int
socketTimeout
Constructors Summary
public PoolTcpEndpoint()

    
      
	//	super("tc_log");	// initialize default logger
	tp = new ThreadPool();
    
public PoolTcpEndpoint(org.apache.tomcat.util.threads.ThreadPool tp)

        this.tp=tp;
    
Methods Summary
java.net.SocketacceptSocket()

        if( !running || serverSocket==null ) return null;

        Socket accepted = null;

    	try {
            if(factory==null) {
                accepted = serverSocket.accept();
            } else {
                accepted = factory.acceptSocket(serverSocket);
            }
            if (null == accepted) {
                log.warn("Null socket returned by accept");
            } else {
                if (!running) {
                    accepted.close();  // rude, but unlikely!
                    accepted = null;
                } else if (factory != null) {
                    factory.initSocket( accepted );
                }
            }
        }
        catch(InterruptedIOException iioe) {
            // normal part -- should happen regularly so
            // that the endpoint can release if the server
            // is shutdown.
        }
        catch (AccessControlException ace) {
            // When using the Java SecurityManager this exception
            // can be thrown if you are restricting access to the
            // socket with SocketPermission's.
            // Log the unauthorized access and continue
            String msg = sm.getString("endpoint.warn.security",
                                      serverSocket,ace);
            log.warn(msg);
        }
        catch (IOException e) {

            String msg = null;

            if (running) {
                msg = sm.getString("endpoint.err.nonfatal",
                        serverSocket, e);
                log.error(msg, e);
            }

            if (accepted != null) {
                try {
                    accepted.close();
                } catch(Throwable ex) {
                    msg = sm.getString("endpoint.err.nonfatal",
                                       accepted, ex);
                    log.warn(msg, ex);
                }
                accepted = null;
            }

            if( ! running ) return null;
            reinitializing = true;
            // Restart endpoint when getting an IOException during accept
            synchronized (threadSync) {
                if (reinitializing) {
                    reinitializing = false;
                    // 1) Attempt to close server socket
                    closeServerSocket();
                    initialized = false;
                    // 2) Reinit endpoint (recreate server socket)
                    try {
                        msg = sm.getString("endpoint.warn.reinit");
                        log.warn(msg);
                        initEndpoint();
                    } catch (Throwable t) {
                        msg = sm.getString("endpoint.err.nonfatal",
                                           serverSocket, t);
                        log.error(msg, t);
                    }
                    // 3) If failed, attempt to restart endpoint
                    if (!initialized) {
                        msg = sm.getString("endpoint.warn.restart");
                        log.warn(msg);
                        try {
                            stopEndpoint();
                            initEndpoint();
                            startEndpoint();
                        } catch (Throwable t) {
                            msg = sm.getString("endpoint.err.fatal",
                                               serverSocket, t);
                            log.error(msg, t);
                        } finally {
                            // Current thread is now invalid: kill it
                            throw new ThreadDeath();
                        }
                    }
                }
            }

        }

        return accepted;
    
protected voidcloseServerSocket()

        Socket s = null;
        try {
            // Need to create a connection to unlock the accept();
            if (inet == null) {
                s=new Socket("127.0.0.1", port );
            }else{
                s=new Socket(inet, port );
                    // setting soLinger to a small value will help shutdown the
                    // connection quicker
                s.setSoLinger(true, 0);
            }
        } catch(Exception e) {
            log.error("Caught exception trying to unlock accept on " + port
                    + " " + e.toString());
        } finally {
            if (s != null) {
                try {
                    s.close();
                } catch (Exception e) {
                    // Ignore
                }
            }
        }
        try {
            if( serverSocket!=null)
                serverSocket.close();
        } catch(Exception e) {
            log.error("Caught exception trying to close socket.", e);
        }
        serverSocket = null;
    
public java.net.InetAddressgetAddress()

	    return inet;
    
public intgetBacklog()

        return backlog;
    
public TcpConnectionHandlergetConnectionHandler()

	    return handler;
    
public intgetMaxSpareThreads()

        return tp.getMaxSpareThreads();
    
public intgetMaxThreads()

        return tp.getMaxThreads();
    
public intgetMinSpareThreads()

        return tp.getMinSpareThreads();
    
public intgetPort()

        return port;
    
public intgetServerSoTimeout()

        return serverTimeout;
    
ServerSocketFactorygetServerSocketFactory()

 	    return factory;
   
public intgetSoLinger()

        return linger;
    
public intgetSoTimeout()

        return socketTimeout;
    
public booleangetTcpNoDelay()

        return tcpNoDelay;
    
public voidinitEndpoint()

	try {
	    if(factory==null)
		factory=ServerSocketFactory.getDefault();
	    if(serverSocket==null) {
                try {
                    if (inet == null) {
                        serverSocket = factory.createSocket(port, backlog);
                    } else {
                        serverSocket = factory.createSocket(port, backlog, inet);
                    }
                } catch ( BindException be ) {
                    throw new BindException(be.getMessage() + ":" + port);
                }
	    }
            if( serverTimeout >= 0 )
		serverSocket.setSoTimeout( serverTimeout );
	} catch( IOException ex ) {
	    //	    log("couldn't start endpoint", ex, Logger.DEBUG);
            throw ex;
	} catch( InstantiationException ex1 ) {
	    //	    log("couldn't start endpoint", ex1, Logger.DEBUG);
            throw ex1;
	}
        initialized = true;
    
public booleanisPoolOn()

        return isPool;
    
public booleanisRunning()

	return running;
    
public voidlog(java.lang.String msg)

deprecated

	log.info(msg);
    
public voidlog(java.lang.String msg, java.lang.Throwable t)

deprecated

	log.error( msg, t );
    
public voidlog(java.lang.String msg, int level)

deprecated

	log.info( msg );
    
public voidlog(java.lang.String msg, java.lang.Throwable t, int level)

deprecated

    	log.error( msg, t );
    
public voidsetAddress(java.net.InetAddress inet)

	    this.inet=inet;
    
public voidsetBacklog(int backlog)
Allows the server developer to specify the backlog that should be used for server sockets. By default, this value is 100.

	if( backlog>0)
	    this.backlog = backlog;
    
public voidsetConnectionHandler(TcpConnectionHandler handler)

    	this.handler=handler;
    
public voidsetMaxSpareThreads(int maxThreads)

	if(maxThreads > 0) 
	    tp.setMaxSpareThreads(maxThreads);
    
public voidsetMaxThreads(int maxThreads)

	if( maxThreads > 0)
	    tp.setMaxThreads(maxThreads);
    
public voidsetMinSpareThreads(int minThreads)

	if(minThreads > 0) 
	    tp.setMinSpareThreads(minThreads);
    
public voidsetPoolOn(boolean isPool)

        this.isPool = isPool;
    
public voidsetPort(int port)

        this.port=port;
    
public voidsetServerSoTimeout(int i)

	serverTimeout=i;
    
public voidsetServerSocket(java.net.ServerSocket ss)

	    serverSocket = ss;
    
public voidsetServerSocketFactory(ServerSocketFactory factory)

	    this.factory=factory;
    
public voidsetServerTimeout(int timeout)
Sets the timeout in ms of the server sockets created by this server. This method allows the developer to make servers more or less responsive to having their server sockets shut down.

By default this value is 1000ms.

	this.serverTimeout = timeout;
    
public voidsetSoLinger(int i)

	linger=i;
    
public voidsetSoTimeout(int i)

	socketTimeout=i;
    
voidsetSocketOptions(java.net.Socket socket)

        if(linger >= 0 ) 
            socket.setSoLinger( true, linger);
        if( tcpNoDelay )
            socket.setTcpNoDelay(tcpNoDelay);
        if( socketTimeout > 0 )
            socket.setSoTimeout( socketTimeout );
    
public voidsetTcpNoDelay(boolean b)

	tcpNoDelay=b;
    
public voidstartEndpoint()

        if (!initialized) {
            initEndpoint();
        }
	if(isPool) {
	    tp.start();
	}
	running = true;
        if(isPool) {
    	    listener = new TcpWorkerThread(this);
            tp.runIt(listener);
        } else {
	    log.error("XXX Error - need pool !");
	}
    
public voidstopEndpoint()

	if (running) {
	    tp.shutdown();
	    running = false;
            if (serverSocket != null) {
                closeServerSocket();
            }
	}