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

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

/**
 * 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 java.util.*;
import java.util.concurrent.ConcurrentHashMap;

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

	private String routerUuid;
	private Map curLinkCosts = new ConcurrentHashMap();
	private List listeners = new LinkedList();
	private long notificationInterval = 200;
	private long maxAge = 200;
	private Timer timer = new 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 = (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);
					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) {
							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) {
							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)) {
							dirty = true;
							break;
						}
					}
					for (String alias : linkCost.getAliases()) {
						if (!currentCost.getAliases().contains(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();
		timer.schedule(new NotificationTask(), 0, notificationInterval);
	}

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

	private class NotificationTask extends TimerTask {

		public void run() {

			// Check for aging
			for (LinkCost linkCost : curLinkCosts.values()) {
				if (linkCost.getTimeStamp() + maxAge < System.currentTimeMillis()) {
					linkCost.setLink(false);
					dirty = true;
					logger.trace("Link: " + linkCost.getKey() + " expired");
				}
			}

		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy