You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2005/11/24 06:24:29 UTC
svn commit: r348657 -
/tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java
Author: costin
Date: Wed Nov 23 21:24:26 2005
New Revision: 348657
URL: http://svn.apache.org/viewcvs?rev=348657&view=rev
Log:
New Endpoint - as simple as possible, no 'spare threads' or recycling. This is a good
fit for embedded - where footprint is more important and you don't expect huge loads. It
also makes it easy to organize the code.
Note that all the SSL code is gone too ( both here and in base class ) - so same approach as Apr could
be taken. Instead of having SslImpl and all the other classes, that will be specific to the endpoint.
Added:
tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java
Added: tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java
URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java?rev=348657&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java Wed Nov 23 21:24:26 2005
@@ -0,0 +1,379 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation
+ *
+ * Licensed 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.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.BindException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.security.AccessControlException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * Very simple endpoint - no thread pool, no recycling, etc.
+ *
+ * Relies the JVM thread pool, if any.
+ *
+ * Used for embedded use cases, where you wouldn't expect a huge load, and
+ * memory is important ( no caching or keeping around objects ).
+ *
+ * Note that ServerSocket and the whole SSL machinery is also gone - instead
+ * use a subclass that extends this and knows about ssl. We may add it back, but
+ * needs to be fixed.
+ *
+ * @author Costin Manolache ( costin@apache.org )
+ */
+public class SimpleEndpoint extends PoolTcpEndpoint {
+
+ static Log log=LogFactory.getLog(SimpleEndpoint.class );
+
+ private final Object threadSync = new Object();
+
+ /* The background thread. */
+ private Thread thread = null;
+
+ public SimpleEndpoint() {
+ }
+
+
+ // -------------------- Public methods --------------------
+
+ public void initEndpoint() throws IOException, InstantiationException {
+ try {
+ if(serverSocket==null) {
+ try {
+ if (inet == null) {
+ serverSocket = new ServerSocket(port, backlog);
+ } else {
+ serverSocket = new ServerSocket(port, backlog, inet);
+ }
+ } catch ( BindException be ) {
+ throw new BindException(be.getMessage() + ":" + port);
+ }
+ }
+ if( serverTimeout >= 0 )
+ serverSocket.setSoTimeout( serverTimeout );
+
+ thread = new Thread(this, "SimpleEP");
+ thread.setDaemon(daemon);
+ if( getThreadPriority() > 0 ) {
+ thread.setPriority(getThreadPriority());
+ }
+ thread.setDaemon(true);
+ thread.start();
+
+ } catch( IOException ex ) {
+ throw ex;
+ }
+ initialized = true;
+ }
+
+ public void startEndpoint() throws IOException, InstantiationException {
+ if (!initialized) {
+ initEndpoint();
+ }
+ running = true;
+ paused = false;
+
+ }
+
+ public void pauseEndpoint() {
+ if (running && !paused) {
+ paused = true;
+ unlockAccept();
+ }
+ }
+
+ public void resumeEndpoint() {
+ if (running) {
+ paused = false;
+ }
+ }
+
+ public void stopEndpoint() {
+ if (running) {
+ running = false;
+ if (serverSocket != null) {
+ closeServerSocket();
+ }
+ initialized=false ;
+ }
+ }
+
+ protected void closeServerSocket() {
+ if (!paused)
+ unlockAccept();
+ try {
+ if( serverSocket!=null)
+ serverSocket.close();
+ } catch(Exception e) {
+ log.error(sm.getString("endpoint.err.close"), e);
+ }
+ serverSocket = null;
+ }
+
+ protected void unlockAccept() {
+ 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) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
+ }
+ } finally {
+ if (s != null) {
+ try {
+ s.close();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
+ // -------------------- Private methods
+
+ Socket acceptSocket() {
+ if( !running || serverSocket==null ) return null;
+
+ Socket accepted = null;
+
+ try {
+ accepted = serverSocket.accept();
+ if (null == accepted) {
+ log.warn(sm.getString("endpoint.warn.nullSocket"));
+ } else {
+ if (!running) {
+ 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.
+ }
+ 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);
+ }
+ // Current thread is now invalid: kill it
+ throw new ThreadDeath();
+ }
+ }
+ }
+
+ }
+
+ return accepted;
+ }
+
+ protected void processSocket(Socket s, TcpConnection con, Object[] threadData) {
+ // Process the connection
+ int step = 1;
+ try {
+
+ // 1: Set socket options: timeout, linger, etc
+ setSocketOptions(s);
+
+ // 2: SSL handshake
+ step = 2;
+
+ // 3: Process the connection
+ step = 3;
+ con.setEndpoint(this);
+ con.setSocket(s);
+ getConnectionHandler().processConnection(con, threadData);
+
+ } catch (SocketException se) {
+ log.error(sm.getString("endpoint.err.socket", s.getInetAddress()),
+ se);
+ // Try to close the socket
+ try {
+ s.close();
+ } catch (IOException e) {
+ }
+ } catch (Throwable t) {
+ if (step == 2) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("endpoint.err.handshake"), t);
+ }
+ } else {
+ log.error(sm.getString("endpoint.err.unexpected"), t);
+ }
+ // Try to close the socket
+ try {
+ s.close();
+ } catch (IOException e) {
+ }
+ } finally {
+ if (con != null) {
+ con.recycle();
+ }
+ }
+ }
+
+
+ /**
+ * Accept, dispatch on a new thread. May benefit from VM thread pooling, but
+ * the goal is to minimize the number of resources used.
+ *
+ * TODO: change this to use NIO, use the thread for other control events
+ * ( timers, etc ) that would require a separate thread.
+ *
+ * TODO: maybe add back ability to do pooling, by refactoring ThreadPool
+ * or adding some optional interface. Maybe better abstract the other endpoint
+ * thread models in a new TP interface.
+ */
+ public void run() {
+
+ // Loop until we receive a shutdown command
+ while (running) {
+
+ // Loop if endpoint is paused
+ while (paused) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+
+ // Accept the next incoming connection from the server socket
+ Socket socket = acceptSocket();
+
+ // Hand this socket off to an appropriate processor
+ Thread t=new Thread( new SimpleThread(this, socket) );
+ t.setDaemon(daemon);
+ if( getThreadPriority() > 0 )
+ t.setPriority(getThreadPriority());
+
+ threadStart( t );// notify listeners
+
+ t.start();
+
+ }
+
+ // Notify the threadStop() method that we have shut ourselves down
+ synchronized (threadSync) {
+ threadSync.notifyAll();
+ }
+
+ }
+
+ static class SimpleThread implements Runnable {
+
+ private Socket socket;
+ private PoolTcpEndpoint ep;
+ private ThreadLocal tl=new ThreadLocal();
+
+ public SimpleThread(SimpleEndpoint endpoint, Socket socket) {
+ this.socket = socket;
+ this.ep = endpoint;
+ }
+
+ public void run() {
+ Object[] threadData = (Object [])tl.get();
+ if( threadData == null ) {
+ threadData=new Object[2];
+ threadData[0]=new TcpConnection();
+ threadData[1] = ep.getConnectionHandler().init();
+ tl.set(threadData);
+ } else {
+ System.err.println("Congrats, the VM does thread pooling !!!");
+ }
+ ep.processSocket( socket, (TcpConnection)threadData[0],
+ (Object[])threadData[1]);
+
+ ep.threadEnd( Thread.currentThread() );
+ }
+ }
+
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org