FileDocCategorySizeDatePackage
CometSelector.javaAPI DocGlassfish v2 API11634Tue Jul 10 13:20:24 BST 2007com.sun.enterprise.web.connector.grizzly.comet

CometSelector

public class CometSelector extends Object
NIO Selector allowing CometHandler to receive non-blocking requests bytes during request polling.
author
Jeanfrancois Arcand

Fields Summary
protected CometEngine
cometEngine
The CometEngine singleton
private Selector
selector
The java.nio.channels.Selector
private Logger
logger
Logger.
private ConcurrentHashMap
keysToRegister
The list of SelectionKey to register with the Selector
Constructors Summary
public CometSelector(CometEngine cometEngine)
New CometSelector

param
cometEngine The CometEngine singleton


    
                 
       
        this.cometEngine = cometEngine;
    
Methods Summary
protected synchronized voidcancelKey(java.nio.channels.SelectionKey key)
Cancel a SelectionKey, and delegate the request polling interruption to the CometEngine

param
key the expired SelectionKey

        if (!key.isValid()) return;
        
        try{
            CometTask cometTask = (CometTask)key.attachment();
            if (cometTask != null){
                SelectorThread st = cometTask.getSelectorThread();
                SelectionKey mainKey = cometTask.getSelectionKey();
                cometTask.getCometContext().interrupt(mainKey);        
                cometEngine.interrupt(key);                    
                st.cancelKey(mainKey);
            } else {
                cometEngine.interrupt(key);                    
            }
        } catch (Throwable t) {
            logger.log(Level.SEVERE,"CometSelector",t);
        } finally {
            key.attach(null);
        }
        key.cancel();
    
public java.nio.channels.SelectionKeycometKeyFor(java.nio.channels.SelectableChannel channel)
Return the SelectionKey associated with this channel.

        NioProvider nioP = NioProvider.getProvider();
        if (nioP == null) {
            return channel.keyFor(selector);
        } else {
            return nioP.keyFor(channel, selector);
        }
    
protected voidexpireIdleKeys()
Expires registered SelectionKey. If a SelectionKey is expired, the request will be resumed and the HTTP request will complete,

       
        Set<SelectionKey> readyKeys = selector.keys();
        if (readyKeys.isEmpty()){
            return;
        }
        long current = System.currentTimeMillis();
        Iterator<SelectionKey> iterator = readyKeys.iterator();
        SelectionKey key;
        while (iterator.hasNext()) {
            key = iterator.next();    
            CometTask cometTask = (CometTask)key.attachment();
            
            if (cometTask == null) return;
            
            long expire = cometTask.getExpireTime();
            if (current - expire >= cometTask.getExpirationDelay()) {
                cancelKey(key);
            } 
            
            /**
             * The connection has been resumed since the timeout is 
             * re-attached to the SelectionKey so cancel the Comet key.
             */
            if (cometTask.getSelectionKey() != null 
                    && cometTask.getSelectionKey().attachment() instanceof Long){
                key.cancel();
                cometEngine.interrupt(key);
            }
        }                    
    
public voidregisterKey(java.nio.channels.SelectionKey key, CometTask cometTask)
Register the SelectionKey/code> to the Selector. We cannot register the SelectionKey/code> directy on the Selector because there is a deadlock in the VM (see bug XXX).

        cometTask.setExpireTime(System.currentTimeMillis());
        keysToRegister.put(key, cometTask);
        selector.wakeup();
    
public voidstart()
Start the java.nio.channels.Selector running on its Thread.

        new Thread("CometSelector"){
            {
               setDaemon(true);                
            }
            
            public void run(){       
                try{
                    selector = Selector.open();
                } catch(IOException ex){
                    // Most probably a fd leak.
                    logger.log(Level.SEVERE,"CometSelector.open()",ex);
                    return;
                }
                while (true){
                    SelectionKey key = null;
                    Set readyKeys;
                    Iterator<SelectionKey> iterator;
                    int selectorState = 0; 

                    try{
                        selectorState = 0;
  
                        try{
                            selectorState = selector.select(1000);
                        } catch (CancelledKeyException ex){
                            ;
                        }

                        readyKeys = selector.selectedKeys();
                        iterator = readyKeys.iterator();                      
                        CometTask cometTask;
                        while (iterator.hasNext()) {
                            key = iterator.next();
                            iterator.remove();
                            if (key.isValid()) {
                                cometTask = (CometTask)key.attachment();
                                if (key.isReadable()){
                                    key.interestOps(key.interestOps() 
                                        & (~SelectionKey.OP_READ));
                                    cometTask.upcoming_op = 
                                            CometTask.OP_EVENT.READ;
                                } 
                                
                                if (key.isWritable()){
                                    key.interestOps(key.interestOps() 
                                        & (~SelectionKey.OP_WRITE));   
                                    cometTask.upcoming_op = 
                                            CometTask.OP_EVENT.WRITE;                                    
                                }
                                
                                if (cometTask.getSelectionKey().attachment() == null){
                                    cometTask.execute();
                                } else {
                                    key.cancel();
                                }
                            } else {
                                cancelKey(key);
                            }
                        }
                        
                        Iterator<SelectionKey> keys = 
                                keysToRegister.keySet().iterator();
                        /**
                         * The mainKey is the SelectionKey returned by the
                         * Selector used in the SelectorThread class.
                         */
                        SelectionKey mainKey;
                        SocketChannel channel;
                        while (keys.hasNext()){
                            mainKey = keys.next();
                            channel =  (SocketChannel)mainKey.channel();
                            if (mainKey.isValid() && channel.isOpen()) {
                                key = channel
                                    .register(selector,SelectionKey.OP_READ);  
                                cometTask = keysToRegister.remove(mainKey);
                                cometTask.setCometKey(key);
                                key.attach(cometTask); 
                                keys.remove();
                            } 
                        }                             
                        expireIdleKeys();
                        
                        if (selectorState <= 0){
                            selector.selectedKeys().clear();
                        }
                    } catch (Throwable t){
                        if (key != null){                           
                            try{
                                cancelKey(key);
                            } catch (Throwable t2){
                                logger.log(Level.SEVERE,"CometSelector",t2);
                            }
                        }
                                                
                        if (selectorState <= 0){
                            selector.selectedKeys().clear();
                        }
                        logger.log(Level.SEVERE,"CometSelector",t);
                    }      
                }   
            }
        }.start();
    
public voidwakeup()
Wakes up the java.nio.channels.Selector

        selector.wakeup();