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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to