Router Module analysis of ONE simulator

本文深入探讨了如何从Active Router类派生并重写update()和replicate()方法,以实现自定义的Direct Delivery Router。通过解析Direct Delivery Router的update()方法,我们了解了其在发送消息过程中的关键逻辑,包括检查当前是否正在传输、是否有可传递的消息等。同时,文章详细介绍了isTransferring()、canStartTransfer()、exchangeDeliverableMessages()等辅助方法的功能,以及如何确保路由系统高效地进行消息传递。

    If you want to compose your own routing module, you have to derive a new class from the ActiveRouter class and rewrite the update() method and probably the replicate() method too. In this article, we look into these two methods.

    Let's take the DirectDeliveryRouter for an example. The following snippet is the function body of its DirectDeliveryRouter::update() method.

 1     @Override
 2     public void update() {
 3         super.update();
 4         if (isTransferring() || !canStartTransfer()) {
 5             return// can't start a new transfer
 6         }
 7         
 8         // Try only the messages that can be delivered to final recipient
 9         if (exchangeDeliverableMessages() != null) {
10             return// started a transfer
11         }
12     }

    It firstly call the update method of is parent (ActiveRouter). Then if the router is transferring right now it just returns. Here is the ActiveRouter::isTransferring method:

 1 /**
 2      * Returns true if this router is transferring something at the moment or
 3      * some transfer has not been finalized.
 4      * @return true if this router is transferring something
 5      */
 6     public boolean isTransferring() {
 7         if (this.sendingConnections.size() > 0) {
 8             return true// sending something
 9         }
10         
11         if (this.getHost().getConnections().size() == 0) {
12             return false// not connected
13         }
14         
15         List<Connection> connections = getConnections();
16         for (int i=0, n=connections.size(); i<n; i++) {
17             Connection con = connections.get(i);
18             if (!con.isReadyForTransfer()) {
19                 return true;    // a connection isn't ready for new transfer(it's busy)
20             }
21         }
22         
23         return false;        

24     } 

The function Connection::isReadyForTransfer:

1 /**
2      * Returns true if the connection is ready to transfer a message (connection
3      * is up and there is no message being transferred).
4      * @return true if the connection is ready to transfer a message
5      */
6     public boolean isReadyForTransfer() {
7         return this.isUp && this.msgOnFly == null

8     } 

The function body of ActiveRouter::canStartTransfer is:

 1 /**
 2      * Makes rudimentary checks (that we have at least one message and one
 3      * connection) about can this router start transfer.
 4      * @return True if router can start transfer, false if not
 5      */
 6     protected boolean canStartTransfer() {
 7         if (this.getNrofMessages() == 0) {
 8             return false;
 9         }
10         if (this.getConnections().size() == 0) {
11             return false;
12         }
13         
14         return true;

15     } 

 

The function body of DirectDeliveryRouter::exchangeDeliverableMessages:

 1 /**
 2      * Exchanges deliverable (to final recipient) messages between this host
 3      * and all hosts this host is currently connected to. First all messages
 4      * from this host are checked and then all other hosts are asked for
 5      * messages to this host. If a transfer is started, the search ends.
 6      * @return A connection that started a transfer or null if no transfer
 7      * was started
 8      */
 9     protected Connection exchangeDeliverableMessages() {
10         List<Connection> connections = getConnections();
11 
12         if (connections.size() == 0) {
13             return null;
14         }
15         
16         @SuppressWarnings(value = "unchecked")
17         Tuple<Message, Connection> t =
18             tryMessagesForConnected(sortByQueueMode(getMessagesForConnected()));
19 
20         if (t != null) {
21             return t.getValue(); // started transfer
22         }
23         
24         // didn't start transfer to any node -> ask messages from connected
25         for (Connection con : connections) {
26             if (con.getOtherNode(getHost()).requestDeliverableMessages(con)) {
27                 return con;
28             }
29         }
30         
31         return null;

32     }

