001package org.apache.commons.jcs.utils.discovery;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
024
025import java.util.ArrayList;
026
027/**
028 * Used to periodically broadcast our location to other caches that might be listening.
029 */
030public class UDPDiscoverySenderThread
031    implements Runnable
032{
033    /** The logger. */
034    private static final Log log = LogFactory.getLog( UDPDiscoverySenderThread.class );
035
036    /**
037     * details of the host, port, and service being advertised to listen for TCP socket connections
038     */
039    private final UDPDiscoveryAttributes attributes;
040
041    /** List of known regions. */
042    private ArrayList<String> cacheNames = new ArrayList<String>();
043
044    /**
045     * @param cacheNames The cacheNames to set.
046     */
047    protected void setCacheNames( ArrayList<String> cacheNames )
048    {
049        if ( log.isInfoEnabled() )
050        {
051            log.info( "Resetting cacheNames = [" + cacheNames + "]" );
052        }
053        this.cacheNames = cacheNames;
054    }
055
056    /**
057     * @return Returns the cacheNames.
058     */
059    protected ArrayList<String> getCacheNames()
060    {
061        return cacheNames;
062    }
063
064    /**
065     * Constructs the sender with the port to tell others to connect to.
066     * <p>
067     * On construction the sender will request that the other caches let it know their addresses.
068     * @param attributes host, port, etc.
069     * @param cacheNames List of strings of the names of the region participating.
070     */
071    public UDPDiscoverySenderThread( UDPDiscoveryAttributes attributes, ArrayList<String> cacheNames )
072    {
073        this.attributes = attributes;
074
075        this.cacheNames = cacheNames;
076
077        if ( log.isDebugEnabled() )
078        {
079            log.debug( "Creating sender thread for discoveryAddress = [" + attributes.getUdpDiscoveryAddr()
080                + "] and discoveryPort = [" + attributes.getUdpDiscoveryPort() + "] myHostName = ["
081                + attributes.getServiceAddress() + "] and port = [" + attributes.getServicePort() + "]" );
082        }
083
084        UDPDiscoverySender sender = null;
085        try
086        {
087            // move this to the run method and determine how often to call it.
088            sender = new UDPDiscoverySender( attributes.getUdpDiscoveryAddr(), attributes.getUdpDiscoveryPort() );
089            sender.requestBroadcast();
090
091            if ( log.isDebugEnabled() )
092            {
093                log.debug( "Sent a request broadcast to the group" );
094            }
095        }
096        catch ( Exception e )
097        {
098            log.error( "Problem sending a Request Broadcast", e );
099        }
100        finally
101        {
102            try
103            {
104                if ( sender != null )
105                {
106                    sender.destroy();
107                }
108            }
109            catch ( Exception e )
110            {
111                log.error( "Problem closing Request Broadcast sender", e );
112            }
113        }
114    }
115
116    /**
117     * Send a message.
118     */
119    @Override
120    public void run()
121    {
122        UDPDiscoverySender sender = null;
123        try
124        {
125            // create this connection each time.
126            // more robust
127            sender = new UDPDiscoverySender( attributes.getUdpDiscoveryAddr(), attributes.getUdpDiscoveryPort() );
128
129            sender.passiveBroadcast( attributes.getServiceAddress(), attributes.getServicePort(), cacheNames );
130
131            // todo we should consider sending a request broadcast every so
132            // often.
133
134            if ( log.isDebugEnabled() )
135            {
136                log.debug( "Called sender to issue a passive broadcast" );
137            }
138
139        }
140        catch ( Exception e )
141        {
142            log.error( "Problem calling the UDP Discovery Sender [" + attributes.getUdpDiscoveryAddr() + ":"
143                + attributes.getUdpDiscoveryPort() + "]", e );
144        }
145        finally
146        {
147            if (sender != null)
148            {
149                try
150                {
151                    sender.destroy();
152                }
153                catch ( Exception e )
154                {
155                    log.error( "Problem closing Passive Broadcast sender", e );
156                }
157            }
158        }
159    }
160
161    /**
162     * Issues a remove broadcast to the others.
163     */
164    protected void shutdown()
165    {
166        UDPDiscoverySender sender = null;
167        try
168        {
169            // create this connection each time.
170            // more robust
171            sender = new UDPDiscoverySender( attributes.getUdpDiscoveryAddr(), attributes.getUdpDiscoveryPort() );
172
173            sender.removeBroadcast( attributes.getServiceAddress(), attributes.getServicePort(), cacheNames );
174
175            if ( log.isDebugEnabled() )
176            {
177                log.debug( "Called sender to issue a remove broadcast in shudown." );
178            }
179        }
180        catch ( Exception e )
181        {
182            log.error( "Problem calling the UDP Discovery Sender", e );
183        }
184        finally
185        {
186            try
187            {
188                if ( sender != null )
189                {
190                    sender.destroy();
191                }
192            }
193            catch ( Exception e )
194            {
195                log.error( "Problem closing Remote Broadcast sender", e );
196            }
197        }
198    }
199}