前面通过阅读代码知道了怎样推断各个模块处理某个消息的先后顺序。那么内部是怎样实现的呢?
     每当一个模块表示对一个消息感兴趣的时候,就会调用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. vim 插件之supertab

    supertab.vim 这个插件是用来把tab键作为只能补全的映射,当然,具体更能肯定不仅仅只是如此,等待以后发现吧 地址 http://github.com/ervandew/supertab h ...

  2. hpuoj--校赛--考试来了(水题)

    问题 C: 感恩节KK专场--考试来了 时间限制: 1 Sec  内存限制: 128 MB 提交: 475  解决: 112 [提交][状态][讨论版] 题目描述 很多课程马上就结课了,随之而来的就是 ...

  3. rest_framework-认证-总结完结篇

    执行过程 APIView() Ruquest() Authentication() OrderView()APIView() def duspatch: self.initial(request) d ...

  4. Wow C++11

    什么是C++11? 一句话C++11是最新的C++标准,在2011年发布,所以叫C++11.在新的标准出现前,我们一直在用的是C++98,可想而知这份标准是1998年发布的,之后再2003年最过小的修 ...

  5. BZOJ 4552 排序 Heoi2016

    记得当年省选的时候 这道题连暴力都没写对(尴尬ing) (当年天真的认为sort是左闭右闭的hhhhhh) 思路: 首先 二分答案 线段树 首先二分答案,然后需要知道进行m次排序后p位置上的数字是否大 ...

  6. jquery的append/prepend和after/before有什么区别呢?

    append <p> <span class="s1">s1</span> </p> <script> $(" ...

  7. HD-ACM算法专攻系列(3)——Least Common Multiple

    题目描述: 源码: /**/ #include"iostream" using namespace std; int MinComMultiple(int n, int m) { ...

  8. E. Reachability from the Capital(tarjan+dfs)

    求联通分量个数,在dfs一次 #include <iostream> #include <algorithm> #include <cstring> #includ ...

  9. HDU 3342 Legal or Not(判断环)

    Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is so h ...

  10. PHP——下载图片到本地代码

    <?php //获取网页图片 $url = "http://qlogo2.store.qq.com/qzone/393183837/393183837/50"; $curl ...