org.apache.tomcat.util.net.BaseEndpoint Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomcat.util.net;
import java.net.InetAddress;
import java.util.concurrent.Executor;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
/**
* APR tailored thread pool, providing the following services:
*
* - Socket acceptor thread
* - Socket poller thread
* - Sendfile thread
* - Worker threads pool
*
*
* When switching to Java 5, there's an opportunity to use the virtual
* machine's thread pool.
*
* @author Mladen Turk
* @author Remy Maucherat
*/
public abstract class BaseEndpoint {
// -------------------------------------------------------------- Constants
protected static Log log = LogFactory.getLog(BaseEndpoint.class);
protected static StringManager sm =
StringManager.getManager("org.apache.tomcat.util.net.res");
/**
* The Request attribute key for the cipher suite.
*/
public static final String CIPHER_SUITE_KEY = "javax.servlet.request.cipher_suite";
/**
* The Request attribute key for the key size.
*/
public static final String KEY_SIZE_KEY = "javax.servlet.request.key_size";
/**
* The Request attribute key for the client certificate chain.
*/
public static final String CERTIFICATE_KEY = "javax.servlet.request.X509Certificate";
/**
* The Request attribute key for the session id.
* This one is a Tomcat extension to the Servlet spec.
*/
public static final String SESSION_ID_KEY = "javax.servlet.request.ssl_session";
// ----------------------------------------------------------------- Fields
/**
* Running state of the endpoint.
*/
protected volatile boolean running = false;
/**
* Will be set to true whenever the endpoint is paused.
*/
protected volatile boolean paused = false;
/**
* Track the initialization state of the endpoint.
*/
protected boolean initialized = false;
/**
* Current worker threads busy count.
*/
protected int curThreadsBusy = 0;
/**
* Current worker threads count.
*/
protected int curThreads = 0;
/**
* Sequence number used to generate thread names.
*/
protected int sequence = 0;
// ------------------------------------------------------------- Properties
/**
* External Executor based thread pool.
*/
protected Executor executor = null;
public void setExecutor(Executor executor) { this.executor = executor; }
public Executor getExecutor() { return executor; }
/**
* Maximum amount of worker threads.
*/
protected int maxThreads = 200;
public void setMaxThreads(int maxThreads) { this.maxThreads = maxThreads; }
public int getMaxThreads() { return maxThreads; }
/**
* Priority of the acceptor and poller threads.
*/
protected int threadPriority = Thread.NORM_PRIORITY;
public void setThreadPriority(int threadPriority) { this.threadPriority = threadPriority; }
public int getThreadPriority() { return threadPriority; }
/**
* Server socket port.
*/
protected int port;
public int getPort() { return port; }
public void setPort(int port ) { this.port=port; }
/**
* Address for the server socket.
*/
protected InetAddress address;
public InetAddress getAddress() { return address; }
public void setAddress(InetAddress address) { this.address = address; }
/**
* Allows the server developer to specify the backlog that
* should be used for server sockets. By default, this value
* is 100.
*/
protected int backlog = 100;
public void setBacklog(int backlog) { if (backlog > 0) this.backlog = backlog; }
public int getBacklog() { return backlog; }
/**
* Socket TCP no delay.
*/
protected boolean tcpNoDelay = false;
public boolean getTcpNoDelay() { return tcpNoDelay; }
public void setTcpNoDelay(boolean tcpNoDelay) { this.tcpNoDelay = tcpNoDelay; }
/**
* Socket linger.
*/
protected int soLinger = 100;
public int getSoLinger() { return soLinger; }
public void setSoLinger(int soLinger) { this.soLinger = soLinger; }
/**
* Socket timeout.
*/
protected int soTimeout = -1;
public int getSoTimeout() { return soTimeout; }
public void setSoTimeout(int soTimeout) { this.soTimeout = soTimeout; }
/**
* The default is true - the created threads will be
* in daemon mode. If set to false, the control thread
* will not be daemon - and will keep the process alive.
*/
protected boolean daemon = true;
public void setDaemon(boolean b) { daemon = b; }
public boolean getDaemon() { return daemon; }
/**
* Name of the thread pool, which will be used for naming child threads.
*/
protected String name = "TP";
public void setName(String name) { this.name = name; }
public String getName() { return name; }
/**
* Dummy maxSpareThreads property.
*/
public int getMaxSpareThreads() { return 0; }
/**
* Dummy minSpareThreads property.
*/
public int getMinSpareThreads() { return 0; }
// --------------------------------------------------------- Public Methods
/**
* Return the amount of threads that are managed by the pool.
*
* @return the amount of threads that are managed by the pool
*/
public int getCurrentThreadCount() {
return curThreads;
}
/**
* Return the amount of threads currently busy.
*
* @return the amount of threads currently busy
*/
public int getCurrentThreadsBusy() {
return curThreadsBusy;
}
/**
* Return the state of the endpoint.
*
* @return true if the endpoint is running, false otherwise
*/
public boolean isRunning() {
return running;
}
/**
* Return the state of the endpoint.
*
* @return true if the endpoint is paused, false otherwise
*/
public boolean isPaused() {
return paused;
}
// ----------------------------------------------- Public Lifecycle Methods
/**
* Initialize the endpoint.
*/
public abstract void init()
throws Exception;
/**
* Start the APR endpoint, creating acceptor, poller and sendfile threads.
*/
public abstract void start()
throws Exception;
/**
* Pause the endpoint, which will make it stop accepting new sockets.
*/
public void pause() {
if (running && !paused) {
paused = true;
unlockAccept();
}
}
/**
* Resume the endpoint, which will make it start accepting new sockets
* again.
*/
public void resume() {
if (running) {
paused = false;
}
}
/**
* Stop the endpoint. This will cause all processing threads to stop.
*/
public abstract void stop();
/**
* Deallocate APR memory pools, and close server socket.
*/
public abstract void destroy() throws Exception;
// ------------------------------------------------------ Protected Methods
/**
* Get a sequence number used for thread naming.
*/
protected int getSequence() {
return sequence++;
}
/**
* Unlock the server socket accept using a bugus connection.
*/
protected void unlockAccept() {
java.net.Socket s = null;
try {
// Need to create a connection to unlock the accept();
if (address == null) {
s = new java.net.Socket(InetAddress.getByName("localhost").getHostAddress(), port);
} else {
s = new java.net.Socket(address, port);
// setting soLinger to a small value will help shutdown the
// connection quicker
s.setSoLinger(true, 0);
}
} catch(Exception e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
}
} finally {
if (s != null) {
try {
s.close();
} catch (Exception e) {
// Ignore
}
}
}
}
}