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 2006/01/04 08:45:06 UTC
svn commit: r365856 - in
/tomcat/sandbox/java/org/apache/tomcat/util/net/apr: ./ AprByteChannel.java
AprEndpoint.java AprFileChannel.java AprSocket.java
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: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org