Package org.apache.geronimo.network

Source Code of org.apache.geronimo.network.SelectorManager$Event

/**
*
* Copyright 2004 The Apache Software Foundation
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

package org.apache.geronimo.network;

import java.io.IOException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geronimo.gbean.GBeanInfo;
import org.apache.geronimo.gbean.GBeanInfoBuilder;
import org.apache.geronimo.gbean.GBeanLifecycle;
import org.apache.geronimo.gbean.WaitingException;
import org.apache.geronimo.pool.ThreadPool;


/**
* The SelectorManager will manage one Selector and the thread that checks
* the selector.
*
* @version $Rev: 56022 $ $Date: 2004-10-30 00:16:18 -0500 (Sat, 30 Oct 2004) $
*/
public class SelectorManager implements Runnable, GBeanLifecycle {

    final static private Log log = LogFactory.getLog(SelectorManager.class);

    private ThreadPool threadPool;

    /**
     * The running flag that all worker and server
     * threads check to determine if the service should
     * be stopped.
     */
    private volatile boolean running;

    /**
     * The selector used to wait for non-blocking events.
     */
    private Selector selector;

    /**
     * timeout for select
     */
    private long timeout;

    /**
     * The groupd that threads created by this class will be a member of.
     */
    private ThreadGroup threadGroup;

    /**
     * The name that the selector thread is labeled
     */
    private String threadName;

    /**
     * how many times we have been started ++ and stoped --
     */
    private int startCounter;

    /**
     * A list of channels to be closed.
     */
    private Stack closing = new Stack();


    public SelectorManager() throws IOException {
        threadGroup = new ThreadGroup("Geronimo NIO Workers");
        selector = Selector.open();
    }

    public long getTimeout() {
        return timeout;
    }

    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    public Selector getSelector() {
        return selector;
    }

    public ThreadPool getThreadPool() {
        return threadPool;
    }

    public void setThreadPool(ThreadPool threadPool) {
        this.threadPool = threadPool;
    }

    public String getThreadName() {
        return threadName;
    }

    public void setThreadName(String threadName) {
        this.threadName = threadName;
    }

    /**
     * Main processing method for the SelectionManager object
     */
    public void run() {
        try {

            log.debug("Selector Work thread has started.");
            log.debug("Selector Manager timeout: " + timeout);
            while (running) {
                try {

                    synchronized (closing) {
                        if (!closing.isEmpty()) {
                            /**
                             * Close channels that have been queued up to be
                             * closed.  Closing channels in this manner prevents
                             * NullPointExceptions.
                             *
                             * http://developer.java.sun.com/developer/bugParade/bugs/4729342.html
                             */
                            Iterator iter = closing.iterator();

                            while (iter.hasNext()) {
                                SelectableChannel selectableChannel = (SelectableChannel) iter.next();
                                selectableChannel.close();
                            }
                            closing.clear();
                        }
                    }

                    log.trace("Waiting for selector to return.");
                    if (selector.select(timeout) == 0) {
                        log.trace("timeout == 0");

                        /**
                         * Clean stale connections that do not have and data: select
                         * returns indicating that the count of active connections with
                         * input is 0.  However the list still has these "stale"
                         * connections lingering around.  We remove them since they
                         * are prematurely triggering selection to return w/o input.
                         *
                         * http://nagoya.apache.org/jira/secure/ViewIssue.jspa?key=DIR-18
                         */
                        Iterator list = selector.selectedKeys().iterator();

                        while (list.hasNext()) {
                            SelectionKey key = (SelectionKey) list.next();
                            log.trace("REMOVING " + key);
                            key.channel().close();
                            key.cancel();
                            list.remove();
                        }

                        continue;
                    }

                    // Get a java.util.Set containing the SelectionKey objects for
                    // all channels that are ready for I/O.
                    Set keys = selector.selectedKeys();

                    // Use a java.util.Iterator to loop through the selected keys
                    for (Iterator i = keys.iterator(); i.hasNext();) {
                        SelectionKey key = (SelectionKey) i.next();

                        if (key.isReadable()) {
                            log.trace("-OP_READ " + key);
                            key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
                            threadPool.execute(new Event(key, SelectionKey.OP_READ));
                        }
                        if (key.isWritable()) {
                            log.trace("-OP_WRITE " + key);
                            key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
                            threadPool.execute(new Event(key, SelectionKey.OP_WRITE));
                        }
                        if (key.isAcceptable()) {
                            log.trace("-OP_ACCEPT " + key);
                            key.interestOps(key.interestOps() & (~SelectionKey.OP_ACCEPT));
                            threadPool.execute(new Event(key, SelectionKey.OP_ACCEPT));
                        }

                        i.remove(); // Remove the key from the set of selected keys
                    }

                } catch (CancelledKeyException e) {
                    log.debug("Key has Been Cancelled: " + e);
                }
            }
        } catch (IOException e) {
            log.warn("IOException occured.", e);
        } catch (InterruptedException e) {
            log.debug("Selector Work thread has been interrupted.");
        } catch (Throwable t) {
            log.error("Throwable occured.", t);
        } finally {
            log.debug("Selector Work thread has stopped.");
        }
    }

