
org.coos.messaging.routing.SimpleDVAlgorithm 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.Link;
import org.coos.messaging.Message;
import org.coos.messaging.impl.DefaultMessage;
import org.coos.messaging.util.UuidHelper;
import java.util.Collection;
import java.util.HashMap;
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;
public class SimpleDVAlgorithm extends DefaultRoutingAlgorithm implements HashMapCallback {
public static final String ALG_NAME = "simpledv";
public static final String REFRESH_INTERVAL = "refreshInterval";
public static final String AGING_FACTOR = "agingFactor";
private Timer timer;
private int refreshInterval = 100; // Default value
private int agingFactor = 5; // Default value
public SimpleDVAlgorithm() {
}
public SimpleDVAlgorithm(Router router, String routerUuid) {
init(routerUuid, router);
}
@Override public void init(String routerUuid, Router router) {
// Setting the refreshinterval property
String refIntvStr = properties.get(REFRESH_INTERVAL);
if (refIntvStr != null) {
refreshInterval = Integer.parseInt(refIntvStr);
}
//Setting the aging factor property
String agefactStr = properties.get(AGING_FACTOR);
if (agefactStr != null) {
agingFactor = Integer.parseInt(agefactStr);
}
super.init(routerUuid, router);
}
@SuppressWarnings("unchecked")
public void processRoutingInfo(Message routingInfo) {
Vector linkCosts = (Vector) routingInfo.getBody();
String s = "";
for (Map routingTable : routingTables.values()) {
for (int i = 0; i < linkCosts.size(); i++) {
LinkCost linkCost = (LinkCost) linkCosts.elementAt(i);
s += linkCost.getFromUuid() + "<->" + linkCost.getToUuid() + ": " +
linkCost.getCost(Link.DEFAULT_QOS_CLASS) + ": " + linkCost.getAliases() + ", ";
if (routingInfo.getMessageContext().getInBoundChannel() != null) {
//It is remote routingInfo
String toUuid = linkCost.getToUuid();
Link link = routingInfo.getMessageContext().getInBoundChannel().getOutLink();
if (linkCost.getCost(Link.DEFAULT_QOS_CLASS) < LinkCost.MAX_VALUE) {
((TimedConcurrentHashMap) routingTable).put(toUuid, link,
agingFactor * refreshInterval, this);
List aliases = linkCost.getAliases();
for (String alias : aliases) {
router.putAlias(alias, toUuid);
}
}
} else {
//It is local routingInfo
String toUuid = linkCost.getToUuid();
Link link = links.get(linkCost.getLinkId());
if ((linkCost.getCost(Link.DEFAULT_QOS_CLASS) < LinkCost.MAX_VALUE) &&
(link != null)) {
((TimedConcurrentHashMap) routingTable).put(toUuid, link,
agingFactor * refreshInterval, this);
List aliases = linkCost.getAliases();
for (String alias : aliases) {
router.putAlias(alias, toUuid);
}
}
}
}
}
logger.trace("Receiving on " + router.getCOOSInstanceName() + ", from " +
routingInfo.getSenderEndpointUri() + " linkinfo: " + s);
if (loggingEnabled) {
for (String qos : routingTables.keySet()) {
printRoutingTable(routerUuid, qos, routingTables.get(qos), logger);
}
printAliasTable(routerUuid, aliasTable, logger);
}
}
@SuppressWarnings("unchecked")
public void publishLink(Link link) {
//from the local node
List links = new LinkedList();
links.add(link);
Iterator iter = routingTables.keySet().iterator();
while (iter.hasNext()) {
String qos = iter.next();
TimedConcurrentHashMap routingTable = routingTables.get(qos);
if (link.getCost() < LinkCost.MAX_VALUE) {
routingTable.put(link.getDestinationUuid(), link, agingFactor * refreshInterval,
this);
//This approach by broadcasting every new connection results in more traffic than
//handling it on a scheduled basis. However, it might not be a problem.
//In case of very fast reconnection with same UUID it may be a problem with
//the strategy of broadcast for every link that is added. The new link will be added before
//the old is removed and hence a problem may occur.
//broadcastRoutingInfo(routingTable);
}
}
}
private void broadcastRoutingInfo(Map routingTable) {
try {
String s = "";
for (Link link : routingTable.values()) {
s += link.getDestinationUuid() + ": " + link.getAlises() + ", ";
}
// Send routinginfo to all router elements in routing table
Set uuids = new HashSet();
// Get routing table entries for all qos parameters
for (Link link : routingTable.values()) {
if ((link.getChannel() != null) && !link.getChannel().isReceiveRoutingInfo()) {
continue;
}
uuids.add(link.getDestinationUuid());
}
for (String uuid : uuids) {
// Only sending routerinfo to neighbour routers
if (UuidHelper.getSegmentFromEndpointNameOrEndpointUuid(uuid).equals(segment) &&
UuidHelper.isRouterUuid(uuid)) {
sendRouterInfo(uuid, constructRoutingInfo(uuid, routingTable));
logger.trace("RouterInfo from: " + router.getCOOSInstanceName() + ", to:" +
uuid + ":: " + s);
}
}
// Send info to self
sendRouterInfo(routerUuid, constructLocalRoutingInfo(links.values()));
} catch (Exception e) {
logger.error("Exception ignored.", e);
}
}
@SuppressWarnings("unchecked")
private Vector constructRoutingInfo(String receivingRouterUuid,
Map routingTable) {
Vector routingInfo = new Vector();
for (String uuid : routingTable.keySet()) {
Link link = routingTable.get(uuid);
String uuidSegment = UuidHelper.getSegmentFromSegmentOrEndpointUuid(uuid);
Vector broadCastAliases = new Vector();
Map aliasTable = router.getAliasTable();
for (String alias1 : aliasTable.keySet()) {
String uuid1 = aliasTable.get(alias1);
//Do not propagate localcoos aliases to other coos nodes
if (!alias1.startsWith(Router.LOCAL_SEGMENT) && uuid.equals(uuid1)) {
broadCastAliases.add(alias1);
}
}
if (uuidSegment.equals(segment) && !UuidHelper.isSegment(uuid) &&
!link.equals(routingTable.get(receivingRouterUuid))) {
//The endpoints belonging to the router in the segment except from localcoos
routingInfo.addElement(new LinkCost(routerUuid, uuid, link.getLinkId(),
link.getCostMap(), broadCastAliases));
} else if (UuidHelper.isSegment(uuid) && !uuidSegment.equals(segment) &&
UuidHelper.isInParentChildRelation(uuidSegment,
UuidHelper.getSegmentFromSegmentOrEndpointUuid(receivingRouterUuid))) {
//Other segments
routingInfo.addElement(new LinkCost(routerUuid, uuid, link.getLinkId(),
link.getCostMap(), link.getAlises()));
}
}
routingInfo.addElement(new LinkCost(routerUuid, routerUuid, null,
new HashMap(), new Vector()));
return routingInfo;
}
@SuppressWarnings("unchecked")
private Vector constructLocalRoutingInfo(Collection links) {
Vector routingInfoLocal = new Vector();
for (Link link : links) {
String uuid = link.getDestinationUuid();
String uuidSegment = UuidHelper.getSegmentFromSegmentOrEndpointUuid(uuid);
if (uuidSegment.equals(segment) && !UuidHelper.isSegment(uuid)) {
routingInfoLocal.addElement(new LinkCost(routerUuid, uuid, link.getLinkId(),
link.getCostMap(), link.getAlises()));
} else if (UuidHelper.isSegment(uuid) && !uuidSegment.equals(segment)) {
// Aliases are not part of cross segment linkcost to gateway
// (local) topology map.
// Aliases in cross segment linkcosts pointing at other
// segment must not be added since this is where dico
// aliases pointing
// to uuids in own segment is located
routingInfoLocal.addElement(new LinkCost(routerUuid, uuid, link.getLinkId(),
link.getCostMap(), null));
}
}
return routingInfoLocal;
}
private void sendRouterInfo(String uuid, Vector routingInfo) {
try {
DefaultMessage msg = new DefaultMessage();
msg.setReceiverEndpointUri("coos://" + uuid);
msg.setSenderEndpointUri("coos://" + routerUuid);
msg.setHeader(Message.SERIALIZATION_METHOD, Message.SERIALIZATION_METHOD_JAVA);
msg.setHeader(Message.TYPE, Message.TYPE_ROUTING_INFO);
msg.setBody(routingInfo);
router.processMessage(msg);
} catch (Exception e) {
logger.error("Exception ignored.", e);
}
}
private void broadcastRoutingInfoAndSchedule() {
broadcastRoutingInfo(routingTables.get(Link.DEFAULT_QOS_CLASS));
try {
timer.schedule(new TimerTask() {
@Override public void run() {
broadcastRoutingInfoAndSchedule();
}
}, refreshInterval);
} catch (IllegalStateException e) {
// Nothing to be done. This situation occures when the timer is
// cancelled in the stop routine
// and the broadcastRoutingInfoAndSchedule is started. I.e. the
// routing algorithm is about to stop.
}
}
public void start() {
timer = new Timer("SimpleDVTimer", true);
broadcastRoutingInfoAndSchedule();
}
public void stop() throws Exception {
if (timer != null) {
timer.cancel();
}
}
public boolean remove(Object key, TimedConcurrentHashMap, ?> routingTable) {
Link link = (Link) routingTable.get(key);
if ((link != null) && (link.getChannel() != null) && link.getChannel().isDefaultGw() &&
link.getDestinationUuid().equals(key)) {
return false;
}
for (String alias : aliasTable.keySet()) {
if (aliasTable.get(alias).equals(key)) {
aliasTable.remove(alias);
}
}
return true;
}
public String getAlgorithmName() {
return ALG_NAME;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy