You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2006/11/13 15:31:09 UTC

svn commit: r474333 - in /jakarta/httpcomponents/httpcore/trunk/module-nio/src: examples/org/apache/http/nio/examples/ main/java/org/apache/http/nio/impl/ main/java/org/apache/http/nio/protocol/ main/java/org/apache/http/nio/util/

Author: olegk
Date: Mon Nov 13 06:31:08 2006
New Revision: 474333

URL: http://svn.apache.org/viewvc?view=rev&rev=474333
Log:
* Minor API tweaks
* A number of bug fixes

Modified:
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java
    jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/examples/org/apache/http/nio/examples/AsyncHttpServer.java Mon Nov 13 06:31:08 2006
@@ -10,6 +10,8 @@
 import java.net.URLDecoder;
 
 import org.apache.http.ConnectionClosedException;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
 import org.apache.http.HttpException;
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
@@ -30,6 +32,8 @@
 import org.apache.http.nio.protocol.AsyncHttpService;
 import org.apache.http.nio.reactor.IOEventDispatch;
 import org.apache.http.nio.reactor.IOReactor;
+import org.apache.http.nio.util.ContentInputBuffer;
+import org.apache.http.nio.util.ContentOutputBuffer;
 import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
@@ -41,6 +45,7 @@
 import org.apache.http.protocol.ResponseContent;
 import org.apache.http.protocol.ResponseDate;
 import org.apache.http.protocol.ResponseServer;
+import org.apache.http.util.EntityUtils;
 
 public class AsyncHttpServer {
 
@@ -52,7 +57,7 @@
         HttpParams params = new DefaultHttpParams(null);
         params
             .setIntParameter(HttpConnectionParams.SO_TIMEOUT, 5000)
-            .setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8 * 1024)
+            .setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 1024)
             .setBooleanParameter(HttpConnectionParams.STALE_CONNECTION_CHECK, false)
             .setBooleanParameter(HttpConnectionParams.TCP_NODELAY, true)
             .setParameter(HttpProtocolParams.ORIGIN_SERVER, "Jakarta-HttpComponents-NIO/1.1");
