Author: costin Date: Tue Jan 3 23:45:04 2006 New Revision: 365856 URL: http://svn.apache.org/viewcvs?rev=365856&view=rev Log: Remove duplicate code, few more attempts to find a 'consistent' way to deal with apr by implementing nio interfaces using apr.
Added: tomcat/sandbox/java/org/apache/tomcat/util/net/apr/ tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprByteChannel.java tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprEndpoint.java - copied, changed from r348662, tomcat/sandbox/java/org/apache/tomcat/util/net/AprEndpoint.java tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprFileChannel.java tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprSocket.java Added: tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprByteChannel.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprByteChannel.java?rev=365856&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprByteChannel.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprByteChannel.java Tue Jan 3 23:45:04 2006 @@ -0,0 +1,26 @@ +/* + */ +package org.apache.tomcat.util.net.apr; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; + +public class AprByteChannel implements ByteChannel { + + public int read(ByteBuffer dst) throws IOException { + return 0; + } + + public boolean isOpen() { + return false; + } + + public void close() throws IOException { + } + + public int write(ByteBuffer src) throws IOException { + return 0; + } + +} Copied: tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprEndpoint.java (from r348662, tomcat/sandbox/java/org/apache/tomcat/util/net/AprEndpoint.java) URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprEndpoint.java?p2=tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprEndpoint.java&p1=tomcat/sandbox/java/org/apache/tomcat/util/net/AprEndpoint.java&r1=348662&r2=365856&rev=365856&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprEndpoint.java Tue Jan 3 23:45:04 2006 @@ -14,27 +14,26 @@ * limitations under the License. */ -package org.apache.tomcat.util.net; +package org.apache.tomcat.util.net.apr; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Stack; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.tomcat.jni.OS; import org.apache.tomcat.jni.Address; import org.apache.tomcat.jni.Error; -import org.apache.tomcat.jni.File; import org.apache.tomcat.jni.Library; +import org.apache.tomcat.jni.OS; import org.apache.tomcat.jni.Poll; import org.apache.tomcat.jni.Pool; -import org.apache.tomcat.jni.Socket; -import org.apache.tomcat.jni.Status; import org.apache.tomcat.jni.SSL; import org.apache.tomcat.jni.SSLContext; import org.apache.tomcat.jni.SSLSocket; +import org.apache.tomcat.jni.Socket; +import org.apache.tomcat.jni.Status; +import org.apache.tomcat.util.net.PoolTcpEndpoint; +import org.apache.tomcat.util.net.TcpConnection; +import org.apache.tomcat.util.net.TcpConnectionHandler; import org.apache.tomcat.util.res.StringManager; import org.apache.tomcat.util.threads.ThreadWithAttributes; @@ -221,23 +220,6 @@ return sendfileSize; } - - /** - * 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; } - - /** * Handling of accepted sockets. */ @@ -261,32 +243,6 @@ /** - * 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; - } - - - /** * Timeout on first request read before going to the poller, in ms. */ protected int firstReadTimeout = 100; @@ -304,25 +260,6 @@ this.pollTime = pollTime; } - - /** - * 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; } - - /** * Use endfile for sending static files. */ @@ -536,10 +473,10 @@ serverSockPool = Pool.create(rootPool); // Create the APR address that will be bound String addressStr = null; - if (address == null) { + if (inet == null) { addressStr = null; } else { - addressStr = address.getHostAddress(); + addressStr = inet.getHostAddress(); } long inetAddress = Address.info(addressStr, Socket.APR_INET, port, 0, rootPool); @@ -739,37 +676,6 @@ /** - * 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("127.0.0.1", 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 - } - } - } - } - - - /** * Process the specified connection. */ protected boolean setSocketOptions(long socket) { @@ -778,12 +684,12 @@ try { // 1: Set socket options: timeout, linger, etc - if (soLinger >= 0) - Socket.optSet(socket, Socket.APR_SO_LINGER, soLinger); + if (linger >= 0) + Socket.optSet(socket, Socket.APR_SO_LINGER, linger); if (tcpNoDelay) Socket.optSet(socket, Socket.APR_TCP_NODELAY, (tcpNoDelay ? 1 : 0)); - if (soTimeout > 0) - Socket.timeoutSet(socket, soTimeout * 1000); + if (socketTimeout > 0) + Socket.timeoutSet(socket, socketTimeout * 1000); // 2: SSL handshake step = 2; @@ -857,7 +763,7 @@ /** * Return a new worker thread, and block while to worker is available. */ - protected Worker getWorkerThread() { + public Worker getWorkerThread() { // Allocate a new worker thread Worker workerThread = createWorkerThread(); while (workerThread == null) { @@ -942,7 +848,6 @@ } } - } @@ -968,13 +873,13 @@ protected void init() { pool = Pool.create(serverSockPool); try { - serverPollset = Poll.create(pollerSize, pool, 0, soTimeout * 1000); + serverPollset = Poll.create(pollerSize, pool, 0, socketTimeout * 1000); } catch (Error e) { if (Status.APR_STATUS_IS_EINVAL(e.getError())) { try { // Use WIN32 maximum poll size pollerSize = 62; - serverPollset = Poll.create(pollerSize, pool, 0, soTimeout * 1000); + serverPollset = Poll.create(pollerSize, pool, 0, socketTimeout * 1000); log.warn(sm.getString("endpoint.poll.limitedpollsize")); } catch (Error err) { log.error(sm.getString("endpoint.poll.initfail"), e); @@ -1107,7 +1012,7 @@ } } } - if (soTimeout > 0 && maintainTime > 1000000L) { + if (socketTimeout > 0 && maintainTime > 1000000L) { rv = Poll.maintain(serverPollset, desc, true); maintainTime = 0; if (rv > 0) { @@ -1140,7 +1045,7 @@ /** * Server processor class. */ - protected class Worker implements Runnable { + public class Worker implements Runnable { protected Thread thread = null; @@ -1157,7 +1062,7 @@ * * @param socket TCP socket to process */ - protected synchronized void assign(long socket) { + public synchronized void assign(long socket) { // Wait for the Processor to get the previous Socket while (available) { @@ -1250,7 +1155,6 @@ thread.start(); } - } // TODO: theradEnd event, etc @@ -1263,296 +1167,7 @@ // ----------------------------------------------- SendfileData Inner Class - /** - * SendfileData class. - */ - public static class SendfileData { - // File - public String fileName; - public long fd; - public long fdpool; - // Range information - public long start; - public long end; - // Socket and socket pool - public long socket; - // Position - public long pos; - // KeepAlive flag - public boolean keepAlive; - } - - // --------------------------------------------------- Sendfile Inner Class - - - /** - * Sendfile class. - */ - public static class Sendfile implements Runnable { - - protected long sendfilePollset = 0; - protected long pool = 0; - protected long[] desc; - protected HashMap sendfileData; - - protected ArrayList addS; - - protected int sendfileCount = 0; - public int getSendfileCount() { return sendfileCount; } - - AprEndpoint ep; - protected long serverSockPool = 0; - - - protected int sendfileSize = 256; - public void setSendfileSize(int sendfileSize) { this.sendfileSize = sendfileSize; } - public int getSendfileSize() { return sendfileSize; } - - public Sendfile( AprEndpoint ep, long serverSockPool ) { - this.ep = ep; - this.serverSockPool = serverSockPool; - } - - - /** - * Create the sendfile poller. With some versions of APR, the maximum poller size will - * be 62 (reocmpiling APR is necessary to remove this limitation). - */ - protected void init() { - pool = Pool.create(serverSockPool); - try { - sendfilePollset = Poll.create(sendfileSize, pool, 0, ep.getSoTimeout() * 1000); - } catch (Error e) { - if (Status.APR_STATUS_IS_EINVAL(e.getError())) { - try { - // Use WIN32 maximum poll size - sendfileSize = 62; - sendfilePollset = Poll.create(sendfileSize, pool, 0, ep.getSoTimeout() * 1000); - log.warn(sm.getString("endpoint.poll.limitedpollsize")); - } catch (Error err) { - log.error(sm.getString("endpoint.poll.initfail"), e); - } - } else { - log.error(sm.getString("endpoint.poll.initfail"), e); - } - } - desc = new long[sendfileSize * 2]; - sendfileData = new HashMap(sendfileSize); - addS = new ArrayList(); - } - - /** - * Destroy the poller. - */ - protected void destroy() { - // Close any socket remaining in the add queue - for (int i = (addS.size() - 1); i >= 0; i--) { - SendfileData data = (SendfileData) addS.get(i); - Socket.destroy(data.socket); - } - // Close all sockets still in the poller - int rv = Poll.pollset(sendfilePollset, desc); - if (rv > 0) { - for (int n = 0; n < rv; n++) { - Socket.destroy(desc[n*2+1]); - } - } - Pool.destroy(pool); - sendfileData.clear(); - } - - /** - * Add the sendfile data to the sendfile poller. Note that in most cases, - * the initial non blocking calls to sendfile will return right away, and - * will be handled asynchronously inside the kernel. As a result, - * the poller will never be used. - * - * @param data containing the reference to the data which should be snet - * @return true if all the data has been sent right away, and false - * otherwise - */ - public boolean add(SendfileData data) { - // Initialize fd from data given - try { - data.fdpool = Socket.pool(data.socket); - data.fd = File.open - (data.fileName, File.APR_FOPEN_READ - | File.APR_FOPEN_SENDFILE_ENABLED | File.APR_FOPEN_BINARY, - 0, data.fdpool); - data.pos = data.start; - // Set the socket to nonblocking mode - Socket.timeoutSet(data.socket, 0); - while (true) { - long nw = Socket.sendfilen(data.socket, data.fd, - data.pos, data.end - data.pos, 0); - if (nw < 0) { - if (!(-nw == Status.EAGAIN)) { - Socket.destroy(data.socket); - data.socket = 0; - return false; - } else { - // Break the loop and add the socket to poller. - break; - } - } else { - data.pos = data.pos + nw; - if (data.pos >= data.end) { - // Entire file has been sent - Pool.destroy(data.fdpool); - // Set back socket to blocking mode - Socket.timeoutSet(data.socket, ep.getSoTimeout() * 1000); - return true; - } - } - } - } catch (Exception e) { - log.error(sm.getString("endpoint.sendfile.error"), e); - return false; - } - // Add socket to the list. Newly added sockets will wait - // at most for pollTime before being polled - synchronized (addS) { - addS.add(data); - addS.notify(); - } - return false; - } - - /** - * Remove socket from the poller. - * - * @param data the sendfile data which should be removed - */ - protected void remove(SendfileData data) { - int rv = Poll.remove(sendfilePollset, data.socket); - if (rv == Status.APR_SUCCESS) { - sendfileCount--; - } - sendfileData.remove(data); - } - - /** - * The background thread that listens for incoming TCP/IP connections and - * hands them off to an appropriate processor. - */ - public void run() { - - // Loop until we receive a shutdown command - while (ep.isRunning()) { - - // Loop if endpoint is paused - while (ep.isPaused()) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore - } - } - - while (sendfileCount < 1 && addS.size() < 1) { - try { - synchronized (addS) { - addS.wait(); - } - } catch (InterruptedException e) { - // Ignore - } - } - - try { - // Add socket to the poller - if (addS.size() > 0) { - synchronized (addS) { - for (int i = (addS.size() - 1); i >= 0; i--) { - SendfileData data = (SendfileData) addS.get(i); - int rv = Poll.add(sendfilePollset, data.socket, Poll.APR_POLLOUT); - if (rv == Status.APR_SUCCESS) { - sendfileData.put(new Long(data.socket), data); - sendfileCount++; - } else { - log.warn(sm.getString("endpoint.sendfile.addfail", "" + rv)); - // Can't do anything: close the socket right away - Socket.destroy(data.socket); - } - } - addS.clear(); - } - } - // Pool for the specified interval - int rv = Poll.poll(sendfilePollset, ep.getPollTime(), desc, false); - if (rv > 0) { - for (int n = 0; n < rv; n++) { - // Get the sendfile state - SendfileData state = - (SendfileData) sendfileData.get(new Long(desc[n*2+1])); - // Problem events - if (((desc[n*2] & Poll.APR_POLLHUP) == Poll.APR_POLLHUP) - || ((desc[n*2] & Poll.APR_POLLERR) == Poll.APR_POLLERR)) { - // Close socket and clear pool - remove(state); - // Destroy file descriptor pool, which should close the file - // Close the socket, as the reponse would be incomplete - Socket.destroy(state.socket); - continue; - } - // Write some data using sendfile - long nw = Socket.sendfilen(state.socket, state.fd, - state.pos, - state.end - state.pos, 0); - if (nw < 0) { - // Close socket and clear pool - remove(state); - // Close the socket, as the reponse would be incomplete - // This will close the file too. - Socket.destroy(state.socket); - continue; - } - - state.pos = state.pos + nw; - if (state.pos >= state.end) { - remove(state); - if (state.keepAlive) { - // Destroy file descriptor pool, which should close the file - Pool.destroy(state.fdpool); - Socket.timeoutSet(state.socket, ep.getSoTimeout() * 1000); - // If all done hand this socket off to a worker for - // processing of further requests - ep.getWorkerThread().assign(state.socket); - } else { - // Close the socket since this is - // the end of not keep-alive request. - Socket.destroy(state.socket); - } - } - } - } else if (rv < 0) { - /* Any non timeup error is critical */ - if (-rv == Status.TIMEUP) - rv = 0; - else { - log.error(sm.getString("endpoint.poll.fail", Error.strerror(-rv))); - // Handle poll critical failure - synchronized (this) { - destroy(); - init(); - } - } - } - /* TODO: See if we need to call the maintain for sendfile poller */ - } catch (Throwable t) { - log.error(sm.getString("endpoint.poll.error"), t); - } - } - - // Notify the threadStop() method that we have shut ourselves down - ep.threadSyncNotify(); - } - - } - - - // -------------------------------------- ConnectionHandler Inner Interface /** Added: tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprFileChannel.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprFileChannel.java?rev=365856&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprFileChannel.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprFileChannel.java Tue Jan 3 23:45:04 2006 @@ -0,0 +1,120 @@ +/* + */ +package org.apache.tomcat.util.net.apr; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +/** Abstraction for APR sendfile ( and maybe other file operations - later ). + * + * Only transferTo is implemented using APR. + * Rest of methods could be implemented by delegating to a java file channel. + * + * @author Costin Manolache + */ +public class AprFileChannel extends FileChannel { + // fd - for APR, it's a pointer to the apr struct + long fd; + + public AprFileChannel( long fd ) { + this.fd=fd; + } + + // -------------- FileChannel implementation --------------- + + public long transferTo(long position, long count, WritableByteChannel target) + throws IOException { + return 0; + } + + + + public int read(ByteBuffer dst) throws IOException { + return 0; + } + + + public long read(ByteBuffer[] dsts, int offset, int length) + throws IOException { + return 0; + } + + + public int write(ByteBuffer src) throws IOException { + return 0; + } + + + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException { + return 0; + } + + + public long position() throws IOException { + return 0; + } + + + public FileChannel position(long newPosition) throws IOException { + return null; + } + + + public long size() throws IOException { + return 0; + } + + + public FileChannel truncate(long size) throws IOException { + return null; + } + + + public void force(boolean metaData) throws IOException { + } + + + public long transferFrom(ReadableByteChannel src, long position, long count) + throws IOException { + return 0; + } + + + public int read(ByteBuffer dst, long position) throws IOException { + return 0; + } + + + public int write(ByteBuffer src, long position) throws IOException { + return 0; + } + + + public MappedByteBuffer map(MapMode mode, long position, long size) + throws IOException { + return null; + } + + + public FileLock lock(long position, long size, boolean shared) + throws IOException { + return null; + } + + + public FileLock tryLock(long position, long size, boolean shared) + throws IOException { + return null; + } + + + protected void implCloseChannel() throws IOException { + } + +} Added: tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprSocket.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprSocket.java?rev=365856&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprSocket.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/apr/AprSocket.java Tue Jan 3 23:45:04 2006 @@ -0,0 +1,53 @@ +/* + */ +package org.apache.tomcat.util.net.apr; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.SocketException; + + +/** Wrapper around apr socket handle. Only a subset of the Socket methods + * will be supported. + * + * This allows the apr connector to pass around Socket objects, and should + * support all call made by endpoint and tomcat, so Apr can be used in the same + * way. + * + * @author Costin Manolache + */ +public class AprSocket extends Socket { + public long aprHandle; + + public InputStream getInputStream() throws IOException { + return super.getInputStream(); + } + + + public OutputStream getOutputStream() throws IOException { + return super.getOutputStream(); + } + + + public void setKeepAlive(boolean on) throws SocketException { + super.setKeepAlive(on); + } + + + public void setSoLinger(boolean on, int linger) throws SocketException { + super.setSoLinger(on, linger); + } + + + public synchronized void setSoTimeout(int timeout) throws SocketException { + super.setSoTimeout(timeout); + } + + + public void setTcpNoDelay(boolean on) throws SocketException { + super.setTcpNoDelay(on); + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]