https://issues.apache.org/bugzilla/show_bug.cgi?id=50495

           Summary: Comet connector needs ability to access the client
                    send queue.
           Product: Tomcat 7
           Version: 7.0.5
          Platform: PC
        OS/Version: All
            Status: NEW
          Severity: blocker
          Priority: P2
         Component: Connectors
        AssignedTo: dev@tomcat.apache.org
        ReportedBy: gober...@msn.com


I use NIO HTTP Tomcat connector org.apache.coyote.Http11NioProtocol to
implement Comet streaming to browsers and mobile devices. 
The application opens 'primary' persistent Comet connection to receive data
from the server. Server sends data to the client periodically.

It will be possible that one of the clients is "slow reader" for various
reasons. If I call PrintWriter.print("message") to send data to such client,
the message will be queued internally by the Tomcat "Comet Processor". If
message flow is heavy, the client message queues may become large and Tomcat
can run out of memory. I was able to duplicate this quite easily by sending
messages in a loop.

It will be critical to address these issues for any "production quality"
application.

I would like to request 2 enhancements to address this:
1) I would like to somehow "compress" the pending client's queue. Messages I
send are financial market data messages. So if I send message for stock IBM and
the message is queued, then when a new message for IBM is generated, I should
be able to detect that there is a message in the queue pending to be sent and
just replace content of the one already pending instead of queuing a new one.

2) If queue for a client reaches a high water mark, I should be able to detect
it, disconnect the client and delete the queue.

This is how data is sent now with Tomcat Comet:
PrintWriter out = response.getWriter();
out.print("my message");



This is how I would prefer it to work. This is very rough idea.
// Comet PrintWriter will be exposed:
CometPrintWriter out = (CometPrintWriter)response.getWriter();

// detect queue size and disconnect if necessary.
int queueSize = out.getQueue().size()

// get cached message for the stock symbol
ICometMessage existingMessageForTheSymbol = ...
if (existingMessageForTheSymbol == null) {
    ICometMessage newMessage = new MyMessage(...)
    out.addMessage(newMessage);
    // cache the newMessage in a Map.
}
else {
    if (!existingMessageForTheSymbol.replaceMessage(...)) {
        // message is already sent. need to create a new one:
        ICometMessage newMessage = new MyMessage(...)
        out.addMessage(newMessage);
        // cache the newMessage in a Map.
    }
}

// this interface would be a part of Tomcat Comet
interface ICometMessage {
   // called by Tomcat comet before message is sent.
   void beforeMessageSent();

   // called by Tomcat comet after message is sent.
   void afterMessageSent();
}

class MyMessage implements ICometMessage {
   ReentrantLock lock = ...;
   boolean messageSent;

   public void beforeMessageSent() {
      lock.lock();
      messageSent = true;
   }

   public void afterMessageSent() {
      lock.unlock();
   }

   public boolean replaceMessage(...) {
      lock.lock();
      if (messageSent) {
         lock.unlock();
         return false;
      }

      // replace message data.

      lock.unlock();

      return true;
   }
}

-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

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

Reply via email to