dev@grizzly.java.net

patches to cometcontext , performance improvements.

From: gustav trede <gustav.trede_at_gmail.com>
Date: Fri, 31 Oct 2008 10:14:20 +0100

Hello,

several methods in cometcontext was having bad performance.
first iterating throw all handlers and then for each handler do a hashmap
lookup...
so i made it work with a simple iteration. no extra lookups and its much
fewer lines of code.
places where i fixed this is :

getCometHandler()
initialize()
interrupt()


    /**
     * Retrive a {_at_link CometHandler} using its SelectionKey. The
     * {_at_link SelectionKey} is not exposed to the Comet API, hence this
     * method must be protected.
     */
    protected CometHandler getCometHandler(SelectionKey key){
        for (Entry<CometHandler,SelectionKey> entry:handlers.entrySet()){
            if (entry.getValue() == key )
               return entry.getKey();
        }
        return null;
    }



    /**
     * Initialize the newly added {_at_link CometHandler}.
     *
     * @param attachment An object shared amongst {_at_link CometHandler}.
     * @param type The type of notification.
     * @param key The SelectionKey representing the CometHandler.
     */
     protected void initialize(SelectionKey key) throws IOException {
        CometEvent event = new CometEvent<E>();
        event.setType(CometEvent.INITIALIZE);
        event.setCometContext(this);

        for (Entry<CometHandler,SelectionKey> entry:handlers.entrySet()){
            SelectionKey ak = entry.getValue();
            if(ak != null && ak.equals(key)){
                entry.getKey().onInitialize(event);
                break;
            }
        }
    }


    /**
     * Interrupt a {_at_link CometHandler} by invoking {_at_link
CometHandler#onInterrupt}
     */
    protected void interrupt(CometTask task){
        CometEvent event = new CometEvent<E>();
        event.setType(CometEvent.INTERRUPT);
        event.attach(null);
        event.setCometContext(this);

        for (Entry<CometHandler,SelectionKey> entry:handlers.entrySet()){
            if (entry.getValue().equals(task.getSelectionKey())){
                try{
                    entry.getKey().onInterrupt(event);
                    handlers.remove(entry.getKey());
                } catch (IOException ex){
                    logger.log(Level.WARNING,"Exception: ",ex);
                }
                break;
            }
        }
        activeTasks.remove(task);
    }



in notify method, there is no special case for the non polling ,but pure
server pushing usage case.
there is no need to call resetsuspendidle if expiration is not used.
I found no nice way to do this, so i did it this way in my local code:

            if (expirationDelay < Long.MAX_VALUE)
                resetSuspendIdleTimeout()

heres the entire method:

    public void notify(final E attachment,final int eventType,final int
cometHandlerID)
            throws IOException{
        CometHandler cometHandler = getCometHandler(cometHandlerID);

        if (cometHandler == null){
            throw new IllegalStateException(INVALID_COMET_HANDLER);
        }
        CometEvent event = new CometEvent<E>();
        event.setType(eventType);
        event.attach(attachment);
        event.setCometContext(CometContext.this);


notificationHandler.setBlockingNotification(blockingNotification);
        notificationHandler.notify(event,cometHandler);
        if (event.getType() == CometEvent.TERMINATE
            || event.getType() == CometEvent.INTERRUPT) {
            resumeCometHandler(cometHandler);
        } else {
            if (expirationDelay < Long.MAX_VALUE)
                resetSuspendIdleTimeout();
        }
    }



Also there is a need to make things available for subclass, by changing
private to protected or get set methods.

regards
  gustav trede