/*
* @(#)LABELDecisionEngine.java
*
* Copyright 2010 by University of Pittsburgh, released under GPLv3.
*
*/
package routing.community;
import java.util.*;
import core.*;
import routing.*;
/**
*
Implements the LABEL routing protocol described in How Small Labels
* create Big Improvements by Pan Hui and Jon Crowcroft (2007). The authors
* found that, where nodes self describe their community with some text label,
* they are more likely to contact nodes with in their community. While the
* paper doesn't discuss a protocol that uses programmatic community detection
* techniques, other papers of the authors reference the idea (though do not
* specifically present it). Thus, this class is a bit of an extrapolation of
* their various works on the matter.
*
* The protocol has each node only forward message to members of the
* destination's community, i.e. at any given time, if a connected peer declares
* the destination of a message to be in its local community, then a node
* decides to transfer the message to that peer.
*
*
* \@inproceedings{4144796,
* Author = {Hui, Pan and Crowcroft, Jon},
* Doi = {10.1109/PERCOMW.2007.55},
* Journal = {Pervasive Computing and Communications Workshops, 2007. PerCom
* Workshops '07. Fifth Annual IEEE International Conference on},
* Month = {March},
* Pages = {65 -70},
* Title = {How Small Labels Create Big Improvements},
* Year = {2007}
* }
*
*
* @author PJ Dillon, University of Pittsburgh
*/
public class LABELDecisionEngine
implements RoutingDecisionEngine, CommunityDetectionEngine
{
/** Name corresponding to the community detection class to use in this router
*/
public static final String COMMUNITY_ALG_SETTING = "communityDetectAlg";
protected CommunityDetection community;
/**
* Records the times at which each open connection started. Used to compute
* the duration of each connection (needed by the community detection algs).
*/
protected Map startTimestamps;
/**
* A record of the entire connection history of this node for the whole
* simulation. As each connection goes down, a new entry is added into the
* list for the peer that just disconnected.
*/
protected Map> connHistory;
/**
* Initializes the decision engine using the given Settings object, extracting
* the class of community detection algorithm to use. This constructor does
* NOT create instances of the member fields since this constructor is
* generally only used to create a "prototype" object that each actual
* instance replicates.
*
* @param s Settings from which to get class name
*/
public LABELDecisionEngine(Settings s)
{
if(s.contains(COMMUNITY_ALG_SETTING))
this.community = (CommunityDetection)
s.createIntializedObject(s.getSetting(COMMUNITY_ALG_SETTING));
else
this.community = new SimpleCommunityDetection(s);
}
/**
* Initializes the LABEL decision engine to be a copy of the parameter
* decision engine.
*
* @param proto LABELDecisionEngine to copy
*/
public LABELDecisionEngine(LABELDecisionEngine proto)
{
this.community = proto.community.replicate();
startTimestamps = new HashMap();
connHistory = new HashMap>();
}
public void connectionUp(DTNHost thisHost, DTNHost peer){}
/**
* Records the duration of the lost connection and informs the Community
* Detection object that the connection was last.
*/
public void connectionDown(DTNHost thisHost, DTNHost peer)
{
double time = startTimestamps.get(peer);
double etime = SimClock.getTime();
// Find or create the connection history list
List history;
if(!connHistory.containsKey(peer))
{
history = new LinkedList();
connHistory.put(peer, history);
}
else
history = connHistory.get(peer);
// add the new connection to the history
if(etime - time > 0)
history.add(new Duration(time, etime));
// Inform the community detection object
CommunityDetection peerCD = this.getOtherDecisionEngine(peer).community;
community.connectionLost(thisHost, peer, peerCD, history);
startTimestamps.remove(peer);
}
/**
* Starts timing the duration of the new connection and informs the community
* detection object of the new connection.
*/
public void doExchangeForNewConnection(Connection con, DTNHost peer)
{
DTNHost myHost = con.getOtherNode(peer);
LABELDecisionEngine de = this.getOtherDecisionEngine(peer);
this.community.newConnection(myHost, peer, de.community);
this.startTimestamps.put(peer, SimClock.getTime());
de.startTimestamps.put(myHost, SimClock.getTime());
}
public boolean newMessage(Message m) {return true;}
public boolean isFinalDest(Message m, DTNHost aHost)
{return m.getTo() == aHost;} // Unicast Routings
public boolean shouldSaveReceivedMessage(Message m, DTNHost thisHost)
{return m.getTo() != thisHost;}
/**
* LABEL Routing works such that we only send the message to hosts in the same
* local community as the message's destination.
*/
public boolean shouldSendMessageToHost(Message m, DTNHost otherHost)
{
if(m.getTo() == otherHost) return true;
DTNHost dest = m.getTo();
LABELDecisionEngine de = getOtherDecisionEngine(otherHost);
return de.commumesWithHost(dest);
}
public boolean shouldDeleteSentMessage(Message m, DTNHost otherHost)
{
return !this.commumesWithHost(m.getTo());
}
public boolean shouldDeleteOldMessage(Message m, DTNHost hostReportingOld)
{
return true;
}
public RoutingDecisionEngine replicate()
{
return new LABELDecisionEngine(this);
}
protected boolean commumesWithHost(DTNHost h)
{
return community.isHostInCommunity(h);
}
private LABELDecisionEngine getOtherDecisionEngine(DTNHost h)
{
MessageRouter otherRouter = h.getRouter();
assert otherRouter instanceof DecisionEngineRouter :
"This router only works with other routers of same type";
return (LABELDecisionEngine) ((DecisionEngineRouter)otherRouter)
.getDecisionEngine();
}
public Set getLocalCommunity()
{
return this.community.getLocalCommunity();
}
}