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

    http://www.online-tech-tips.com/windows-10/download-windows-10-spotlight-lock-screen-images/ 图片位置 C: ...

  2. 14.mocha+should.js

    转自http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html 众所周知对于任何一个项目来说,做好单元测试都是必不 ...

  3. MySql-Error: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

    MySql-Error: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) 标签( ...

  4. 什么是MySQL?(一)

    课程大纲 第一章:初识MySQL 1.1什么是MySQL?  1.2如何安装MySQL?  1.3如何配置MySQL?  1.4如何启动和关闭MySQL?  1.5MySQL的登录和退出  1.6如何 ...

  5. HBase的体系结构

  6. js实现图片上传后即时预览

    //关于FileReader对象 http://blog.csdn.net/zk437092645/article/details/8745647 <!DOCTYPE html> < ...

  7. UI Framework-1: Aura Event Handling

    Event Handling A diagram of the architecture of this system:     HWNDMessageHandler owns the WNDPROC ...

  8. 运维派 企业面试题1 监控MySQL主从同步是否异常

    Linux运维必会的实战编程笔试题(19题) 企业面试题1:(生产实战案例):监控MySQL主从同步是否异常,如果异常,则发送短信或者邮件给管理员.提示:如果没主从同步环境,可以用下面文本放到文件里读 ...

  9. WHU 1548 Home 2-SAT

    ---恢复内容开始--- 题意: N个人想回家在至少一个时刻.至多两个时刻.并且,他们每个人都能独自回家. 定义:ai表示第i个人回家的时间, xij = abs(ai - aj) (i != j). ...

  10. 使用glPushMatrix和glPopMatrix的原因

    转自 百度百科   glPushMatrix 函数将当前矩阵堆栈推送,通过一个,复制当前矩阵. 这就是后 glPushMatrix 的调用堆栈的顶部矩阵是它下面的相同的.   1. 原理讲解 终于明白 ...