前面通过阅读代码知道了怎样推断各个模块处理某个消息的先后顺序。那么内部是怎样实现的呢?
     每当一个模块表示对一个消息感兴趣的时候,就会调用IFloodlightProviderService(详细有Controller类实现)的addOFMessageListener方法进行注冊订阅,核心工作是由 ListenerDispatcher类来完毕:1)每次添加一个观察者的时候都会推断其是否是终结点(也就是不被其它的listener所依赖),由于终于确定这些观察者顺序的时候就是由这些终结点開始往前进行DFS遍历而得到。2)比方说ForwardingBase和Distributing
(我们自己加的。没有约束其顺序)。当它们注冊packetin消息的时候。会增加到终结点集合terminals中。所以从它们開始深度遍历的时候得到的有序集合ordering=linkdiscovery,topology,devicemanager, forwarding, distributing(这里进行了两次DFS traverse)。接下来看代码:

-------------Controller中实现IFloodlightProviderService的方法
            @Override
         public synchronized void addOFMessageListener(OFType type,
                                                       IOFMessageListener listener)
{
                //先推断与type相应的 ListenerDispatcher对象是否存在
             ListenerDispatcherOFTypeIOFMessageListener>
ldd =
                 messageListeners.get(type);
             if (ldd
== null ) {
                 ldd = new ListenerDispatcherOFTypeIOFMessageListener>();
                 messageListeners.put(type, ldd);
             }
             //注冊监听type这个消息。
             ldd.addListener(type, listener);
         }
--------------ListenerDispatcher实现(维护这些观察者,有依赖关系)

