All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coos.messaging.routing.DefaultRouter Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
/**
 * COOS - Connected Objects Operating System (www.connectedobjects.org).
 *
 * Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * You may also contact one of the following for additional information:
 * Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
 * Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
 */
package org.coos.messaging.routing;

import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.coos.messaging.COOS;
import org.coos.messaging.ConnectingException;
import org.coos.messaging.Link;
import org.coos.messaging.Message;
import org.coos.messaging.Processor;
import org.coos.messaging.ProcessorException;
import org.coos.messaging.ProcessorInterruptException;
import org.coos.messaging.impl.DefaultProcessor;
import org.coos.messaging.util.Log;
import org.coos.messaging.util.LogFactory;
import org.coos.messaging.util.URIHelper;
import org.coos.messaging.util.UuidGenerator;
import org.coos.messaging.util.UuidHelper;


/**
 * The DefaultRouter (actually default point to point router) contains the point
 * to point routing mechanisms
 *
 * @author Knut Eilif Husa, Tellu AS
 */
public class DefaultRouter extends DefaultProcessor implements Router, HashMapCallback {

    private static final String LINK_TIMEOUT_DEFAULT = "60000"; // Default value
    public static final String LINK_TIMEOUT = "linkTimeout";

    private Collection preProcessors = new ConcurrentLinkedQueue();
    private Collection postProcessors = new ConcurrentLinkedQueue();

    private Map> routingTables = new ConcurrentHashMap>();
    private Map aliasTable = new ConcurrentHashMap();

    // todo let the links be handled by the coos instance
    private Map links = new ConcurrentHashMap();
    private Map routingAlgorithms = new ConcurrentHashMap();
    private Map segmentMapping = new ConcurrentHashMap();

    // The uuid of the router in the different segments it participates in. If
    // more than one uuid, this router is a gateway router
    private Collection routerUuids = new ConcurrentLinkedQueue();
    private Collection QoSClasses = new ConcurrentLinkedQueue();
    private String defaultQoSClass;
    private String COOSInstanceName;
    private boolean running = false;
    private boolean enabled = true;
    @SuppressWarnings("unused")
	private boolean loggingEnabled = false;
    private Link defaultGw = null;


    private final Log logger = LogFactory.getLog(this.getClass(), false);
    private COOS COOS;

    private long linkTimeout;

    // This constructor is only used by tests
    public DefaultRouter(String routerUuid) {
        COOSInstanceName = routerUuid;
        new LinkStateAlgorithm(this, routerUuid);
        addQoSClass(Link.DEFAULT_QOS_CLASS, true);
        addSegmentMapping(UuidHelper.getSegmentFromSegmentOrEndpointUuid(routerUuid), routerUuid, "linkstate");
    }