The function body of ActiveRouter::tryMessagesForConnected:

 1     /**
 2      * Tries to send messages for the connections that are mentioned
 3      * in the Tuples in the order they are in the list until one of
 4      * the connections starts transferring or all tuples have been tried.
 5      * @param tuples The tuples to try
 6      * @return The tuple whose connection accepted the message or null if
 7      * none of the connections accepted the message that was meant for them.
 8      */
 9     protected Tuple<Message, Connection> tryMessagesForConnected(
10             List<Tuple<Message, Connection>> tuples) {
11         if (tuples.size() == 0) {
12             return null;
13         }
14         
15         for (Tuple<Message, Connection> t : tuples) {
16             Message m = t.getKey();
17             Connection con = t.getValue();
18             if (startTransfer(m, con) == RCV_OK) {
19                 return t;
20             }
21         }
22         
23         return null;

24     } 

 The function body of MessageRouter::sortByQueueMode:

 1     /**
 2      * Sorts/shuffles the given list according to the current sending queue 
 3      * mode. The list can contain either Message or Tuple<Message, Connection> 
 4      * objects. Other objects cause error. 
 5      * @param list The list to sort or shuffle
 6      * @return The sorted/shuffled list
 7      */
 8     @SuppressWarnings(value = "unchecked"/* ugly way to make this generic */
 9     protected List sortByQueueMode(List list) {
10         switch (sendQueueMode) {
11         case Q_MODE_RANDOM:
12             Collections.shuffle(list, new Random(SimClock.getIntTime()));
13             break;
14         case Q_MODE_FIFO:
15             Collections.sort(list, 
16                     new Comparator() {
17                 /** Compares two tuples by their messages' receiving time */
18                 public int compare(Object o1, Object o2) {
19                     double diff;
20                     Message m1, m2;
21                     
22                     if (o1 instanceof Tuple) {
23                         m1 = ((Tuple<Message, Connection>)o1).getKey();
24                         m2 = ((Tuple<Message, Connection>)o2).getKey();
25                     }
26                     else if (o1 instanceof Message) {
27                         m1 = (Message)o1;
28                         m2 = (Message)o2;
29                     }
30                     else {
31                         throw new SimError("Invalid type of objects in " + 
32                                 "the list");
33                     }
34                     
35                     diff = m1.getReceiveTime() - m2.getReceiveTime();
36                     if (diff == 0) {
37                         return 0;
38                     }
39                     return (diff < 0 ? -1 : 1);
40                 }
41             });
42             break;
43         /* add more queue modes here */
44         default:
45             throw new SimError("Unknown queue mode " + sendQueueMode);
46         }
47         
48         return list;

49     }

The function body of ActiveRouter::getMessagesForConnected:

 1     /**
 2      * Returns a list of message-connections tuples of the messages whose
 3      * recipient is some host that we're connected to at the moment.
 4      * @return a list of message-connections tuples
 5      */
 6     protected List<Tuple<Message, Connection>> getMessagesForConnected() {
 7         if (getNrofMessages() == 0 || getConnections().size() == 0) {
 8             /* no messages -> empty list */
 9             return new ArrayList<Tuple<Message, Connection>>(0); 
10         }
11 
12         List<Tuple<Message, Connection>> forTuples = 
13             new ArrayList<Tuple<Message, Connection>>();
14         for (Message m : getMessageCollection()) {
15             for (Connection con : getConnections()) {
16                 DTNHost to = con.getOtherNode(getHost());
17                 if (m.getTo() == to) {
18                     forTuples.add(new Tuple<Message, Connection>(m,con));
19                 }
20             }
21         }
22         
23         return forTuples;

24     } 

The function body of MessageRouter::requestDeliverableMessages :

1     /**
2      * Requests for deliverable message from this router to be sent trough a
3      * connection.
4      * @param con The connection to send the messages trough
5      * @return True if this router started a transfer, false if not
6      */
7     public boolean requestDeliverableMessages(Connection con) {
8         return false// default behavior is to not start -- subclasses override

9     } 

转载于:https://www.cnblogs.com/jcleung/archive/2011/05/31/2064957.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值