    public SelectionKey register(SelectableChannel selectableChannel, int ops, SelectionEventListner listener) throws ClosedChannelException {
        synchronized (closing) {
            selector.wakeup();
            SelectionKey key = selectableChannel.register(selector, ops, listener);
            return key;
        }
    }

    public void closeChannel(SelectableChannel selectableChannel) throws IOException {
        synchronized (closing) {
            selector.wakeup();
            closing.push(selectableChannel);
        }
    }

    public void addInterestOps(SelectionKey selectorKey, int addOpts) {
        synchronized (closing) {
            selector.wakeup();
            selectorKey.interestOps(selectorKey.interestOps() | addOpts);
        }
    }

    public void doStart() throws WaitingException, Exception {
        startCounter++;
        if (startCounter == 1) {
            log.debug("Starting a Selector Work thread.");
            running = true;
            new Thread(threadGroup, this, threadName).start();
        }
    }

    public void doStop() throws WaitingException, Exception {
        startCounter--;
        if (startCounter == 0) {
            log.debug("Stopping a Selector Work thread.");
            running = false;
            selector.wakeup();
        }
    }

    public void doFail() {
    }

    private static final GBeanInfo GBEAN_INFO;

    static {
        GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(SelectorManager.class);

        infoFactory.addAttribute("timeout", long.class, true);
        infoFactory.addReference("ThreadPool", ThreadPool.class);
        infoFactory.addAttribute("threadPool", ThreadPool.class, false);
        infoFactory.addAttribute("threadName", String.class, true);

        infoFactory.addOperation("getSelector");
        infoFactory.addOperation("closeChannel", new Class[] {SelectableChannel.class});
        infoFactory.addOperation("addInterestOps", new Class[] {SelectionKey.class, int.class});
        infoFactory.addOperation("register", new Class[] {SelectableChannel.class, int.class, SelectionEventListner.class});

        GBEAN_INFO = infoFactory.getBeanInfo();
    }

    public static GBeanInfo getGBeanInfo() {
        return GBEAN_INFO;
    }

    public class Event implements Runnable {

        final int flags;
        final SelectionKey key;

        private Event(SelectionKey key, int flags) {
            this.flags = flags;
            this.key = key;
        }

        public SelectionKey getSelectionKey() {
            return key;
        }

        public final boolean isReadable() {
            return (flags & SelectionKey.OP_READ) != 0;
        }

        public final boolean isWritable() {
            return (flags & SelectionKey.OP_WRITE) != 0;
        }

        public final boolean isAcceptable() {
            return (flags & SelectionKey.OP_ACCEPT) != 0;
        }

        public void run() {
            try {
                ((SelectionEventListner) key.attachment()).selectionEvent(this);
            } catch (Throwable e) {
                log.trace("Request Failed.", e);
            }
        }
    }
}
TOP

Related Classes of org.apache.geronimo.network.SelectorManager$Event

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.