首页 > 代码库 > Floodlight中 处理packetin消息的顺序(2)

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对象是否存在
             ListenerDispatcher< OFTypeIOFMessageListener> ldd =
                 messageListeners.get(type);
             if (ldd == null ) {
                 ldd = new ListenerDispatcher< OFTypeIOFMessageListener>();
                 messageListeners.put(type, ldd);
             }
             //注册监听type这个消息;
             ldd.addListener(type, listener);
         }
--------------ListenerDispatcher实现(维护这些观察者,有依赖关系)

public class ListenerDispatcher <U, T 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