The ONE目前支持两种消息队列:先进先出FIFO和随机。本文介绍与之相关的技术细节,以及介绍如何添加新的消息模式。
1. 消息发送队列模式
The ONE目前支持两种消息发送队列:先进先出FIFO和随机。
//MessageRouter.java
public static final int Q_MODE_RANDOM = 1;
public static final int Q_MODE_FIFO = 2;
可以在设置文件设置消息队列模式,若不设置,则默认为随机。
Group.sendQueue = 1 # 随机,默认
Group.sendQueue = 2 # 先来先到FIFO
值得注意的是,The ONE使用HashMap
组织消息,HashMap
是无序的,所以getMessageCollection()
取得的消息是无序的。如果消息要按某种排序(FIFO),需先换成实现List
接口的类存储,再调用sortByQueueMode
排序队列。使用方法如下:
//ActiveRouter.java的tryAllMessagesToAllConnections()
List<Message> messages = new ArrayList<Message>(this.getMessageCollection());
this.sortByQueueMode(messages);
getMessageCollection()
源代码如下:
//MessageRouter.java
private HashMap<String, Message> messages;
public Collection<Message> getMessageCollection() {
return this.messages.values();
}
2. 随机模式
随机器取决于当前仿真时钟,如果一个节点在update interval被更新多次,那么消息的顺序是一样的。相关源代码如下:
//MessageRouter.java
protected List sortByQueueMode(List list) {
switch (sendQueueMode) {
case Q_MODE_RANDOM:
Collections.shuffle(list, new Random(SimClock.getIntTime()));
break;
}
}
3. 先进先出
先接收到的消息在队头,后接收到的消息在队尾。支持两种List:Message
和Tuple<Message, Connection>
,源代码如下:
//MessageRouter.java
protected List sortByQueueMode(List list) {
switch (sendQueueMode) {
case Q_MODE_FIFO:
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
double diff;
Message m1, m2;
//Tuple<Message, Connection>
if (o1 instanceof Tuple) {
m1 = ((Tuple<Message, Connection>)o1).getKey();
m2 = ((Tuple<Message, Connection>)o2).getKey();
} else if (o1 instanceof Message) {
m1 = (Message)o1;
m2 = (Message)o2;
} else {
throw new SimError("Invalid type of objects in " + "the list");
}
diff = m1.getReceiveTime() - m2.getReceiveTime();
if (diff == 0) {
return 0;
}
return (diff < 0 ? -1 : 1);
}
});
break;
}
}
4. 新消息在队尾
对于FIFO,新产生的消息是在队头还是队尾?要回答这个问题,只需看新创建消息的成员变量timeReceived
被设成了什么,代码如下:
//Message.java
publi Message(DTNHost from, DTNHost to, String id, int size) {
...
this.timeCreated = SimClock.getTime();
this.timeReceived = this.timeCreated;
...
}
可见,新创建消息的timeReceived
被初始化成当前仿真时钟,所以新创建的消息被放在队尾。顺便提一下,判断一个消息是否新创建的方法如下:
if (m.getCreationTime() == m.getReceiveTime())
5. 添加新模式
理解了上面的内容,添加新的消息模式就很简单了,最主要是修改sortByQueueMode
和compareByQueueMode
。sortByQueueMode
对buffer的消息排序;compareByQueueMode(m1, m2)
比较两个消息谁在前面,返回-1
,m1
在前面;返回1
,m2
在前面;返回0
,则表示不确定。在MaxProp
、Prophet
都用到了这个函数。完整步骤如下:
//MessageRouter.java
//步骤1:添加静态变量
public static final int Q_MODE_FIFO_EXTEND = 3;
//步骤2:修改构造函数,sendQueueMode > 2更为3
public MessageRouter(Settings s) {
if (s.contains(SEND_QUEUE_MODE_S)) {
this.sendQueueMode = s.getInt(SEND_QUEUE_MODE_S);
if (sendQueueMode < 1 || sendQueueMode > 2) { //sendQueueMode > 3
throw new SettingsError("Invalid value for " + s.getFullPropertyName(SEND_QUEUE_MODE_S));
}
}
}
//步骤3:修改sortedQueueMode
protected List sortByQueueMode(List list) {
switch (sendQueueMode) {
case Q_MODE_FIFO_EXTEND:
...
break;
}
}
//步骤4:修改compareByQueueMode
protected int compareByQueueMode(Message m1, Message m2) {
switch (sendQueueMode) {
case Q_MODE_FIFO_EXTEND:
...
return ...;
}
}
//步骤5:在设置文件设置
Group.sendQueue = 3