Package org.apache.jcs.auxiliary.lateral.socket.tcp.discovery

Source Code of org.apache.jcs.auxiliary.lateral.socket.tcp.discovery.UDPDiscoveryReceiver$MyThreadFactory

package org.apache.jcs.auxiliary.lateral.socket.tcp.discovery;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.
*/

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jcs.auxiliary.lateral.LateralCacheAttributes;
import org.apache.jcs.auxiliary.lateral.LateralCacheInfo;
import org.apache.jcs.auxiliary.lateral.LateralCacheNoWait;
import org.apache.jcs.auxiliary.lateral.socket.tcp.LateralTCPCacheManager;
import org.apache.jcs.auxiliary.lateral.socket.tcp.TCPLateralCacheAttributes;
import org.apache.jcs.auxiliary.lateral.socket.tcp.behavior.ITCPLateralCacheAttributes;
import org.apache.jcs.engine.behavior.ICache;
import org.apache.jcs.engine.behavior.ICompositeCacheManager;
import org.apache.jcs.engine.behavior.IShutdownObserver;

import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;

/**
* Receives UDP Discovery messages.
*/
public class UDPDiscoveryReceiver
    implements Runnable, IShutdownObserver
{
    private final static Log log = LogFactory.getLog( UDPDiscoveryReceiver.class );

    private final byte[] m_buffer = new byte[65536];

    private MulticastSocket m_socket;

    // todo consider using the threadpool manager to
    // get this thread pool
    // for now place a tight restrcition on the pool size
    private static final int maxPoolSize = 10;

    private PooledExecutor pooledExecutor = null;

    // number of messages received.
    private int cnt = 0;

    /**
     * Service to get cache names and hande request broadcasts
     */
    protected UDPDiscoveryService service = null;

    private String multicastAddressString = "";

    private int multicastPort = 0;

    private ICompositeCacheManager cacheMgr;

    private boolean shutdown = false;

    /**
     * Constructor for the LateralUDPReceiver object.
     * <p>
     * We determine out own host using InetAddress
     *
     * @param service
     * @param multicastAddressString
     * @param multicastPort
     * @param cacheMgr
     * @exception IOException
     */
    public UDPDiscoveryReceiver( UDPDiscoveryService service, String multicastAddressString, int multicastPort,
                                ICompositeCacheManager cacheMgr )
        throws IOException
    {
        this.service = service;
        this.multicastAddressString = multicastAddressString;
        this.multicastPort = multicastPort;
        this.cacheMgr = cacheMgr;

        // create a small thread pool to handle a barage
        pooledExecutor = new PooledExecutor( new BoundedBuffer( 100 ), maxPoolSize );
        pooledExecutor.discardOldestWhenBlocked();
        //pooledExecutor.setMinimumPoolSize(1);
        pooledExecutor.setThreadFactory( new MyThreadFactory() );

        if ( log.isInfoEnabled() )
        {
            log.info( "constructing listener, [" + this.multicastAddressString + ":" + this.multicastPort + "]" );
        }

        try
        {
            createSocket( this.multicastAddressString, this.multicastPort );
        }
        catch ( IOException ioe )
        {
            // consider eatign this so we can go on, or constructing the socket
            // later
            throw ioe;
        }
    }

    /**
     * Creates the socket for this class.
     *
     * @param multicastAddressString
     * @param multicastPort
     * @throws IOException
     */
    private void createSocket( String multicastAddressString, int multicastPort )
        throws IOException
    {
        try
        {
            m_socket = new MulticastSocket( multicastPort );
            m_socket.joinGroup( InetAddress.getByName( multicastAddressString ) );
        }
        catch ( IOException e )
        {
            log.error( "Could not bind to multicast address [" + multicastAddressString + ":" + multicastPort + "]", e );
            throw e;
        }
    }

    /**
     * Highly unreliable. If it is processing one message while another comes in ,
     * the second message is lost. This is for low concurency peppering.
     *
     * @return the object message
     * @throws IOException
     */
    public Object waitForMessage()
        throws IOException
    {
        final DatagramPacket packet = new DatagramPacket( m_buffer, m_buffer.length );

        Object obj = null;
        try
        {
            m_socket.receive( packet );

            final ByteArrayInputStream byteStream = new ByteArrayInputStream( m_buffer, 0, packet.getLength() );

            final ObjectInputStream objectStream = new ObjectInputStream( byteStream );

            obj = objectStream.readObject();

        }
        catch ( Exception e )
        {
            log.error( "Error receving multicast packet", e );
        }
        return obj;
    }

    /** Main processing method for the LateralUDPReceiver object */
    public void run()
    {
        try
        {
            while ( !shutdown )
            {
                Object obj = waitForMessage();

                // not thread safe, but just for debugging
                cnt++;

                if ( log.isDebugEnabled() )
                {
                    log.debug( getCnt() + " messages received." );
                }

                UDPDiscoveryMessage message = null;

                try
                {
                    message = (UDPDiscoveryMessage) obj;
                    // check for null
                    if ( message != null )
                    {
                        MessageHandler handler = new MessageHandler( message );

                        pooledExecutor.execute( handler );

                        if ( log.isDebugEnabled() )
                        {
                            log.debug( "Passed handler to executor." );
                        }
                    }
                    else
                    {
                        log.warn( "message is null" );
                    }
                }
                catch ( ClassCastException cce )
                {
                    log.warn( "Received unknown message type " + cce.getMessage() );
                }
            } // end while
        }
        catch ( Exception e )
        {
            log.error( "Unexpected exception in UDP receiver.", e );
            try
            {
                Thread.sleep( 100 );
                // TODO consider some failure count so we don't do this
                // forever.
            }
            catch ( Exception e2 )
            {
                log.error( "Problem sleeping", e2 );
            }
        }
        return;
    }

    /**
     * @param cnt
     *            The cnt to set.
     */
    public void setCnt( int cnt )
    {
        this.cnt = cnt;
    }

    /**
     * @return Returns the cnt.
     */
    public int getCnt()
    {
        return cnt;
    }

    /**
     * Separate thread run when a command comes into the UDPDiscoveryReceiver.
     */
    public class MessageHandler
        implements Runnable
    {
        private UDPDiscoveryMessage message = null;

        /**
         * @param message
         */
        public MessageHandler( UDPDiscoveryMessage message )
        {
            this.message = message;
        }

        /*
         * (non-Javadoc)
         *
         * @see java.lang.Runnable#run()
         */
        public void run()
        {
            // consider comparing ports here instead.
            if ( message.getRequesterId() == LateralCacheInfo.listenerId )
            {
                if ( log.isDebugEnabled() )
                {
                    log.debug( "from self" );
                }
            }
            else
            {
                if ( log.isDebugEnabled() )
                {
                    log.debug( "from another" );
                    log.debug( "Message = " + message );
                }

                // if this is a request message, have the service handle it and
                // return
                if ( message.getMessageType() == UDPDiscoveryMessage.REQUEST_BROADCAST )
                {
                    if ( log.isDebugEnabled() )
                    {
                        log.debug( "Message is a Request Broadcase, will have the service handle it." );
                    }
                    service.serviceRequestBroadcast();
                    return;
                }

                try
                {
                    // get a cache and add it to the no waits
                    // the add method should not add the same.
                    // we need the listener port from the original config.
                    ITCPLateralCacheAttributes lca = null;
                    if ( service.getTcpLateralCacheAttributes() != null )
                    {
                        lca = (ITCPLateralCacheAttributes) service.getTcpLateralCacheAttributes().copy();
                    }
                    else
                    {
                        lca = new TCPLateralCacheAttributes();
                    }
                    lca.setTransmissionType( LateralCacheAttributes.TCP );
                    lca.setTcpServer( message.getHost() + ":" + message.getPort() );
                    LateralTCPCacheManager lcm = LateralTCPCacheManager.getInstance( lca, cacheMgr );

                    ArrayList regions = message.getCacheNames();
                    if ( regions != null )
                    {
                        // for each region get the cache
                        Iterator it = regions.iterator();
                        while ( it.hasNext() )
                        {
                            String cacheName = (String) it.next();

                            try
                            {
                                ICache ic = lcm.getCache( cacheName );

                                if ( log.isDebugEnabled() )
                                {
                                    log.debug( "Got cache, ic = " + ic );
                                }

                                // add this to the nowaits for this cachename
                                if ( ic != null )
                                {
                                    service.addNoWait( (LateralCacheNoWait) ic );
                                    if ( log.isDebugEnabled() )
                                    {
                                        log.debug( "Called addNoWait for cacheName " + cacheName );
                                    }
                                }
                            }
                            catch ( Exception e )
                            {
                                log.error( "Problem creating no wait", e );
                            }
                        }
                        // end while
                    }
                    else
                    {
                        log.warn( "No cache names found in message " + message );
                    }
                }
                catch ( Exception e )
                {
                    log.error( "Problem getting lateral maanger", e );
                }
            }
        }
    }

    /**
     * Allows us to set the daemon status on the executor threads
     *
     * @author aaronsm
     *
     */
    class MyThreadFactory
        implements ThreadFactory
    {
        /*
         * (non-Javadoc)
         *
         * @see EDU.oswego.cs.dl.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
         */
        public Thread newThread( Runnable runner )
        {
            Thread t = new Thread( runner );
            t.setDaemon( true );
            t.setPriority( Thread.MIN_PRIORITY );
            return t;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.jcs.engine.behavior.ShutdownObserver#shutdown()
     */
    public void shutdown()
    {
        try
        {
            shutdown = true;
            m_socket.close();
            pooledExecutor.shutdownNow();
        }
        catch ( Exception e )
        {
            log.error( "Problem closing socket" );
        }
    }
}
// end class
TOP

Related Classes of org.apache.jcs.auxiliary.lateral.socket.tcp.discovery.UDPDiscoveryReceiver$MyThreadFactory

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.