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赞赏
微信赞赏
支付宝赞赏