Package org.apache.geronimo.messaging.remotenode

Source Code of org.apache.geronimo.messaging.remotenode.RemoteNodeManagerImpl

/**
*
* 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.messaging.remotenode;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geronimo.messaging.CommunicationException;
import org.apache.geronimo.messaging.Msg;
import org.apache.geronimo.messaging.MsgHeader;
import org.apache.geronimo.messaging.MsgHeaderConstants;
import org.apache.geronimo.messaging.NodeException;
import org.apache.geronimo.messaging.NodeInfo;
import org.apache.geronimo.messaging.NodeTopology;
import org.apache.geronimo.messaging.interceptors.MsgOutInterceptor;
import org.apache.geronimo.messaging.io.IOContext;
import org.apache.geronimo.pool.ClockPool;

/**
* RemoteNode implementation.
*
* @version $Rev: 46019 $ $Date: 2004-09-14 04:56:06 -0500 (Tue, 14 Sep 2004) $
*/
public class RemoteNodeManagerImpl
    implements RemoteNodeManager
{

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

    private final MessagingTransportFactory factory;
    private final IOContext ioContext;
    private final Collection listeners;
    private final Map remoteNodes;
    private final RemoteNodeRouter router;
    private NodeServer server;
    private final NodeInfo nodeInfo;
    private final RemoteNodeMonitor remoteNodeMonitor;
   
    /**
     * Node topology to be used to derive the most appropriate path to reach
     * a node.
     */
    private NodeTopology topology;
   
    /**
     * Topology being prepared.
     */
    private NodeTopology preparedTopology;
   
    public RemoteNodeManagerImpl(NodeInfo aNodeInfo, IOContext anIOContext,
        ClockPool aClockPool, MessagingTransportFactory aFactory) {
        if ( null == aNodeInfo ) {
            throw new IllegalArgumentException("NodeInfo is required.");
        } else if ( null == anIOContext ) {
            throw new IllegalArgumentException("IOContext is required.");
        } else if ( null == aClockPool ) {
            throw new IllegalArgumentException("Clock Pool is required.");
        } else if ( null == aFactory ) {
            throw new IllegalArgumentException("Factory is required.");
        }
        nodeInfo = aNodeInfo;
        ioContext = anIOContext;
        factory = aFactory;
       
        listeners = new ArrayList();
        remoteNodes = new HashMap();
        router = new RemoteNodeRouter();
        remoteNodeMonitor = new RemoteNodeMonitor(this, aClockPool);
    }

    public void start() throws NodeException {
        log.info("Starting RemoteNodeManager for node {" + nodeInfo + "}");
        server = factory.factoryServer(nodeInfo, ioContext);
        server.setRemoteNodeManager(this);
        server.start();
        remoteNodeMonitor.start();
    }
   
    public void stop() throws NodeException {
        log.info("Stopping RemoteNodeManager for node {" + nodeInfo + "}");
        remoteNodeMonitor.stop();
        server.stop();
        Collection nodes;
        synchronized(remoteNodes) {
            nodes = new ArrayList(remoteNodes.values());
        }
        for (Iterator iter = nodes.iterator(); iter.hasNext();) {
            RemoteNode node = (RemoteNode) iter.next();
            node.leave();
            node.setMsgProducerOut(null);
        }
    }

    public void prepareTopology(NodeTopology aTopology) throws NodeException {
        Set oldNeighbours;
        if ( null == topology ) {
            oldNeighbours = Collections.EMPTY_SET;
        } else {
            oldNeighbours = topology.getNeighbours(nodeInfo);
        }
        // Computes the new neighbours
        Set newNeighbours = aTopology.getNeighbours(nodeInfo);
        newNeighbours.removeAll(oldNeighbours);

        // Makes sure that one does not drop them during the reconfiguration.
        remoteNodeMonitor.unscheduleNodeDeletion(newNeighbours);

        Exception exception = null;
        // Joins all the new neighbours
        for (Iterator iter = newNeighbours.iterator(); iter.hasNext();) {
            NodeInfo node = (NodeInfo) iter.next();
            try {
                findOrJoinRemoteNode(node);
            } catch (NodeException e) {
                exception = e;
                break;
            } catch (CommunicationException e) {
                exception = e;
                break;
            }
        }
        // One new neighbour has not been joined successfully. Rolls-back.
        if ( null != exception ) {
            for (Iterator iter = newNeighbours.iterator(); iter.hasNext();) {
                NodeInfo node = (NodeInfo) iter.next();
                leaveRemoteNode(node);
            }
            throw new NodeException("Can not apply topology.", exception);
        }
        preparedTopology = aTopology;
    }
   
    public void commitTopology() {
        Set oldNeighbours;
        if ( null == topology ) {
            oldNeighbours = Collections.EMPTY_SET;
        } else {
            oldNeighbours = topology.getNeighbours(nodeInfo);
        }
        // Computes the old neighbours
        Set newNeighbours = preparedTopology.getNeighbours(nodeInfo);
        oldNeighbours.removeAll(newNeighbours);

        // Schedules the deletion of the old neighbours.
        remoteNodeMonitor.scheduleNodeDeletion(oldNeighbours);
       
        topology = preparedTopology;
    }
   
    public void addListener(RemoteNodeEventListener aListener) {
        synchronized(listeners) {
            listeners.add(aListener);
        }
    }

    public void removeListener(RemoteNodeEventListener aListener) {
        synchronized(listeners) {
            listeners.remove(aListener);
        }
    }
   
    public void leaveRemoteNode(NodeInfo aNodeInfo) {
        synchronized(remoteNodes) {
            RemoteNode remoteNode = (RemoteNode) remoteNodes.get(aNodeInfo);
            if ( null == remoteNode ) {
                return;
            }
            remoteNode.leave();
            unregisterRemoteNode(remoteNode);
        }
    }
   
    public RemoteNode findOrJoinRemoteNode(NodeInfo aNodeInfo)
        throws NodeException {
        RemoteNode remoteNode;
        synchronized(remoteNodes) {
            remoteNode = (RemoteNode) remoteNodes.get(aNodeInfo);
            if ( null != remoteNode ) {
                return remoteNode;
            }
            remoteNode =
                factory.factoryRemoteNode(nodeInfo, aNodeInfo, ioContext);
            remoteNode.setManager(this);
            remoteNode.join();
        }
        return remoteNode;
    }
   
    public RemoteNode findRemoteNode(NodeInfo aNodeInfo) {
        synchronized(remoteNodes) {
            return (RemoteNode) remoteNodes.get(aNodeInfo);
        }
    }

    public void registerRemoteNode(RemoteNode aRemoteNode) {
        log.info("Node {" + aRemoteNode.getNodeInfo() + "} has joined.");
        synchronized(remoteNodes) {
            remoteNodes.put(aRemoteNode.getNodeInfo(), aRemoteNode);
        }
        notifyListeners(
            new RemoteNodeEvent(aRemoteNode, RemoteNodeEvent.NODE_ADDED));
    }

    public void unregisterRemoteNode(RemoteNode aRemoteNode) {
        log.info("Node {" + aRemoteNode.getNodeInfo() + "} has left.");
        synchronized(remoteNodes) {
            remoteNodes.remove(aRemoteNode.getNodeInfo());
        }
        notifyListeners(
            new RemoteNodeEvent(aRemoteNode, RemoteNodeEvent.NODE_REMOVED));
    }
   
    public Collection listRemoteNodes() {
        return Collections.unmodifiableCollection(remoteNodes.values());
    }

    public MsgOutInterceptor getMsgConsumerOut() {
        return router;
    }

    private void notifyListeners(RemoteNodeEvent anEvent) {
        Collection tmpListeners;
        synchronized(listeners) {
            tmpListeners = new ArrayList(listeners);
        }
        for (Iterator iter = tmpListeners.iterator(); iter.hasNext();) {
            RemoteNodeEventListener listener =
                (RemoteNodeEventListener) iter.next();
            listener.fireRemoteNodeEvent(anEvent);
        }
    }
   
    /**
     * Msg consumer.
     */
    private class RemoteNodeRouter implements MsgOutInterceptor {

        public void push(Msg aMsg) {
            MsgHeader header = aMsg.getHeader();
            Object destNode = header.getHeader(MsgHeaderConstants.DEST_NODES);
            if (destNode instanceof NodeInfo) {
                destNode = new NodeInfo[] {(NodeInfo) destNode };
            }
            MsgOutInterceptor out;
            NodeInfo[] dests = (NodeInfo[]) destNode;
            for (int i = 0; i < dests.length; i++) {
                NodeInfo target = dests[i];
                Msg msg2 = new Msg(aMsg);
                MsgHeader header2 = msg2.getHeader();
                // A path is defined if this Msg is routed via the node
                // owning this instance.
                NodeInfo[] path =
                    (NodeInfo[]) header2.getOptionalHeader(
                        MsgHeaderConstants.DEST_NODE_PATH);
                if ( null != path ) {
                    // A path has already been computed. Gets the next hop.
                    target = path[0];
                    // Pops the next hop from the path.
                    header2.addHeader(
                        MsgHeaderConstants.DEST_NODE_PATH,
                        NodeInfo.pop(path));
                    RemoteNode remoteNode = findRemoteNode(target);
                    if ( null == remoteNode ) {
                        throw new CommunicationException(target +
                            " has failed during a topology reconfiguration.");
                    }
                    out = remoteNode.getMsgConsumerOut();
                } else {
                    // A path has not already been computed. Computes one.
                    NodeInfo src = (NodeInfo)
                        header2.getHeader(MsgHeaderConstants.SRC_NODE);
                    NodeTopology topo = markTopology(header2);
                    path = topo.getPath(src, target);
                    if (null == path) {
                        throw new CommunicationException("{" + target
                            + "} is not reachable by {" + src +
                            "} in the topology " + topo);
                    }
                    RemoteNode remoteNode = findRemoteNode(path[0]);
                    if ( null == remoteNode ) {
                        throw new CommunicationException(path[0] +
                            " has failed during a topology reconfiguration.");
                    }
                    out = remoteNode.getMsgConsumerOut();
                   
                    // Inserts the computed path and the new dests.
                    header2.addHeader(MsgHeaderConstants.DEST_NODE_PATH, NodeInfo.pop(path));
                    header2.addHeader(MsgHeaderConstants.DEST_NODES, target);
                }
                out.push(msg2);
            }
        }
       
        /**
         * If the topology version is not set, then the Msg is sent in the
         * current topology.
         * <BR>
         * If it is set, then one checks that the associated topology is
         * still defined. It must be either the currently installed or the
         * one being prepared.
         */
        private NodeTopology markTopology(MsgHeader aHeader) {
            NodeTopology topo = topology;
            Integer version = (Integer)
                aHeader.getOptionalHeader(MsgHeaderConstants.TOPOLOGY_VERSION);
            if ( null == version ) {
                aHeader.addHeader(MsgHeaderConstants.TOPOLOGY_VERSION,
                    new Integer(topo.getVersion()));
            } else if ( version.intValue() == preparedTopology.getVersion() ) {
                topo = preparedTopology;
            } else if ( version.intValue() != topo.getVersion() ) {
                throw new CommunicationException("Topology version " +
                    version + " too old.");
            }
            return topo;
        }
       
    }
   
}
TOP

Related Classes of org.apache.geronimo.messaging.remotenode.RemoteNodeManagerImpl

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.