* <ul>\r
* <li>Socket acceptor thread</li>\r
* <li>Socket poller thread</li>\r
- * <li>Sendfile thread</li>\r
* <li>Worker threads pool</li>\r
* </ul>\r
*\r
public int getPollerSize() { return pollerSize; }\r
\r
\r
- /**\r
- * Size of the sendfile (= concurrent files which can be served).\r
- */\r
- protected int sendfileSize = 1 * 1024;\r
- public void setSendfileSize(int sendfileSize) { this.sendfileSize = sendfileSize; }\r
- public int getSendfileSize() { return sendfileSize; }\r
-\r
\r
/**\r
* Server socket port.\r
public String getName() { return name; }\r
\r
\r
- /**\r
- * Use endfile for sending static files.\r
- */\r
- protected boolean useSendfile = Library.APR_HAS_SENDFILE;\r
- public void setUseSendfile(boolean useSendfile) { this.useSendfile = useSendfile; }\r
- public boolean getUseSendfile() { return useSendfile; }\r
-\r
\r
/**\r
* Allow comet request handling.\r
public int getAcceptorThreadCount() { return acceptorThreadCount; }\r
\r
\r
- /**\r
- * Sendfile thread count.\r
- */\r
- protected int sendfileThreadCount = 0;\r
- public void setSendfileThreadCount(int sendfileThreadCount) { this.sendfileThreadCount = sendfileThreadCount; }\r
- public int getSendfileThreadCount() { return sendfileThreadCount; }\r
-\r
\r
/**\r
* Poller thread count.\r
\r
\r
/**\r
- * The static file sender.\r
- */\r
- protected Sendfile[] sendfiles = null;\r
- protected int sendfileRoundRobin = 0;\r
- public Sendfile getSendfile() {\r
- sendfileRoundRobin = (sendfileRoundRobin + 1) % sendfiles.length;\r
- return sendfiles[sendfileRoundRobin];\r
- }\r
-\r
-\r
- /**\r
* Dummy maxSpareThreads property.\r
*/\r
public int getMaxSpareThreads() { return 0; }\r
}\r
\r
\r
- /**\r
- * Number of sendfile sockets.\r
- */\r
- public int getSendfileCount() {\r
- if (sendfiles == null) {\r
- return 0;\r
- } else {\r
- int sendfileCount = 0;\r
- for (int i = 0; i < sendfiles.length; i++) {\r
- sendfileCount += sendfiles[i].getSendfileCount();\r
- }\r
- return sendfileCount;\r
- }\r
- }\r
-\r
\r
/**\r
* Return the amount of threads that are managed by the pool.\r
InetSocketAddress addr = (address!=null?new InetSocketAddress(address,port):new InetSocketAddress(port));\r
serverSock.socket().bind(addr,100); //todo, set backlog value\r
serverSock.configureBlocking(true); //mimic APR behavior\r
- // Sendfile usage on systems which don't support it cause major problems\r
- if (useSendfile) {\r
- log.warn(sm.getString("endpoint.sendfile.nosupport"));\r
- useSendfile = false;\r
- }\r
\r
// Initialize thread count defaults for acceptor, poller and sendfile\r
if (acceptorThreadCount == 0) {\r
// limit to one poller, no need for others\r
pollerThreadCount = 1;\r
}\r
- if (sendfileThreadCount != 0) {\r
- sendfileThreadCount = 0;\r
- }\r
\r
// Initialize SSL if needed\r
if (!"off".equalsIgnoreCase(SSLEngine)) {\r
// value = SSL.SSL_CVERIFY_OPTIONAL_NO_CA;\r
// }\r
// SSLContext.setVerify(sslContext, value, SSLVerifyDepth);\r
- // For now, sendfile is not supported with SSL\r
- useSendfile = false;\r
}\r
\r
initialized = true;\r
\r
\r
/**\r
- * Start the APR endpoint, creating acceptor, poller and sendfile threads.\r
+ * Start the APR endpoint, creating acceptor, poller threads.\r
*/\r
public void start()\r
throws Exception {\r
pollerThread.setDaemon(true);\r
pollerThread.start();\r
}\r
-\r
- // Start sendfile threads\r
- if (useSendfile) {\r
- sendfiles = new Sendfile[sendfileThreadCount];\r
- for (int i = 0; i < sendfileThreadCount; i++) {\r
- sendfiles[i] = new Sendfile();\r
- sendfiles[i].init();\r
- Thread sendfileThread = new Thread(sendfiles[i], getName() + "-Sendfile-" + i);\r
- sendfileThread.setPriority(threadPriority);\r
- sendfileThread.setDaemon(true);\r
- sendfileThread.start();\r
- }\r
- }\r
}\r
}\r
\r
pollers[i].destroy();\r
}\r
pollers = null;\r
- if (useSendfile) {\r
- for (int i = 0; i < sendfiles.length; i++) {\r
- sendfiles[i].destroy();\r
- }\r
- sendfiles = null;\r
- }\r
}\r
}\r
\r
}\r
\r
\r
- // ----------------------------------------------- SendfileData Inner Class\r
-\r
-\r
- /**\r
- * SendfileData class.\r
- */\r
- public static class SendfileData {\r
- // File\r
- public String fileName;\r
- public long fd;\r
- public long fdpool;\r
- // Range information\r
- public long start;\r
- public long end;\r
- // Socket and socket pool\r
- public SocketChannel socket;\r
- // Position\r
- public long pos;\r
- // KeepAlive flag\r
- public boolean keepAlive;\r
- }\r
-\r
-\r
- // --------------------------------------------------- Sendfile Inner Class\r
-\r
-\r
- /**\r
- * Sendfile class.\r
- */\r
- public class Sendfile implements Runnable {\r
-\r
- protected long sendfilePollset = 0;\r
- protected long pool = 0;\r
- protected long[] desc;\r
- protected HashMap<Long, SendfileData> sendfileData;\r
-\r
- protected int sendfileCount;\r
- public int getSendfileCount() { return sendfileCount; }\r
-\r
- protected ArrayList<SendfileData> addS;\r
-\r
- /**\r
- * Create the sendfile poller. With some versions of APR, the maximum poller size will\r
- * be 62 (reocmpiling APR is necessary to remove this limitation).\r
- */\r
- protected void init() {\r
-// pool = Pool.create(serverSockPool);\r
-// int size = sendfileSize / sendfileThreadCount;\r
-// sendfilePollset = allocatePoller(size, pool, soTimeout);\r
-// if (sendfilePollset == 0 && size > 1024) {\r
-// size = 1024;\r
-// sendfilePollset = allocatePoller(size, pool, soTimeout);\r
-// }\r
-// if (sendfilePollset == 0) {\r
-// size = 62;\r
-// sendfilePollset = allocatePoller(size, pool, soTimeout);\r
-// }\r
-// desc = new long[size * 2];\r
-// sendfileData = new HashMap<Long, SendfileData>(size);\r
-// addS = new ArrayList<SendfileData>();\r
- }\r
-\r
- /**\r
- * Destroy the poller.\r
- */\r
- protected void destroy() {\r
-// // Wait for polltime before doing anything, so that the poller threads\r
-// // exit, otherwise parallel descturction of sockets which are still\r
-// // in the poller can cause problems\r
-// try {\r
-// synchronized (this) {\r
-// this.wait(pollTime / 1000);\r
-// }\r
-// } catch (InterruptedException e) {\r
-// // Ignore\r
-// }\r
-// // Close any socket remaining in the add queue\r
-// for (int i = (addS.size() - 1); i >= 0; i--) {\r
-// SendfileData data = addS.get(i);\r
-// Socket.destroy(data.socket);\r
-// }\r
-// // Close all sockets still in the poller\r
-// int rv = Poll.pollset(sendfilePollset, desc);\r
-// if (rv > 0) {\r
-// for (int n = 0; n < rv; n++) {\r
-// Socket.destroy(desc[n*2+1]);\r
-// }\r
-// }\r
-// Pool.destroy(pool);\r
-// sendfileData.clear();\r
- }\r
-\r
- /**\r
- * Add the sendfile data to the sendfile poller. Note that in most cases,\r
- * the initial non blocking calls to sendfile will return right away, and\r
- * will be handled asynchronously inside the kernel. As a result,\r
- * the poller will never be used.\r
- *\r
- * @param data containing the reference to the data which should be snet\r
- * @return true if all the data has been sent right away, and false\r
- * otherwise\r
- */\r
- public boolean add(SendfileData data) {\r
-// // Initialize fd from data given\r
-// try {\r
-// data.fdpool = Socket.pool(data.socket);\r
-// data.fd = File.open\r
-// (data.fileName, File.APR_FOPEN_READ\r
-// | File.APR_FOPEN_SENDFILE_ENABLED | File.APR_FOPEN_BINARY,\r
-// 0, data.fdpool);\r
-// data.pos = data.start;\r
-// // Set the socket to nonblocking mode\r
-// Socket.timeoutSet(data.socket, 0);\r
-// while (true) {\r
-// long nw = Socket.sendfilen(data.socket, data.fd,\r
-// data.pos, data.end - data.pos, 0);\r
-// if (nw < 0) {\r
-// if (!(-nw == Status.EAGAIN)) {\r
-// Socket.destroy(data.socket);\r
-// data.socket = 0;\r
-// return false;\r
-// } else {\r
-// // Break the loop and add the socket to poller.\r
-// break;\r
-// }\r
-// } else {\r
-// data.pos = data.pos + nw;\r
-// if (data.pos >= data.end) {\r
-// // Entire file has been sent\r
-// Pool.destroy(data.fdpool);\r
-// // Set back socket to blocking mode\r
-// Socket.timeoutSet(data.socket, soTimeout * 1000);\r
-// return true;\r
-// }\r
-// }\r
-// }\r
-// } catch (Exception e) {\r
-// log.error(sm.getString("endpoint.sendfile.error"), e);\r
-// return false;\r
-// }\r
-// // Add socket to the list. Newly added sockets will wait\r
-// // at most for pollTime before being polled\r
-// synchronized (this) {\r
-// addS.add(data);\r
-// this.notify();\r
-// }\r
- return false;\r
- }\r
-\r
- /**\r
- * Remove socket from the poller.\r
- *\r
- * @param data the sendfile data which should be removed\r
- */\r
- protected void remove(SendfileData data) {\r
-// int rv = Poll.remove(sendfilePollset, data.socket);\r
-// if (rv == Status.APR_SUCCESS) {\r
-// sendfileCount--;\r
-// }\r
-// sendfileData.remove(data);\r
- }\r
-\r
- /**\r
- * The background thread that listens for incoming TCP/IP connections and\r
- * hands them off to an appropriate processor.\r
- */\r
- public void run() {\r
-\r
-// // Loop until we receive a shutdown command\r
-// while (running) {\r
-//\r
-// // Loop if endpoint is paused\r
-// while (paused) {\r
-// try {\r
-// Thread.sleep(1000);\r
-// } catch (InterruptedException e) {\r
-// // Ignore\r
-// }\r
-// }\r
-//\r
-// while (sendfileCount < 1 && addS.size() < 1) {\r
-// try {\r
-// synchronized (this) {\r
-// this.wait();\r
-// }\r
-// } catch (InterruptedException e) {\r
-// // Ignore\r
-// }\r
-// }\r
-//\r
-// try {\r
-// // Add socket to the poller\r
-// if (addS.size() > 0) {\r
-// synchronized (this) {\r
-// for (int i = (addS.size() - 1); i >= 0; i--) {\r
-// SendfileData data = addS.get(i);\r
-// int rv = Poll.add(sendfilePollset, data.socket, Poll.APR_POLLOUT);\r
-// if (rv == Status.APR_SUCCESS) {\r
-// sendfileData.put(new Long(data.socket), data);\r
-// sendfileCount++;\r
-// } else {\r
-// log.warn(sm.getString("endpoint.sendfile.addfail", "" + rv, Error.strerror(rv)));\r
-// // Can't do anything: close the socket right away\r
-// Socket.destroy(data.socket);\r
-// }\r
-// }\r
-// addS.clear();\r
-// }\r
-// }\r
-// // Pool for the specified interval\r
-// int rv = Poll.poll(sendfilePollset, pollTime, desc, false);\r
-// if (rv > 0) {\r
-// for (int n = 0; n < rv; n++) {\r
-// // Get the sendfile state\r
-// SendfileData state =\r
-// sendfileData.get(new Long(desc[n*2+1]));\r
-// // Problem events\r
-// if (((desc[n*2] & Poll.APR_POLLHUP) == Poll.APR_POLLHUP)\r
-// || ((desc[n*2] & Poll.APR_POLLERR) == Poll.APR_POLLERR)) {\r
-// // Close socket and clear pool\r
-// remove(state);\r
-// // Destroy file descriptor pool, which should close the file\r
-// // Close the socket, as the reponse would be incomplete\r
-// Socket.destroy(state.socket);\r
-// continue;\r
-// }\r
-// // Write some data using sendfile\r
-// long nw = Socket.sendfilen(state.socket, state.fd,\r
-// state.pos,\r
-// state.end - state.pos, 0);\r
-// if (nw < 0) {\r
-// // Close socket and clear pool\r
-// remove(state);\r
-// // Close the socket, as the reponse would be incomplete\r
-// // This will close the file too.\r
-// Socket.destroy(state.socket);\r
-// continue;\r
-// }\r
-//\r
-// state.pos = state.pos + nw;\r
-// if (state.pos >= state.end) {\r
-// remove(state);\r
-// if (state.keepAlive) {\r
-// // Destroy file descriptor pool, which should close the file\r
-// Pool.destroy(state.fdpool);\r
-// Socket.timeoutSet(state.socket, soTimeout * 1000);\r
-// // If all done hand this socket off to a worker for\r
-// // processing of further requests\r
-// if (!processSocket(state.socket)) {\r
-// Socket.destroy(state.socket);\r
-// }\r
-// } else {\r
-// // Close the socket since this is\r
-// // the end of not keep-alive request.\r
-// Socket.destroy(state.socket);\r
-// }\r
-// }\r
-// }\r
-// } else if (rv < 0) {\r
-// int errn = -rv;\r
-// /* Any non timeup or interrupted error is critical */\r
-// if ((errn != Status.TIMEUP) && (errn != Status.EINTR)) {\r
-// if (errn > Status.APR_OS_START_USERERR) {\r
-// errn -= Status.APR_OS_START_USERERR;\r
-// }\r
-// log.error(sm.getString("endpoint.poll.fail", "" + errn, Error.strerror(errn)));\r
-// // Handle poll critical failure\r
-// synchronized (this) {\r
-// destroy();\r
-// init();\r
-// }\r
-// continue;\r
-// }\r
-// }\r
-// /* TODO: See if we need to call the maintain for sendfile poller */\r
-// } catch (Throwable t) {\r
-// log.error(sm.getString("endpoint.poll.error"), t);\r
-// }\r
-// }\r
-//\r
-// synchronized (this) {\r
-// this.notifyAll();\r
-// }\r
-\r
- }\r
-\r
- }\r
-\r
\r
// ------------------------------------------------ Handler Inner Interface\r
\r