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

前面通过阅读代码知道了怎样推断各个模块处理某个消息的先后顺序。那么内部是怎样实现的呢?

每当一个模块表示对一个消息感兴趣的时候,就会调用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 ;

}

}

数据结构关联图:

转载注明出处:http://blog.csdn.net/vonzhoufz/article/details/34449315

时间: 2024-12-21 00:30:56

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

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

当Controller和SW建立连接之后,就可以处理来自SW的各种OF msg.当接收到 packetin 消息之后,会将其分发给各个监听了这个OFMessage的listeners,所以如果我们要设计自己的控制器模块,只需要实现相应的接口方法,约定执行顺序即可.接口IListener 主要抽象了监听器模块的名字,执行顺序,接口IOFMessageListener则抽象了我们的Controller如何处理具体的这个openflow消息.这里通过阅读代码来判断这些模块处理packetin消息的相对

Floodlight 中创建消息对象的方法

在 floodlight 中创建各种openflow message 和 action 等采用的是简单工厂方式,BasicFactory类(实现OFMessageFactory接口,)会根据消息的类型创建不同的对象,达到更好的封装效果:此外这里调用的是枚举类型的方法.下面是具体代码: ----------工厂接口,还有OFActionFactory,约束需要具体工厂完成的事情 public interface OFMessageFactory { // 根据消息类型得到具体的实例 public 

MFC应用程序中处理消息的顺序

应用程序处理消息的过程: 1.AfxWndProc()        该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc()  该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,然后调用WindowProc()函数 3.WindowProc()       该函数负责发送消息到OnWndMsg()函数,如果未被处理,则调用DefWindowProc()函数 4.OnWndMsg()         该

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

转自: http://www.infoq.com/cn/articles/high-availability-broker-design?utm_source=tuicool&utm_medium=referral 在要求严格顺序消息的场景下,消息的发送者,BROKER端(BROKER端和消息存储放在一起),消息的消费者都要求按照顺序进行,三者任何一个环节的乱序都会导致消息最终的消费顺序被打乱. 如果为每一个消息维护一个有序的ID,发送和存储消息无序,消费逻辑会变得非常复杂,消费端要对消息进行重

MFC窗口的消息响应顺序

最开始的消息传递 1.AfxWndProc() 该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc() 该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,然后调用WindowProc()函数 3.WindowProc() 该函数负责发送消息到OnWndMsg()函数,如果未被处理,则调用DefWindowProc()函数 4.OnWndMsg() 该函数的功能首先按字节对消息进行排序,对于WM_COM

MQ如何解决消息的顺序问题和消息的重复问题?

一.摘要 分布式消息系统作为实现分布式系统可扩展.可伸缩性的关键组件,需要具有高吞吐量.高可用等特点.而谈到消息系统的设计,就回避不了两个问题: 1.消息的顺序问题 2.消息的重复问题 二.关键特性以及其实现原理 2.1.顺序消息 要实现严格的顺序消息,简单且可行的办法就是: 保证生产者 - MQServer - 消费者是一对一对一的关系 这样的设计虽然简单易行,但也会存在一些很严重的问题,比如: 1.并行度就会成为消息系统的瓶颈(吞吐量不够) 2.更多的异常处理,比如:只要消费端出现问题,就会

如何保证消息的顺序性

1.面试官心里分析 其实这个也是用MQ的时候必问的话题,第一看看你了解不了解顺序这个事儿?第二看看你有没有办法保证消息是有顺序的?这个生产系统中常见的问题. 2.面试题剖析 我举个例子,我们以前做过一个mysql binlog同步的系统,压力还是非常大的,日同步数据要达到上亿.mysql -> mysql,常见的一点在于说大数据team,就需要同步一个mysql库过来,对公司的业务系统的数据做各种复杂的操作. 你在mysql里增删改一条数据,对应出来了增删改3条binlog,接着这三条binlo

阿里Java面试题剖析:在高并发的情况下如何保证消息的顺序性?

面试原题 如何保证消息的顺序性? 面试官心理分析 其实这个也是用 MQ 的时候必问的话题,第一看看你了不了解顺序这个事儿?第二看看你有没有办法保证消息是有顺序的?这是生产系统中常见的问题. 面试题剖析 我举个例子,我们以前做过一个 mysql binlog 同步的系统,压力还是非常大的,日同步数据要达到上亿,就是说数据从一个 mysql 库原封不动地同步到另一个 mysql 库里面去(mysql -> mysql).常见的一点在于说比如大数据 team,就需要同步一个 mysql 库过来,对公司

Win32编程中如何处理控制台消息

这篇文章讨论如何处理所有的控制台消息. 第一步,首先要安装一个事件钩子,也就是说要建立一个回调函数.调用Win32 API,原型如下: BOOL SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, // 回调函数BOOL Add // 表示添加还是删除): 参数HandlerRoutine是一个指向函数的指针,原型如下: BOOL WINAPI HandlerRoutine(DWORD dwCtrlType // 控制事件类型): 所有的