tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Remy Maucherat <r...@apache.org>
Subject Re: Proposed simplification of CometEvent
Date Sun, 17 Jun 2007 09:34:52 GMT
Filip Hanik - Dev Lists wrote:
> Ok, one use case scenario would be AJAX requests with asynchronous 
> responses on the server, I can see this be extremely common,
> I've tried to add in comments to make the example clear, and I don't see 
> this example as stupid, as there are a lot more AJAX client frameworks 
> than Comet client frameworks.
> 
> So there are two things we are show casing
> 1. The ability to write asynchronously
> 2. The ability to pipeline HTTP requests (assumption: only dealing with 
> GET requests, no HTTP request body)
> 3. Difference between Comet non blocking and Comet blocking read and 
> writes (note, not related to sockets, API only)
> 
> What I'd like to point out is that this example, becomes easier with 
> blocking read/writes, so I've added that at the bottom for comparison
> 
> Let me know if I've made any mistakes here, so that we can work with a 
> correct example.
> 
> Non blocking read and writes
> 
> public class ExampleDelayedAjaxResponse implements CometProcessor {
>  ...
>  public class DelayedResponder extends Thread {
>    public void run() {
>      ...
>      Client[] clients = getClients();
>      for (int i=0; i<clients.length; i++ ) {
>        CometEvent event = client.getEvent();
>        byte[] data = getDelayedResponse(event);
>        if (data!=null) {
>          if (event.isWriteable()) {
>            event.getHttpServletResponse().getOutputStream().write(data);
>            if (event.isWriteable()) { //did we write it all?
>               event.close(); //close the event, in anticipation of the 
> next request
>               event.register(OP_CALLBACK); //triggers an END event
>            } else { //we didn't write it all, trigger a WRITE event when 
> we are done with the write               event.register(OP_WRITE);
>            }
>          } else {
>            //we are not able to write, let us know when we can
>            event.register(OP_WRITE);

How can you not be able to write, since you didn't write anything at all 
yet for this request.

>          }
>          //remove the client from the  async thread
>          //since we have received the data for this client.
>          clients.remove(event);
>        }
>      }
>      ...
>    }
>  }
>  ...
>  public void event(CometEvent event) throws IOException, ServletException {
>    ...
>    if ( event.getEventType() == CometEvent.EventType.BEGIN ) {
>      //configure non blocking
>      event.configureBlocking(false);
>      //deregister for READ since we want to enable pipe lining on the 
> connection      //for the next HTTP request
>      event.unregister(OP_READ);
>      //add the client to the list
>      clients.add(event);
>    } if ( event.getEventType() == CometEvent.EventType.READ ) {
>      //read client Id and stock list from client
>      //and add the event to our list
>      assert("this should never happen");
>    } if ( event.getEventType() == CometEvent.EventType.WRITE ) {
>      //unregister from the write event
>      event.unregister(OP_WRITE);
>      //we can now write
>      byte[] data = getDelayedResponse(event);           if ( data != 
> null ) {
>        event.getHttpServletResponse().getOutputStream().write(data);
>      }
>      if( data==null || event.isWriteable() ) {
>        event.close();
>      }
>          } if ( event.getEventType() == CometEvent.EventType.END ) {
>      clients.remove(event);         } else if (...) {
>      ...
>    }
>    ...
>  }
> }
> 
> Blocking read and writes
> public class ExampleDelayedAjaxResponse implements CometProcessor {
>  ...
>  public class DelayedResponder extends Thread {
>    public void run() {
>      ...
>      Client[] clients = getClients();
>      for (int i=0; i<clients.length; i++ ) {
>        CometEvent event = client.getEvent();
>        byte[] data = getDelayedResponse(event);
>        if (data!=null) {
>          //register for a write, better do that on a thread pool thread
>          //since write is blocking
>          event.register(OP_WRITE);
>          //remove the client from the  async thread
>          clients.remove(event);
>        }
>      }
>      ...
>    }
>  }
>  ...
>  public void event(CometEvent event) throws IOException, ServletException {
>    ...
>    if ( event.getEventType() == CometEvent.EventType.BEGIN ) {
>      //configure non blocking
>      event.configureBlocking(false);
>      //deregister for READ since we want to enable pipe lining on the 
> connection      //for the next HTTP request

No. The situation where the end of the entity body is reached is 
detected very easily, and handled using a sleep (the 6.0 code is very 
close from that already).

>      event.unregister(OP_READ);
>      //add the client to the list
>      clients.add(event);
>    } if ( event.getEventType() == CometEvent.EventType.READ ) {
>      //read client Id and stock list from client
>      //and add the event to our list
>      assert("this should never happen");
>    } if ( event.getEventType() == CometEvent.EventType.WRITE ) {
>      //unregister from the write event
>      event.unregister(OP_WRITE);
>      //we can now write
>      byte[] data = getDelayedResponse(event);           //note we don't 
> have to check for null data here
>      event.getHttpServletResponse().getOutputStream().write(data);
>      event.close();
>    } if ( event.getEventType() == CometEvent.EventType.END ) {
>      clients.remove(event);
>    } else if (...) {
>      ...
>    }
>    ...
>  }
> }
>  
> Remy, would you mind showing this example with sandbox API, I think with 
> a real world example, I can understand your API better, and maybe you 
> mine :)

Real world for the simple delayed response scenario means using a thread 
to wait and generate an event. You then proceed to write the data. It's 
a bit like your second example, but it should be doing far less.

1) begin event: add the connection to the background thread, and sleep
2) background thread: after a while, invokes callback on the connection
3) callback event: write the data, there are two options:
    a) blocking style: write everything, without wondering if it blocks
    b) non blocking style: write while using isWriteable, and finish 
writing in write events if needed

Rémy


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message