@@ -91,12 +96,18 @@
                 final HttpResponse response,
                 final HttpContext context) throws HttpException, IOException {
 
-            String method = request.getRequestLine().getMethod();
-            if (!method.equalsIgnoreCase("GET") && !method.equalsIgnoreCase("HEAD")) {
+            String method = request.getRequestLine().getMethod().toUpperCase();
+            if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
                 throw new MethodNotSupportedException(method + " method not supported"); 
             }
-            String target = request.getRequestLine().getUri();
+
+            if (request instanceof HttpEntityEnclosingRequest) {
+                HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
+                byte[] entityContent = EntityUtils.toByteArray(entity);
+                System.out.println("Incoming entity content (bytes): " + entityContent.length);
+            }
             
+            String target = request.getRequestLine().getUri();
             final File file = new File(this.docRoot, URLDecoder.decode(target, "UTF-8"));
             if (!file.exists()) {
 
@@ -151,6 +162,7 @@
     public static class MyNHttpServiceHandler implements NHttpServiceHandler {
         
         private static final String HTTP_ASYNC_SERVICE = "http.async-service";
+        private static final String HTTP_WORKER_THREAD = "http.worker-thread";
         
         final private HttpRequestHandlerRegistry reqistry;
         final private HttpParams params;
@@ -178,9 +190,14 @@
             httpproc.addInterceptor(new ResponseContent());
             httpproc.addInterceptor(new ResponseConnControl());
 
+            // Allocate large content input / output buffers
+            ContentInputBuffer inbuffer = new ContentInputBuffer(20480, conn); 
+            ContentOutputBuffer outbuffer = new ContentOutputBuffer(20480, conn); 
+            
             // Set up the HTTP service
             AsyncHttpService httpService = new AsyncHttpService(
-                    conn,
+                    inbuffer,
+                    outbuffer,
                     httpproc,
                     new DefaultConnectionReuseStrategy(), 
                     new DefaultHttpResponseFactory());
@@ -223,13 +240,35 @@
         }
 
         public void requestReceived(final NHttpServerConnection conn) {
+            HttpRequest request = conn.getHttpRequest();
             AsyncHttpService httpService = (AsyncHttpService) conn.getContext()
                 .getAttribute(HTTP_ASYNC_SERVICE);
+            WorkerThread worker = (WorkerThread) conn.getContext()
+                .getAttribute(HTTP_WORKER_THREAD);
             
             // BIG FAT UGLY WARNING!
-            // Do NOT start a new thread per request in real world applications!
-            // Do make sure to use a thread pool  
-            WorkerThread worker = new WorkerThread(httpService, conn); 
+            // =====================
+            // (1) This sample application employs an over-simplistic 
+            //     thread synchronization. In the life applications
+            //     consider implementing a proper connection locking
+            //     mechanism to ensure that only one worker thread
+            //     can have access to an HTTP connection at a time
+            //
+            // (2) Do NOT start a new thread per request in real life 
+            //     applications! Do make sure to use a thread pool.
+            //
+            
+            if (worker != null) {
+                try {
+                    worker.join();
+                } catch (InterruptedException ex) {
+                    return;
+                }
+            }
+            
+            worker = new WorkerThread(httpService, request, conn); 
+            conn.getContext().setAttribute(HTTP_WORKER_THREAD, worker);
+            
             worker.setDaemon(true);
             worker.start();
         }
@@ -260,31 +299,31 @@
     static class WorkerThread extends Thread {
 
         private final AsyncHttpService httpService;
+        private final HttpRequest request;
         private final NHttpServerConnection conn;
         
         public WorkerThread(
                 final AsyncHttpService httpService,
+                final HttpRequest request,
                 final NHttpServerConnection conn) {
             super();
             this.httpService = httpService;
+            this.request = request;
             this.conn = conn;
         }
         
         public void run() {
             System.out.println("New request thread");
             try {
-                this.httpService.handleRequest(this.conn);
+                this.httpService.handleRequest(this.request, this.conn);
             } catch (ConnectionClosedException ex) {
                 System.err.println("Client closed connection");
             } catch (IOException ex) {
                 System.err.println("I/O error: " + ex.getMessage());
             } catch (HttpException ex) {
                 System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage());
-            } finally {
-                try {
-                    this.conn.shutdown();
-                } catch (IOException ignore) {}
             }
+            System.out.println("Request thread terminated");
         }
 
     }

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/impl/NHttpConnectionBase.java Mon Nov 13 06:31:08 2006
@@ -66,17 +66,17 @@
     protected final IOSession session;
     protected final HttpContext context;
     
-    protected ContentLengthStrategy incomingContentStrategy;
-    protected ContentLengthStrategy outgoingContentStrategy;
+    protected final ContentLengthStrategy incomingContentStrategy;
+    protected final ContentLengthStrategy outgoingContentStrategy;
     
     protected final SessionInputBuffer inbuf;
     protected final SessionOutputBuffer outbuf;
     protected final CharArrayBuffer lineBuffer;
     
-    protected ContentDecoder contentDecoder;
-    protected ContentEncoder contentEncoder;
-    protected HttpRequest request;
-    protected HttpResponse response;
+    protected volatile ContentDecoder contentDecoder;
+    protected volatile ContentEncoder contentEncoder;
+    protected volatile HttpRequest request;
+    protected volatile HttpResponse response;
     
     protected volatile boolean closed;
     
@@ -123,19 +123,27 @@
     }
 
     public void requestInput() {
-        this.session.setEvent(EventMask.READ);
+        if (this.contentEncoder != null) {
+            this.session.setEvent(EventMask.READ);
+        }
     }
 
     public void requestOutput() {
-        this.session.setEvent(EventMask.WRITE);
+        if (this.contentDecoder != null) {
+            this.session.setEvent(EventMask.WRITE);
+        }
     }
 
     public void suspendInput() {
-        this.session.clearEvent(EventMask.READ);
+        if (this.contentEncoder != null) {
+            this.session.clearEvent(EventMask.READ);
+        }
     }
 
     public void suspendOutput() {
-        this.session.clearEvent(EventMask.WRITE);
+        if (this.contentDecoder != null) {
+            this.session.clearEvent(EventMask.WRITE);
+        }
     }
 
     protected HttpEntity prepareDecoder(final HttpMessage message) throws HttpException {

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/protocol/AsyncHttpService.java Mon Nov 13 06:31:08 2006
@@ -20,7 +20,6 @@
 import org.apache.http.entity.StringEntity;
 import org.apache.http.nio.ContentDecoder;
 import org.apache.http.nio.ContentEncoder;
-import org.apache.http.nio.ContentIOControl;
 import org.apache.http.nio.NHttpServerConnection;
 import org.apache.http.nio.util.ContentInputBuffer;
 import org.apache.http.nio.util.ContentOutputBuffer;
@@ -43,13 +42,20 @@
     private ConnectionReuseStrategy connStrategy = null;
     
     public AsyncHttpService(
-            final ContentIOControl ioControl,
+            final ContentInputBuffer inbuffer,
+            final ContentOutputBuffer outbuffer,
             final HttpProcessor proc,
             final ConnectionReuseStrategy connStrategy,
             final HttpResponseFactory responseFactory) {
         super();
-        this.inbuffer = new ContentInputBuffer(20480, ioControl); 
-        this.outbuffer = new ContentOutputBuffer(20480, ioControl); 
+        if (inbuffer == null) {
+            throw new IllegalArgumentException("Content input buffer may not be null");
+        }
+        if (outbuffer == null) {
+            throw new IllegalArgumentException("Content output buffer may not be null");
+        }
+        this.inbuffer = inbuffer; 
+        this.outbuffer = outbuffer; 
         setHttpProcessor(proc);
         setConnReuseStrategy(connStrategy);
         setResponseFactory(responseFactory);
@@ -98,14 +104,12 @@
         this.outbuffer.shutdown(ex);
     }
     
-    public void handleRequest(final NHttpServerConnection conn) 
+    public void handleRequest(final HttpRequest request, final NHttpServerConnection conn) 
                 throws HttpException, IOException {
         // Reset buffers
         this.inbuffer.reset();
         this.outbuffer.reset();
-        // Get the incoming request
         HttpContext parentContext = conn.getContext();
-        HttpRequest request = conn.getHttpRequest();
         HttpVersion ver = request.getRequestLine().getHttpVersion();
         if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
             // Downgrade protocol version if greater than HTTP/1.1 
@@ -183,19 +187,10 @@
         // Reset buffers
         this.inbuffer.reset();
         this.outbuffer.reset();
-        // Geenrate response
-        HttpRequest request = conn.getHttpRequest();
+        // Generate response
         HttpContext context = conn.getContext();
-        HttpVersion ver = HttpVersion.HTTP_1_1;
-        if (request != null) {
-            ver = request.getRequestLine().getHttpVersion();
-        }
-        if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
-            // Downgrade protocol version if greater than HTTP/1.1 
-            ver = HttpVersion.HTTP_1_1;
-        }
-        
-        HttpResponse response = this.responseFactory.newHttpResponse(ver, HttpStatus.SC_OK);
+        HttpResponse response = this.responseFactory.newHttpResponse(
+                HttpVersion.HTTP_1_0, HttpStatus.SC_OK);
         response.getParams().setDefaults(this.params);
         
         if (ex instanceof MethodNotSupportedException) {

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentInputBuffer.java Mon Nov 13 06:31:08 2006
@@ -70,7 +70,7 @@
             int total = 0;
             int bytesRead = 0;
             while ((bytesRead = decoder.read(this.buffer)) > 0) {
-                total =+ bytesRead;
+                total += bytesRead;
             }
             if (bytesRead == -1 || decoder.isCompleted()) {
                 this.endOfStream = true;

Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java?view=diff&rev=474333&r1=474332&r2=474333
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/util/ContentOutputBuffer.java Mon Nov 13 06:31:08 2006
@@ -79,11 +79,11 @@
     }
     
     protected void flushBuffer() throws IOException {
-        this.ioctrl.requestOutput();
         synchronized (this.mutex) {
             setOutputMode();
             try {
                 while (hasData() && !this.shutdown) {
+                    this.ioctrl.requestOutput();
                     this.mutex.wait();
                 }