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

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

The 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 org.coos.messaging.util.Log;
import org.coos.messaging.util.LogFactory;
import org.coos.messaging.util.UuidHelper;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author Knut Eilif Husa, Tellu AS
 *
 * Topology map of the COOS network
 */
public class TopologyMap {

    private final String routerUuid;
    private final Map curLinkCosts = new ConcurrentHashMap();
    private final List listeners = new LinkedList();
    private long notificationInterval = 200;
    private long maxAge = 200;
    private Timer timer;
    private boolean dirty = false;

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

    public TopologyMap(String routerUri) {
        this.routerUuid = routerUri;
    }

    public TopologyMap(String routerUuid, long notificationInterval, long maxAge) {
        this.routerUuid = routerUuid;
        this.notificationInterval = notificationInterval;
        this.maxAge = maxAge;
    }

    public void update(Vector linkCosts) {
        // Todo optimize serialization of linkCosts
        // System.out.println("Updating topology map router: " + routerUri);

        for (int i = 0; i < linkCosts.size(); i++) {
            LinkCost linkCost = linkCosts.elementAt(i);

            LinkCost currentCost = curLinkCosts.get(linkCost.getKey());

            if (currentCost != null) {

                if (!linkCost.getLinkId().equals(currentCost.getLinkId())) {

                    // New link
                    LinkCost lc = new LinkCost(linkCost);
                    this.curLinkCosts.put(linkCost.getKey(), lc);

                    //logger.trace("New Link: " + linkCost.getKey() + " caused topologymap change.");
                    dirty = true;
                } else {

                    // check change in cost to trigger a recalculation of
                    // optimal paths
                    for (String qos : currentCost.getQoSClasses()) {
                        int curCost = currentCost.getCost(qos);
                        int candCost = linkCost.getCost(qos);

                        if (curCost != candCost) {

                            //logger.trace("Link: " + linkCost.getKey() + " caused topologymap change," +
                            //              "current cost: "+curCost + ", candidate cost: "+candCost);
                            dirty = true;

                            break;
                        }
                    }

                    for (String qos : linkCost.getQoSClasses()) {

                        // check change in cost
                        int curCost = currentCost.getCost(qos);
                        int candCost = linkCost.getCost(qos);

                        if (curCost != candCost) {

                            //logger.trace("Link: " + linkCost.getKey() + " caused topologymap change," +
                            //              "current cost: "+curCost + ", candidate cost: "+candCost);
                            dirty = true;

                            break;
                        }
                    }

                    // check change in alias to trigger a recalculation of
                    // optimal paths
                    // Not necessary, but else we need to call a separate
                    // interface to deal with this
                    for (String alias : currentCost.getAliases()) {

                        if (!linkCost.getAliases().contains(alias)) {

                            //logger.trace("Link: " + linkCost.getKey() + " caused topologymap change," +
                            //              "new alias: "+alias);
                            dirty = true;

                            break;
                        }
                    }

                    for (String alias : linkCost.getAliases()) {

                        if (!currentCost.getAliases().contains(alias)) {

                            //logger.trace("Link: " + linkCost.getKey() + " caused topologymap change," +
                            //              "new alias: "+alias);
                            dirty = true;

                            break;
                        }
                    }

                    LinkCost lc = new LinkCost(linkCost);
                    this.curLinkCosts.put(linkCost.getKey(), lc);

                }

            } else {
                LinkCost lc = new LinkCost(linkCost);
                this.curLinkCosts.put(linkCost.getKey(), lc);
                dirty = true;
            }
        }

        if (dirty) {

            // Call listeners
            for (int j = 0; j < listeners.size(); j++) {
                TopologyMapListener listener = listeners.get(j);
                listener.notifyChanged(TopologyMap.this);
            }

            // remove infinitePaths after listeners have had a chance to react
            // on infinite path links
            Iterator iter = curLinkCosts.values().iterator();

            while (iter.hasNext()) {
                LinkCost linkCost = iter.next();

                if (!linkCost.isLink()) {
                    logger.trace("Removing link: " + linkCost.getKey() + " from topologyMap");
                    iter.remove();
                }
            }

            dirty = false;
        }

    }

    public void update(LinkCost linkCost) {
        Vector arg = new Vector();
        arg.addElement(linkCost);
        update(arg);
    }

    public List getAliases(String uuid) {
        List res = new LinkedList();

        for (LinkCost lc : curLinkCosts.values()) {

            if (lc.getToUuid().equals(uuid) && !lc.getAliases().isEmpty()) {
                res.addAll(lc.getAliases());
            }
        }

        return res;
    }

    public void addListener(TopologyMapListener listener) {
        listeners.add(listener);
    }

    public void removeListener(TopologyMapListener listener) {
        listeners.add(listener);
    }

    public String getRouterUuid() {
        return routerUuid;
    }

    public boolean isNeighbourNode(String uuid) {
        return isNeighbourNode(routerUuid, uuid);

    }

    public boolean isNeighbourNode(String fromUuid, String toUuid) {
        StringBuffer buf = new StringBuffer();
        buf.append(fromUuid);
        buf.append(",");
        buf.append(toUuid);

        return curLinkCosts.get(buf.toString()) != null;
    }

    public Set getNodeUuids() {

        // return new HashSet(nodeUris);
        HashSet nodeUuid = new HashSet();

        for (LinkCost lc : curLinkCosts.values()) {
            nodeUuid.add(lc.getFromUuid());
            nodeUuid.add(lc.getToUuid());
        }

        return nodeUuid;
    }

    public LinkCost getLinkCost(String fromUuid, String toUuid) {
        StringBuffer buf = new StringBuffer();
        buf.append(fromUuid);
        buf.append(",");
        buf.append(toUuid);

        LinkCost lc = curLinkCosts.get(buf.toString());

        if (lc != null) {
            return lc;
        } else {
            return new LinkCost(fromUuid, toUuid, "-1", LinkCost.MAX_VALUE);
        }
    }

    public LinkCost getLinkCost(String toUuid) {
        return getLinkCost(routerUuid, toUuid);
    }

    public void start() {
        timer = new Timer("TopologyMapTimer", true);
        timer.schedule(new NotificationTask(), 0, notificationInterval);
    }

    public void stop() {

        if (timer != null) {
            timer.cancel();
        }
    }

    public boolean isEmpty() {

        for (LinkCost linkCost : curLinkCosts.values()) {

            if (UuidHelper.isUuid(linkCost.getToUuid())) {
                return false;
            }
        }

        return true;
    }

    private class NotificationTask extends TimerTask {

        @Override public void run() {

            // Check for aging
            for (LinkCost linkCost : curLinkCosts.values()) {
                long now = System.currentTimeMillis();

                if ((linkCost.getTimeStamp() + maxAge) < now) {
                    linkCost.setLink(false);
                    dirty = true;
                    logger.trace("Link: " + linkCost.getKey() + " expired");
                }
            }

        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy