Author: fhanik Date: Tue May 29 14:53:52 2007 New Revision: 542666 URL: http://svn.apache.org/viewvc?view=rev&rev=542666 Log: implement non blocking reading of the request line
Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?view=diff&rev=542666&r1=542665&r2=542666 ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Tue May 29 14:53:52 2007 @@ -792,14 +792,6 @@ RequestInfo rp = request.getRequestProcessor(); rp.setStage(org.apache.coyote.Constants.STAGE_PARSE); - // Set the remote address - remoteAddr = null; - remoteHost = null; - localAddr = null; - localName = null; - remotePort = -1; - localPort = -1; - // Setting up the socket this.socket = socket; inputBuffer.setSocket(socket); @@ -829,17 +821,17 @@ socket.getIOChannel().socket().setSoTimeout((int)soTimeout); inputBuffer.readTimeout = soTimeout; } - if (!inputBuffer.parseRequestLine(keptAlive && (endpoint.getCurrentThreadsBusy() >= limit))) { - // This means that no data is available right now - // (long keepalive), so that the processor should be recycled - // and the method should return true + if (!inputBuffer.parseRequestLine(keptAlive)) { + //no data available yet, since we might have read part + //of the request line, we can't recycle the processor openSocket = true; - // Add the socket to the poller - socket.getPoller().add(socket); + recycle = false; break; } keptAlive = true; if ( !inputBuffer.parseHeaders() ) { + //we've read part of the request, don't recycle it + //instead associate it with the socket openSocket = true; recycle = false; break; @@ -992,6 +984,12 @@ this.socket = null; this.cometClose = false; this.comet = false; + remoteAddr = null; + remoteHost = null; + localAddr = null; + localName = null; + remotePort = -1; + localPort = -1; } Modified: tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java?view=diff&rev=542666&r1=542665&r2=542666 ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/InternalNioInputBuffer.java Tue May 29 14:53:52 2007 @@ -72,6 +72,9 @@ parsingHeader = true; parsingRequestLine = true; + parsingRequestLinePhase = 0; + parsingRequestLineEol = false; + parsingRequestLineStart = 0; headerParsePos = HeaderParsePosition.HEADER_START; headerData.recycle(); swallowInput = true; @@ -115,6 +118,9 @@ */ protected boolean parsingHeader; protected boolean parsingRequestLine; + protected int parsingRequestLinePhase = 0; + protected boolean parsingRequestLineEol = false; + protected int parsingRequestLineStart = 0; protected HeaderParsePosition headerParsePos; @@ -305,6 +311,9 @@ parsingHeader = true; headerParsePos = HeaderParsePosition.HEADER_START; parsingRequestLine = true; + parsingRequestLinePhase = 0; + parsingRequestLineEol = false; + parsingRequestLineStart = 0; headerData.recycle(); swallowInput = true; @@ -346,6 +355,9 @@ parsingHeader = true; headerParsePos = HeaderParsePosition.HEADER_START; parsingRequestLine = true; + parsingRequestLinePhase = 0; + parsingRequestLineEol = false; + parsingRequestLineStart = 0; headerData.recycle(); swallowInput = true; @@ -384,160 +396,148 @@ //check state if ( !parsingRequestLine ) return true; - - int start = 0; - // // Skipping blank lines // - - byte chr = 0; - do { - - // Read new bytes if needed + if ( parsingRequestLinePhase == 0 ) { + byte chr = 0; + do { + + // Read new bytes if needed + if (pos >= lastValid) { + if (useAvailableData) { + return false; + } + if (readTimeout == -1) { + if (!fill(false,true)) //request line parsing + throw new EOFException(sm.getString("iib.eof.error")); + } else { + // Do a simple read with a short timeout + if ( !readSocket(true, false) ) return false; + } + } + chr = buf[pos++]; + } while ((chr == Constants.CR) || (chr == Constants.LF)); + pos--; + parsingRequestLineStart = pos; + parsingRequestLinePhase = 1; + } + if ( parsingRequestLinePhase == 1 ) { + // Mark the current buffer position + if (pos >= lastValid) { if (useAvailableData) { return false; } if (readTimeout == -1) { - if (!fill(false,true)) //request line parsing - throw new EOFException(sm.getString("iib.eof.error")); + if (!fill(false,false)) //request line parsing + return false; } else { // Do a simple read with a short timeout if ( !readSocket(true, false) ) return false; } } - - chr = buf[pos++]; - - } while ((chr == Constants.CR) || (chr == Constants.LF)); - - pos--; - - // Mark the current buffer position - start = pos; - - if (pos >= lastValid) { - if (useAvailableData) { - return false; - } - if (readTimeout == -1) { - if (!fill(false,false)) //request line parsing - return false; - } else { - // Do a simple read with a short timeout - if ( !readSocket(true, false) ) return false; - } + parsingRequestLinePhase = 2; } - - // - // Reading the method name - // Method name is always US-ASCII - // - - boolean space = false; - - while (!space) { - - // Read new bytes if needed - if (pos >= lastValid) { - if (!fill(true,false)) //request line parsing - return false; - } - - if (buf[pos] == Constants.SP) { - space = true; - request.method().setBytes(buf, start, pos - start); + if ( parsingRequestLinePhase == 2 ) { + // + // Reading the method name + // Method name is always US-ASCII + // + boolean space = false; + while (!space) { + // Read new bytes if needed + if (pos >= lastValid) { + if (!fill(true, false)) //request line parsing + return false; + } + if (buf[pos] == Constants.SP) { + space = true; + request.method().setBytes(buf, parsingRequestLineStart, pos - parsingRequestLineStart); + } + pos++; } - - pos++; - + parsingRequestLineStart = pos; + parsingRequestLinePhase = 3; } - - // Mark the current buffer position - start = pos; - int end = 0; - int questionPos = -1; - - // - // Reading the URI - // - - space = false; - boolean eol = false; - - while (!space) { - - // Read new bytes if needed - if (pos >= lastValid) { - if (!fill(true,false)) //request line parsing - return false; + if ( parsingRequestLinePhase == 3 ) { + // Mark the current buffer position + + int end = 0; + int questionPos = -1; + // + // Reading the URI + // + boolean space = false; + while (!space) { + // Read new bytes if needed + if (pos >= lastValid) { + if (!fill(true,false)) //request line parsing + return false; + } + if (buf[pos] == Constants.SP) { + space = true; + end = pos; + } else if ((buf[pos] == Constants.CR) + || (buf[pos] == Constants.LF)) { + // HTTP/0.9 style request + parsingRequestLineEol = true; + space = true; + end = pos; + } else if ((buf[pos] == Constants.QUESTION) + && (questionPos == -1)) { + questionPos = pos; + } + pos++; } - - if (buf[pos] == Constants.SP) { - space = true; - end = pos; - } else if ((buf[pos] == Constants.CR) - || (buf[pos] == Constants.LF)) { - // HTTP/0.9 style request - eol = true; - space = true; - end = pos; - } else if ((buf[pos] == Constants.QUESTION) - && (questionPos == -1)) { - questionPos = pos; + request.unparsedURI().setBytes(buf, parsingRequestLineStart, end - parsingRequestLineStart); + if (questionPos >= 0) { + request.queryString().setBytes(buf, questionPos + 1, + end - questionPos - 1); + request.requestURI().setBytes(buf, parsingRequestLineStart, questionPos - parsingRequestLineStart); + } else { + request.requestURI().setBytes(buf, parsingRequestLineStart, end - parsingRequestLineStart); } - - pos++; - + parsingRequestLineStart = pos; + parsingRequestLinePhase = 4; } - - request.unparsedURI().setBytes(buf, start, end - start); - if (questionPos >= 0) { - request.queryString().setBytes(buf, questionPos + 1, - end - questionPos - 1); - request.requestURI().setBytes(buf, start, questionPos - start); - } else { - request.requestURI().setBytes(buf, start, end - start); - } - - // Mark the current buffer position - start = pos; - end = 0; - - // - // Reading the protocol - // Protocol is always US-ASCII - // - - while (!eol) { - - // Read new bytes if needed - if (pos >= lastValid) { - if (!fill(true,false)) //reques line parsing - return false; - } - - if (buf[pos] == Constants.CR) { - end = pos; - } else if (buf[pos] == Constants.LF) { - if (end == 0) + if ( parsingRequestLinePhase == 4 ) { + // Mark the current buffer position + + end = 0; + // + // Reading the protocol + // Protocol is always US-ASCII + // + while (!parsingRequestLineEol) { + // Read new bytes if needed + if (pos >= lastValid) { + if (!fill(true, false)) //reques line parsing + return false; + } + + if (buf[pos] == Constants.CR) { end = pos; - eol = true; + } else if (buf[pos] == Constants.LF) { + if (end == 0) + end = pos; + parsingRequestLineEol = true; + } + pos++; } - - pos++; - - } - - if ((end - start) > 0) { - request.protocol().setBytes(buf, start, end - start); - } else { - request.protocol().setString(""); + + if ( (end - parsingRequestLineStart) > 0) { + request.protocol().setBytes(buf, parsingRequestLineStart, end - parsingRequestLineStart); + } else { + request.protocol().setString(""); + } + parsingRequestLine = false; + parsingRequestLinePhase = 0; + parsingRequestLineEol = false; + parsingRequestLineStart = 0; + return true; } - parsingRequestLine = false; - return true; - + throw new IllegalStateException("Invalid request line parse phase:"+parsingRequestLinePhase); } private void expand(int newsize) { Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?view=diff&rev=542666&r1=542665&r2=542666 ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Tue May 29 14:53:52 2007 @@ -1461,6 +1461,7 @@ while (iterator != null && iterator.hasNext()) { SelectionKey sk = (SelectionKey) iterator.next(); KeyAttachment attachment = (KeyAttachment)sk.attachment(); + attachment.access(); iterator.remove(); processKey(sk, attachment); }//while --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]