users@grizzly.java.net

Re: OnEvent() never invoked, Comet source code analyzed

From: Jake Lockerbe <lockekal1965_at_aol.com>
Date: Tue, 13 Jul 2010 16:21:03 -0400 (EDT)

 

 I downloaded the sources for grizzly-comet 1.9.19-SNAPSHOT and analyzed the code.

If my analysis is correct, the Comet Context method onEvent() is never invoked because
the code never adds the CometHandler to the hashmap of handlers in the CometContext object.


I discovered the following:

1) CometContext contains a ConcurrentHashpMap<CometHandler,CometTask> handlers

2) The CometContext method addComentHandler(CometHandler handler) invokes the overloaded method
   addCometHandler(CometHandler handler, boolean alreadySuspended) with the boolean set to false.

   Note: This method does not put any instances of handler into the handlers property of CometContext

3) CometContext contains several overloaded notify methods.

   notify(final Object attachment) invokes
   notify(Object attachment,int eventType) with an eventType of CometEvent.NOTIFY

  
   This method (shown below) extracts the keys of the hashmap as a Set and then creates an iterator on this set.
   By my estimation, the keyset is empty at this point and the iterator points to an empty set.

   ****************************************************************************************************
    public void notify(Object attachment,int eventType)throws IOException {
        CometEvent event = new CometEvent(eventType,this,attachment);
        Iterator<CometHandler> iterator = handlers.keySet().iterator();
        notificationHandler.setBlockingNotification(blockingNotification);
        notificationHandler.notify(event,iterator);
        if (event.getType() != CometEvent.TERMINATE
            && event.getType() != CometEvent.INTERRUPT) {
            resetSuspendIdleTimeout();
        }
    }

4) Now when notificationHandler.notify(event,iterator) is invoked, the implementing class'
   DefaultNotificationHandler's notify(event,iterator) is actually invoked.

   Looking at this code, you can see that if the iterator (iteratorHandlers) points to an emtpy Set of handlers the
   notify0 method is never invoked. It appears that this method (notify0) is the method that actually
   invokes the onEvent() method of CometContext.

   ************************************************************************************************
    public void notify(final CometEvent cometEvent,final Iterator<CometHandler> iteratorHandlers)
        throws IOException {
        if (!spreadNotifyToManyToThreads && !blockingNotification && threadPool != null ){
            threadPool.execute(new Runnable() {
                public void run() {
                    while(iteratorHandlers.hasNext()){
                        notify0(cometEvent, iteratorHandlers.next());
                    }
                }});
        }else {
            while(iteratorHandlers.hasNext()){
                notify(cometEvent,iteratorHandlers.next());
            }
        }
    }


    protected void notify0(CometEvent cometEvent,CometHandler cometHandler) {
        try{
            switch (cometEvent.getType()) {
                case CometEvent.INTERRUPT:
                    cometHandler.onInterrupt(cometEvent); break;
                case CometEvent.NOTIFY:
                case CometEvent.READ:
                case CometEvent.WRITE:
                    if (cometHandler instanceof DefaultConcurrentCometHandler){
                        ((DefaultConcurrentCometHandler)cometHandler).EnQueueEvent(cometEvent);
                        break;
                    }
                    if (cometEvent.getCometContext().isActive(cometHandler)){
                        synchronized(cometHandler){
                            cometHandler.onEvent(cometEvent);
                        }
                    }
                    break;
                case CometEvent.INITIALIZE:
                    cometHandler.onInitialize(cometEvent); break;
                case CometEvent.TERMINATE:
                    synchronized(cometHandler){
                        cometHandler.onTerminate(cometEvent); break;
                    }
                default:
                    throw ISEempty;
            }
        } catch (Throwable ex) {
            try {
                cometEvent.getCometContext().resumeCometHandler(cometHandler);
            } catch (Throwable t) {
                logger.log(Level.FINE, "Resume phase failed: ", t);
            }
            logger.log(Level.FINE, "Notification failed: ", ex);
        }
    }