public class ListenerDispatcher <U,
extends IListener<U>>
{
    protected static Logger logger = LoggerFactory.getLogger(ListenerDispatcher. class );
    List<T> listeners = null;
    //每一个OF msg都有唯一的ListenerDispatcher对象。观察者存在listeners链表中
   
    //从listener这个观察者開始,根据有没有监听者在他之前,进行深度优先遍历
    //终于有序序列存在ordering中。visited用于存已经訪问过的terminal
listener。
    private void visit(List<T>
newlisteners, U type, HashSet<T> visited,
                       List<T> ordering,
T listener) {
        if (!visited.contains(listener))
{
            visited.add(listener);
           
            for (T
i : newlisteners) {
                if (ispre(type,
i, listener)) {
                    visit(newlisteners, type, visited, ordering, i);
                }
            }
           ordering.add(listener);
        }
    }
   
    //推断观察者l1
是否在 l2 之前(每一个观察者实现了IListener接口)
    private boolean ispre(U
type, T l1, T l2) {
        return (l2.isCallbackOrderingPrereq(type,
l1.getName()) ||
                l1.isCallbackOrderingPostreq(type, l2.getName()));
    }
   
    //订阅type消息。
    public void addListener(U
type, T listener) {
        List<T> newlisteners = new ArrayList<T>();
        if (listeners != null)
            newlisteners.addAll( listeners );

        newlisteners.add(listener);
        //
Find nodes without outgoing edges
        List<T> terminals = new ArrayList<T>();
        for (T
i : newlisteners) {
            boolean isterm
true;
            for (T
j : newlisteners) {
                if (ispre(type,
i, j)) {
                    isterm = false ;
                    break ;
                }
            }
            if (isterm)
{
                terminals.add(i); //维护终节点集合
            }
        }
       
        if (terminals.size()
== 0) {
            logger .error("No
listener dependency solution: " +
                        "No
listeners without incoming dependencies");
            listeners =
newlisteners;
            return ;
        }
       
        //接下来得到有序的listeners;
        //
visit depth-first traversing in the opposite order from
        //
the dependencies.  Note we will not generally detect cycles
        HashSet<T> visited = new HashSet<T>();
        List<T> ordering = new ArrayList <T>();
        for (T
term : terminals) {
            visit(newlisteners, type, visited, ordering, term);
        }
        listeners =
ordering;
    }

    //观察者退出。为何不直接remove??
    public void removeListener(T
listener) {
        if (listeners != null)
{
            List<T> newlisteners = new ArrayList<T>();
            newlisteners.addAll( listeners );
            newlisteners.remove(listener);
            listeners =
newlisteners;
        }
    }
   
    //清除全部listeners;
    public void clearListeners()
{
        listeners = new ArrayList<T>();
    }
   
    //
    public List<T>
getOrderedListeners() {
        return listeners ;
    }
}


数据结构关联图:



















Floodlight中 处理packetin消息的顺序(2)的更多相关文章

  1. Floodlight中 处理packetin消息的顺序(1)

    当Controller和SW建立连接之后,就能够处理来自SW的各种OF msg.当接收到 packetin 消息之后,会将其分发给各个监听了这个OFMessage的listeners,所以假设我们要设 ...

  2. Floodlight 中创建消息对象的方法

            在 floodlight 中创建各种openflow message 和 action 等採用的是简单工厂方式.BasicFactory类(实现OFMessageFactory接口.) ...

  3. UML中的图的出现顺序

    上接:UML从需求到设计--用例 从开始接触UML到现在对UML逐渐有了更深入的了解.刚开始,对于UML总是感觉UML就是图.一提起UML 就想着这个是画图的东西. 具体这些图都是干什么的.为什么会有 ...

  4. WM_QUIT,WM_CLOSE,WM_DESTROY 消息出现顺序及调用方式

    http://bbs.ednchina.com/BLOG_ARTICLE_3005455.HTM VC中WM_CLOSE.WM_DESTROY.WM_QUIT消息出现顺序及调用方式 wxleasyla ...

  5. rocketmq总结(消息的顺序、重复、事务、消费模式)

    rocketmq总结(消息的顺序.重复.事务.消费模式) 参考: http://www.cnblogs.com/wxd0108/p/6038543.html https://www.cnblogs.c ...

  6. 高可用保证消息绝对顺序消费的BROKER设计方案

    转自: http://www.infoq.com/cn/articles/high-availability-broker-design?utm_source=tuicool&utm_medi ...

  7. 分布式开放消息系统RocketMQ的原理与实践(消息的顺序问题、重复问题、可靠消息/事务消息)

    备注:1.如果您此前未接触过RocketMQ,请先阅读附录部分,以便了解RocketMQ的整体架构和相关术语2.文中的MQServer与Broker表示同一概念 分布式消息系统作为实现分布式系统可扩展 ...

  8. 分布式消息队列RocketMQ&Kafka -- 消息的“顺序消费”

    在说到消息中间件的时候,我们通常都会谈到一个特性:消息的顺序消费问题.这个问题看起来很简单:Producer发送消息1, 2, 3... Consumer按1, 2, 3...顺序消费. 但实际情况却 ...

  9. MQ如何解决消息的顺序性

    一.消息的顺序性 1.延迟队列:设置一个全局变量index,根据实际情况一次按照index++的逻辑一次给消息队列设置延迟时间段,可以是0.5s,甚至1s; 弊端:如果A,B,C..消息队列消费时间不 ...

随机推荐

  1. [NOIP2015模拟10.27] 挑竹签 解题报告(拓扑排序)

    Description 挑竹签——小时候的游戏夏夜,早苗和诹访子在月光下玩起了挑竹签这一经典的游戏.挑竹签,就是在桌上摆上一把竹签,每次从最上层挑走一根竹签.如果动了其他的竹签,就要换对手来挑.在所有 ...

  2. [NOIP2015模拟10.22] 最小代价 解题报告 (最小生成树)

    Description 给出一幅由n个点m条边构成的无向带权图.其中有些点是黑点,其他点是白点.现在每个白点都要与他距离最近的黑点通过最短路连接(如果有很多个黑点,可以选取其中任意一个),我们想要使得 ...

  3. 9-第一个app项目

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  4. Java类和对象11

    首先,编写一个类ChongZai,该类中有3个重载的方法void print():其次,再编写一个主类来测试ChongZai类的功能. public class ChongZai { public v ...

  5. 基于jquery 的find()函数和children()函数的区别

    element.find(selector)  返回匹配element集合中每个元素的后代,参数selector是必须的,可以通过选择器对元素进行过滤,筛选出符合条件的元素.如果想选中所有的后代元素, ...

  6. 51Nod 1010 只包含因子2 3 5的数(打表+二分)

    K的因子中只包含2 3 5.满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15. 所有这样的K组成了一个序列S,现在给出一个数n,求S中 >= 给定数的最小的数. 例如:n = ...

  7. 文本域内容在div中带换行显示

    function ReplaceSeperator(mobiles) { var i; var result = ""; var c; for (i = 0; i < mob ...

  8. JAVA程序类加载及其反射机制

    [IT168 技术]当调用java命令运行某个Java程序时,该命令将启动一条Java虚拟机进程,同一个JVM的所有线程,所有变量都处于同一进程里,它们都是用该JVM进程的内存区. 程序运行到最后正常 ...

  9. node使用express命令报错找不到ejs的解决方法

    首先确定已经全局安装过好几遍express和express-generator,但一使用express命令直接报找不到ejs模块,全局和本地安装ejs都没用,nodemon模块报同样错误,找不到deb ...

  10. Maven学习总结(21)——Maven常用的几个核心概念

    在使用Maven的过程中,经常会遇到几个核心的概念,准确的理解这些概念将会有莫大的帮助. 1. POM(Project Object Model)项目对象模型 POM 与 Java 代码实现了解耦,当 ...