Filip Hanik - Dev Lists wrote:
here we go, some examples

http://people.apache.org/~fhanik/tomcat/aio.html#Example%20code%20snippets

and the entire document has been updated to reflect most changes
http://people.apache.org/~fhanik/tomcat/aio.html

Here is an alternative version of the examples using the sandbox API to give people an idea, along with some comments. No renaming of sleep/callback, or others at this time. Hopefully, I did not make too many mistakes.

First example, which can enter a busy loop if all events start returning false for isWriteable (which is not very likely, of course):

public class ExampleCometStockStreamer implements CometProcessor {
  ...
  public class StockUpdater extends Thread {
    public void run() {
      ...
      StockUpdates[] updates = fetchUpdates();
      Client[] clients = getClients(updates);
      for (int i=0; i<clients.length; i++ ) {
        CometEvent event = client.getEvent();
        StockUpdates[] clientList = getClientUpdates(client,updates);
        client.setAndMergeNextUpdates(clientList);
        if (event.isWriteable()) {
          byte[] data = getUpdateChunk(client.getNextUpdates());
          event.getHttpServletResponse().getOutputStream().write(data);
        }
      }
      ...
    }
  }
  ...
public void event(CometEvent event) throws IOException, ServletException {
    ...
    if ( event.getEventType() == CometEvent.EventType.BEGIN ) {
    } if ( event.getEventType() == CometEvent.EventType.READ ) {
      //read client Id and stock list from client
      //and add the event to our list
      String clientId = readClientInfo(event,stocks);
      clients.add(clientId, event, stocks);
    } if ( event.getEventType() == CometEvent.EventType.WRITE ) {
      //we can now write
      byte[] data = getUpdateChunk(client.getNextUpdates());
      event.getHttpServletResponse().getOutputStream().write(data);
    } else if (...) {
      ...
    }
    ...
  }

}

What this example should be doing is remove the client from the list when isWriteable returns false, and add it back when it gets a write event.

I can translate the second example, but it could lead to an abusive poller use and number of events (all writes are also done synchronously with blocking IO, which never makes sense to me).

public class ExampleCometStockStreamer implements CometProcessor {
  ...
  public class StockUpdater extends Thread {
    public void run() {
      ...
      StockUpdates[] updates = fetchUpdates();
      Client[] clients = getClients(updates);
      for (int i=0; i<clients.length; i++ ) {
        StockUpdates[] clientList = getClientUpdates(client,updates);
        client.setAndMergeNextUpdates(clientList);
        client.getEvent().callback();
      }
      ...
    }
  }
  ...
public void event(CometEvent event) throws IOException, ServletException {
    ...
    if ( event.getEventType() == CometEvent.EventType.BEGIN ) {
      //configure blocking
      event.configureBlocking(true);
    } if ( event.getEventType() == CometEvent.EventType.READ ) {
      //read client Id and stock list from client
      //and add the event to our list
      String clientId = readClientInfo(event,stocks);
      clients.add(clientId, event, stocks);
    } if ( event.getEventType() == CometEvent.EventType.CALLBACK ) {
      Client client = clients.get(event);
      //we can now write
      byte[] data = getUpdateChunk(client.getNextUpdates());
      event.getHttpServletResponse().getOutputStream().write(data);
    } else if (...) {
      ...
    }
    ...
  }

}

I think the third example is wrong: there's no reason for isWriteable or isReadable to change its result unless they trigger a large amount of logic and some IO operations. I thought you said it was wrong ;) Also, it will be very vulnerable to busy loops. I can translate it by wrapping the content of for (int j=0; j<clients.size(); j++) { into a try/catch, and removing the calls to isWriteable (which only introduce useless events, and may cause additional busy loops).

Straight translation (since isWriteable will trigger a write event which will flush, it will work, but busy loops are pretty much certain; it also assumes things about the data to read):

public class ExampleAllReadThenWriteComet implements CometProcessor {
  ...
  public class AllWriterThread extends Thread {
    byte[] dataChunks = ...;
    public void run() {
      ...
      for (int i=0; i<dataChunks.length; i++ ) {
        for (int j=0; j<clients.size(); j++) {
          boolean done = false;
          while (!done) {
            //first read the first request
            //but only if our previous write was completed
if ( clients[j].getEvent().isWriteable() && clients[j].getEvent().isReadable() ) { done = readClientData(clients[j]); //returns true if all data has been received for a request
            }
          }
          done = false;
          while (!done) {
            //write the response
            if ( clients[j].getEvent().isWriteable() {

clients[j].getEvent().getHttpServletResponse().write(dataChunks[i]);
               done = true;
            }
          }
        }
      }
      ...
    }
  }
  ...
public void event(CometEvent event) throws IOException, ServletException {
    ...
    if ( event.getEventType() == CometEvent.EventType.BEGIN ) {
      //add the event to our client list
      clients.add(event);
      //start our writer if all clients have arrived
      if (clients.size()==5) {
        AllWriterThread thread = new AllWriterThread();
        thread.start();
      }
    } if ( event.getEventType() == CometEvent.EventType.READ ) {
    } if ( event.getEventType() == CometEvent.EventType.WRITE ) {
    } else if (...) {
      ...
    }
    ...
  }

}

The last example is quite funny, and I can't translate it (doh), since there's no opposite API to sleep (once you sleep, you have to callback). Waiting until you do operations on a number of connections seems weird, since all would perform as bad as the slowest one (or die if one does not send the data it was supposed to send). I would like to hear about a valid use case (by opposition to crazy coder design) which relies on freely enabling and disabling events.

All of these examples are not very good, I think :( In most of these, you should not be using Comet I think: CPU usage will skyrocket, killing off the benefits over regular Servlets with blocking IO.

Rémy

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to