    public DefaultRouter() {
        //addQoSClass(Link.DEFAULT_QOS_CLASS, true);
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public void removeRouterUuid(String routerUuid) {
        routerUuids.remove(routerUuid);
    }

    public void setLoggingEnabled(boolean loggingEnabled) {
        this.loggingEnabled = loggingEnabled;

        for (RoutingAlgorithm routingAlgorithm : routingAlgorithms.values()) {
            routingAlgorithm.setLoggingEnabled(loggingEnabled);
        }
    }

    @SuppressWarnings("unchecked")
	public void processMessage(Message msg) {

        // Router preprocessors
        for (RouterProcessor routerProcessor : preProcessors) {

            try {
                routerProcessor.processMessage(msg);
            } catch (ProcessorInterruptException e) {
                return;
            } catch (ProcessorException e) {
                logger.error("ProcessorException caught.", e);
            } catch (Exception e) {
                logger.error("Unknown Exception caught.", e);
            }
        }

        if (msg.getReceiverEndpointUri() == null) {
            logger.warn("Message from " + msg.getSenderEndpointUri() + " missing receiver address");
            replyErrorReason(msg, Message.ERROR_NO_RECEIVER);

            return;
        }

        String qosClass = msg.getHeader(Message.QOS_CLASS);

        if (qosClass == null) {
            qosClass = defaultQoSClass;
        }

        Map routingTable = routingTables.get(qosClass);

        String hops = msg.getHeader(Message.HOPS);

        if (hops == null) {
            hops = "1";
        } else {
            hops = String.valueOf(Integer.parseInt(hops) + 1);
        }

        msg.setHeader(Message.HOPS, hops);

        if (Integer.parseInt(hops) > 244) {
            logger.warn("Message from " + msg.getSenderEndpointUri() + ", to: " + msg.getReceiverEndpointUri() + " too many hops");

            return;
        }

        String uuid = resolveAlias(msg);

        if (uuid == null) {

            // will never occur except for localcoos
            replyErrorReason(msg, Message.ERROR_NO_ALIAS + ":" + msg.getReceiverEndpointUri());

            return;
        }

        uuid = UuidHelper.getQualifiedUuid(uuid);

        Link link;

        // check if the message is destined towards this router
        if (routerUuids.contains(uuid)) {
            logger.putMDC(UUID_PREFIX, uuid);

            if (msg.getType().equals(Message.TYPE_ROUTING_INFO)) {
                routingAlgorithms.get(UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(uuid)).processRoutingInfo(msg);
            } else if (msg.getType().equals(Message.TYPE_ALIAS)) {

                try {
                    setLinkAliases((Vector) msg.getBody(), msg.getMessageContext().getInBoundChannel().getOutLink());
                } catch (ProcessorException e) {
                    logger.error("ProcessorException caught while stopping endpoint.", e);
                }
            }
        } else {

            
            // The routing step
            link = route(uuid, msg, routingTable);

            if (link != null) {
                msg.getMessageContext().setNextLink(link);
            }

            // Router postprocessors
            for (RouterProcessor routerProcessor : postProcessors) {

                try {
                    routerProcessor.processMessage(msg);
                } catch (ProcessorInterruptException e) {
                    return;
                } catch (ProcessorException e) {
                    logger.error("ProcessorException caught.", e);
                } catch (Exception e) {
                    logger.error("Unknown Exception caught.", e);
                }
            }

            // The sending step
            if (link != null) {

                if (msg.getHeader(Message.TRACE_ROUTE) != null) {
                    String trace = msg.getHeader(Message.TRACE);

                    if (trace == null) {
                        trace = COOSInstanceName;
                    }

                    msg.setHeader(Message.TRACE, trace + " -> " + link.getDestinationUuid());
                }

                try {
                    link.processMessage(msg);
                } catch (ProcessorException e) {
                    replyErrorReason(msg, e.getMessage());
                }
            } else {
                String errorMsg;
                URIHelper helper = new URIHelper(msg.getReceiverEndpointUri());
                String alias = helper.getEndpoint();

                if (uuid.equals("null")) {
                    errorMsg = COOSInstanceName + ": No uuid for alias " + alias + ", No route from " + COOSInstanceName;
                } else {

                    if (uuid.equals(alias)) {
                        errorMsg = COOSInstanceName + ": No route to: " + alias + " from " + COOSInstanceName;
                    } else {
                        errorMsg = COOSInstanceName + ": No route to: " + alias + " / " + uuid + " from " + COOSInstanceName;
                    }
                }

                logger.warn(errorMsg);
                replyErrorReason(msg, Message.ERROR_NO_ROUTE);
            }
        }
    }

    /**
     * This method dynamically registers and unregisters aliases to link
     *
     * @param regAliases
     *            - An vector containing all aliases to be registered
     * @param outlink
     *            - The link to register the aliases with. This link is always
     *            directed towards an endpoint
     * @throws ProcessorException
     */
    @SuppressWarnings("unchecked")
	public void setLinkAliases(Vector regAliases, Link outlink) throws ProcessorException {
        String segment = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(outlink.getDestinationUuid());

        if (!segment.equals(".")) {
            segment += ".";
        }

        // Qualify aliases
        for (int i = 0; i < regAliases.size(); i++) {
            String alias = (String) regAliases.get(i);

            if (!alias.startsWith(Router.DICO_SEGMENT + ".") && !alias.startsWith(Router.LOCAL_SEGMENT + ".") && !alias.startsWith(segment)) {

                // unqualified aliases are qualified by prefixing with segment
                // name
                String qualifiedAlias = segment + alias;
                regAliases.remove(alias);
                regAliases.add(qualifiedAlias);
            }
        }

        Vector curAliases = outlink.getAlises();
        Iterator itCurAliases = curAliases.iterator();

        // remove aliases that are not present anymore
        while (itCurAliases.hasNext()) {
            String alias = (String) itCurAliases.next();

            if (!regAliases.contains(alias)) {
                itCurAliases.remove();
                removeAlias(alias);
            }
        }

        // Add all aliases
        Iterator itRegAliases = regAliases.iterator();

        while (itRegAliases.hasNext()) {
            String alias = (String) itRegAliases.next();
            outlink.addAlias(alias);

            String oldToUuid = aliasTable.get(alias);

            if ((oldToUuid != null) && !oldToUuid.equals(outlink.getDestinationUuid())) {
                Iterator itRegAliases2 = regAliases.iterator();

                while (itRegAliases2.hasNext()) {
                    removeAlias((String) itRegAliases2.next());
                }

                throw new ProcessorException("Can not register alias:" + alias + " since this alias is occupied for endpoint with uuid " +
                    outlink.getDestinationUuid());
            }

            putAlias(alias, outlink.getDestinationUuid());
        }
    }

    /**
     * This method resolves receiver URIs into uuids. It handles both URIs
     * containing aliases and uuids
     *
     * @param msg
     *            the message to resolve alias for
     * @return the uuid
     */
    public String resolveAlias(Message msg) {
        URIHelper helper = new URIHelper(msg.getReceiverEndpointUri());
        String uuid;
        String alias;
        alias = helper.getEndpoint();

        String segment;

        if ((alias != null) && !helper.isEndpointUuid()) {

            // routing on alias

            if (!helper.isEndpointQualified()) {

                // To account for that not all messages arrives the router via an
                // incoming link.
                // I.e. the routingInfo from this router
                if ((msg.getMessageContext().getInBoundLink() != null) && (msg.getMessageContext().getInBoundLink().getDestinationUuid() != null)) {
                    segment = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(msg.getMessageContext().getInBoundLink().getDestinationUuid());
                } else {
                    segment = ".";
                }

                if (!segment.equals(".")) {
                    segment += ".";
                }

                // the alias is unqualified, first try to route in segment
                // namespace
                String qualifiedAlias = segment + alias;

                uuid = aliasTable.get(qualifiedAlias);

                if (uuid == null) {

                    // If not found in segment namespace, then try to route in
                    // dico namespace
                    qualifiedAlias = DICO_SEGMENT + "." + alias;
                    uuid = aliasTable.get(qualifiedAlias);
                }
            } else {

                // If fully qualified alias then lookup in aliasTable
                uuid = aliasTable.get(alias);
            }

            if ((uuid == null) && !helper.getSegment().equals(Router.LOCAL_SEGMENT) && !helper.getSegment().equals(Router.DICO_SEGMENT)) {

                // we return with the segmented alias in order to allow for
                // routing on segments
                uuid = alias;
            }
        } else {
            uuid = alias;
        }

        return uuid;
    }

    /**
     * This is the core of the routing algorithm
     *
     */
    @SuppressWarnings("unchecked")
	public Link route(String uuid, Message msg, Map routingTable) {

        URIHelper helper = new URIHelper(msg.getSenderEndpointUri());

        if (msg.getMessageContext().getInBoundChannel() != null) {

            // Only populate routingtable with senderSegment/senderUuid if the
            // message enters the router through an incoming channel
            String destUuid = msg.getMessageContext().getInBoundLink().getDestinationUuid();
            String curSegment = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(destUuid);

            String senderEndpointUuid = helper.getEndpoint();
            String senderSegment = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(senderEndpointUuid);

            if (senderSegment.equals(curSegment)) {

                // If senderEndpointUuid belongs to the same segment as the
                // incoming channel
                // populate routingtable with senderUuid
                if (!routingTable.containsKey(senderEndpointUuid)) {
                    ((TimedConcurrentHashMap) routingTable).put(senderEndpointUuid, msg.getMessageContext().getInBoundChannel().getOutLink(),
                        linkTimeout, this);
                }
            } else {

                // If senderEndpointUuid not belongs to the same segment as the
                // incoming channel
                // populate routingtable with segment of the senderUuid
                if (!routingTable.containsKey(senderSegment)) {
                    ((TimedConcurrentHashMap) routingTable).put(senderSegment, msg.getMessageContext().getInBoundChannel().getOutLink(), linkTimeout,
                        this);
                }
            }
        }

        Link link = routingTable.get(uuid);

        // route down
        if (link == null) {
            String toSegment = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(uuid);
            Link inboundLink = msg.getMessageContext().getInBoundLink();

            if (inboundLink == null) {
                return null; // The message has not arrived this router through

                // an inboundLink. It is invalid and can not be
                // routed
            }

            String destUuid = inboundLink.getDestinationUuid();

            if (destUuid == null) {
                logger.warn(COOSInstanceName + ":destinationUuid is null on incoming link : " + inboundLink.getLinkId());
            }

            String curSegment = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(destUuid);

            if (!toSegment.equals(curSegment)) {

                // route down
                while (!toSegment.equals("")) {
                    link = routingTable.get(toSegment);

                    if (link != null) {
                        break;
                    } else {
                        toSegment = UuidHelper.getParentSegment(toSegment);
                    }
                }

                // route up
                /*if (link == null) {
                        if (curSegment != null) {
                                String parentSegment = UuidHelper.getParentSegment(curSegment);
                                if (parentSegment != null) {
                                        link = routingTable.get(parentSegment);
                                }
                        }
                }*/
            }
        }

        // route along defaultGw if set. Must be different from the incoming link
        if (link == null) {

            if ((defaultGw != null) && (defaultGw != msg.getMessageContext().getInBoundChannel().getOutLink())) {
                link = defaultGw;
            } else {

                if (defaultGw == null) {
                    logger.warn("Defaultgw is not set!");
                } else if (defaultGw == msg.getMessageContext().getInBoundChannel().getOutLink()) {
                    logger.warn("Incoming link is defaultgw!");
                }
            }
        }

        return link;
    }

    public void replyErrorReason(Message msg, String message) {

        // Only send error indication on type msg. i.e. from an endpoint
        if (msg.getHeader(Message.TYPE).equals(Message.TYPE_MSG)) {
            msg.setReceiverEndpointUri(msg.getSenderEndpointUri());
            msg.setHeader(Message.TYPE, Message.TYPE_ERROR);
            msg.setHeader(Message.HOPS, "1");
            msg.setHeader(Message.ERROR_REASON, message);
            msg.setHeader(Message.ERROR_CODE, "504");
            processMessage(msg);
        }
    }

    public Processor getDefaultProcessor() {
        return this;
    }

    /**
     * Adding a link to the router. Can either be a link to an endpoint/router
     * or a link to another segment
     *
     * @param routerUuid
     * @param link
     * @throws ConnectingException
     */
    public void addLink(String routerUuid, Link link) throws ConnectingException {

        if (UuidHelper.isUuid(routerUuid)) {
            // It is a router or endpoint

            String seg = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(routerUuid);
            RoutingAlgorithm algorithm = routingAlgorithms.get(seg);

            if (algorithm == null) {
                throw new ConnectingException("Router is not attached to segment: " + seg);
            }

            RouterSegment rs = segmentMapping.get(seg);
            rs.setTimestamp(0);

            link.setDestinationUuid(routerUuid);
            links.put(link.getLinkId(), link);

            if ((link.getChannel() != null) && link.getChannel().isDefaultGw()) {
                defaultGw = link;
                logger.debug("Setting defaultgw " + link);
            }

            algorithm.publishLink(link);
        } else {

            // it is a segment
            link.setDestinationUuid(routerUuid);
            links.put(link.getLinkId(), link);
            routingAlgorithms.get(routerUuid).publishLink(link);
        }

        logger.debug(getCOOSInstanceName() + ": Adding link: " + link);
    }

    public Link getLink(String destinationUuid) {

        if (destinationUuid != null) {

            for (Link link : links.values()) {

                if (link.getDestinationUuid().equals(destinationUuid)) {
                    return link;
                }
            }
        }

        return null;
    }

    public void removeLinkById(String linkId) {
        Link link = links.get(linkId);

        if (link != null) {
            publishAndCleanUpAfterLinkRemoval(link);
        }
    }

    public void removeLink(String destinationUuid) {

        for (Link link : links.values()) {

            if (link.getDestinationUuid().equals(destinationUuid)) {
                publishAndCleanUpAfterLinkRemoval(link);
            }
        }
    }


    private void publishAndCleanUpAfterLinkRemoval(Link link) {
        link.setCost(LinkCost.MAX_VALUE);
        routingAlgorithms.get(UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(link.getDestinationUuid())).publishLink(link);

        // remove from routing table can be done here.
        for (Map routingTable : routingTables.values()) {

            for (String uuidKey : routingTable.keySet()) {
                Link l = routingTable.get(uuidKey);

                if ((l != null) && l.equals((link))) {

                    //remove link to uuidKey
                    routingTable.remove(uuidKey);

                    //remove all aliases pointing at uuidKey
                    for (String aliasKey : aliasTable.keySet()) {
                        String uuid = aliasTable.get(aliasKey);

                        if (uuidKey.equals(uuid)) {
                            removeAlias(aliasKey);
                        }
                    }
                }
            }

            if (COOS != null)
                COOS.removeChannel(link.getDestinationUuid());
        }

        //Check if the destinationUuid was referenced in the alias table
        for (String aliasKey : aliasTable.keySet()) {
            String uuid = aliasTable.get(aliasKey);

            if (link.getDestinationUuid().equals(uuid)) {
                removeAlias(aliasKey);
            }
        }

        //Eventually remove the link
        if ((link.getChannel() != null) && !link.getChannel().isDefaultGw()) {
            links.remove(link.getLinkId());
        }
    }


    public void addQoSClass(String QoSClass, boolean isDefaultQoSClass) {
        this.QoSClasses.add(QoSClass);

        if ((defaultQoSClass == null) || isDefaultQoSClass) {
            defaultQoSClass = QoSClass;
        }

        // create routing tables
        if (routingTables.get(QoSClass) == null) {
            routingTables.put(QoSClass, new TimedConcurrentHashMap());
        }
    }

    public Collection getQoSClasses() {
        return this.QoSClasses;
    }

    public void addPreProcessor(RouterProcessor preProcessor) {
        preProcessor.setRouter(this);
        preProcessors.add(preProcessor);
    }

    public void addPostProcessor(RouterProcessor postProcessor) {
        postProcessor.setRouter(this);
        postProcessors.add(postProcessor);
    }

    public String getCOOSInstanceName() {
        return this.COOSInstanceName;
    }

    public void setCOOSInstanceName(String COOSInstanceName) {
        this.COOSInstanceName = COOSInstanceName;

    }

    public void setCOOS(COOS coos) {
        this.COOSInstanceName = coos.getName();
        this.COOS = coos;
    }

    public COOS getCOOS() {
        return COOS;
    }

    public void setSegmentMappings(Hashtable segmentMapping) {
        this.segmentMapping = new ConcurrentHashMap(segmentMapping);
    }

    public void addSegmentMapping(String segment, String routerUUID, String routerAlgorithm) {
        this.segmentMapping.put(segment, new RouterSegment(segment, routerUUID, routerAlgorithm, false));
    }

    public synchronized void addRoutingAlgorithm(String routerUuid, RoutingAlgorithm routingAlgorithm) {

        if (!UuidHelper.isRouterUuid(routerUuid)) {
            throw new IllegalArgumentException("Router uuid must start with prefix " + ROUTER_UUID_PREFIX);
        }

        Processor processor = null;

        this.routingAlgorithms.put(UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(routerUuid), routingAlgorithm);
        routerUuids.add(routerUuid);

        if (routerUuids.size() > 1) {

            for (String uuid : routerUuids) {

                if (!routerUuid.equals(uuid)) {
                    Link link = new Link(0);
                    link.addFilterProcessor(processor);
                    link.setChainedProcessor(this);

                    try {
                        addLink(UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(uuid), link);
                    } catch (Exception e) {
                        logger.error("Unknown Exception caught.", e);
                    }

                    link = new Link(0);
                    link.addFilterProcessor(processor);
                    link.setChainedProcessor(this);

                    try {
                        addLink(UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(routerUuid), link);
                    } catch (Exception e) {
                        logger.error("Unknown Exception caught.", e);
                    }
                }
            }
        }

        if (running) {

            try {
                routingAlgorithm.start();
            } catch (Exception e) {
                logger.error("Unknown Exception caught.", e);
            }
        }
    }

    /**
     * Takes care of updating
     */
    @SuppressWarnings("unchecked")
	private void aliasesUpdated() {

        // remove global aliases
        for (Link link : links.values()) {
            Collection aliases = link.getAlises();

            synchronized (aliases) {

                //Synchronizes on alias since concurrent access to this member can cause exceptions,
                //Can not use ConcurrentHashmap cause of java 1.3
                for (Iterator iterator = aliases.iterator(); iterator.hasNext();) {
                    String alias = (String) iterator.next();

                    if (alias.startsWith(Router.DICO_SEGMENT + ".") && !aliasTable.containsKey(alias)) {
                        iterator.remove();
                    }
                }
            }
        }

        // add global aliases in crossegment links
        for (String alias : aliasTable.keySet()) {

            if (alias.startsWith(Router.DICO_SEGMENT + ".")) {
                String aliasUuid = aliasTable.get(alias);
                String aliasSegment = UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(aliasUuid);

                for (Link link : links.values()) {
                    String segment = UuidHelper.getSegmentFromSegmentOrEndpointUuid(link.getDestinationUuid());

                    if (aliasSegment.equals(segment) && UuidHelper.isSegment(link.getDestinationUuid())) {
                        link.addAlias(alias);
                    }
                }
            }
        }
    }

    public String getDefaultQoSClass() {
        return defaultQoSClass;
    }

    public RoutingAlgorithm getRoutingAlgorithm(String segment) {
        return routingAlgorithms.get(segment);
    }

    public Map> getRoutingTables() {
        return routingTables;
    }

    public Map getRoutingTable(String qos) {
        return routingTables.get(qos);
    }

    public Map getLinks() {
        return links;
    }

    public Link getLinkById(String id) {

        return links.get(id);
    }

    public void start() throws Exception {

        String linkTimeoutStr = getProperty(LINK_TIMEOUT, LINK_TIMEOUT_DEFAULT);
        linkTimeout = 0;

        if (linkTimeoutStr != null) {
            linkTimeout = Integer.parseInt(linkTimeoutStr);
        }
        for (TimedConcurrentHashMap routingTable : routingTables.values()) {
            routingTable.start();
        }

        if (!running && enabled) {

            for (RoutingAlgorithm routingAlgorithm : routingAlgorithms.values()) {
                routingAlgorithm.start();
            }

            running = true;
        }
    }

    @SuppressWarnings("unchecked")
	public void stop() throws Exception {

        for (RoutingAlgorithm routingAlgorithm : routingAlgorithms.values()) {
            routingAlgorithm.stop();
        }

        for (TimedConcurrentHashMap routingTable : routingTables.values()) {
            routingTable.stop();
        }

        running = false;
    }

    public String toString() {
        return "Router " + COOSInstanceName;
    }

    public Map getAliasTable() {
        return aliasTable;
    }

    public void putAlias(String alias, String toUuid) {
        String oldToUuid = aliasTable.get(alias);

        if ((oldToUuid != null) && !oldToUuid.equals(toUuid)) {
            logger.warn("Possible alias conflict for alias: " + alias + ". Was pointing to : " + oldToUuid + ". Now pointing to :" + toUuid + ".");
        }

        aliasTable.put(alias, toUuid);
        aliasesUpdated();
    }

    public void removeAlias(String alias) {
        aliasTable.remove(alias);
        aliasesUpdated();
    }

    @Override public void addDynamicSegment(String segmentName, String routingAlg) throws ConnectingException {
        RoutingAlgorithm prototype = COOS.getRoutingAlgorithm(routingAlg);

        if (prototype == null) {
            throw new ConnectingException("Routingalgorithm: " + routingAlg + " not defined. Refusing dynamic segment allocation: " + segmentName);
        }

        RoutingAlgorithm algorithm = prototype.copy();
        UuidGenerator uuidGenerator = new UuidGenerator(ROUTER_UUID_PREFIX);
        String routerUuid = segmentName + "." + uuidGenerator.generateSanitizedId();
        segmentMapping.put(segmentName, new RouterSegment(segmentName, routerUuid, routingAlg, false, true));
        algorithm.init(routerUuid, this);
    }

    @Override public RouterSegment getSegment(String segmentName) {
        return segmentMapping.get(segmentName);
    }

    @Override public Map getSegmentMap() {
        return segmentMapping;
    }

    @Override public void removeSegment(String segmentName) {
        segmentMapping.remove(segmentName);
        routingAlgorithms.remove(segmentName);
        removeLink(segmentName);
    }

    public Link getDefaultGw() {
        return defaultGw;
    }

    @Override public boolean remove(Object key, TimedConcurrentHashMap routingTable) {
        Link link = (Link) routingTable.get(key);

        // not remove if default gw
        if ((link != null) && (link.getChannel() != null) && link.getChannel().isDefaultGw() && link.getDestinationUuid().equals(key)) {
            return false;
        }

        //remove alias for key
        for (String alias : aliasTable.keySet()) {

            if (aliasTable.get(alias).equals(key)) {
                aliasTable.remove(alias);
            }
        }

        return true;
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy