码农学ODL之Toaster代码解析

Toaster(烤面包机)是OpenDaylight的一个例子,该例子的目的不是让你如何烤面包,而是借这个例子学习OpenDaylight的特性。在Toaster中,真正有关烤面包机相关的代码较少,它只是一种OpenDaylight具体思想的展示品,很多情况没有进行考虑。本文将通过烤面包机这个实例来初步探讨OpenDaylight技术的基本思想。

1.Toaster的需求规格

首先,我们来看下烤面包机要实现的需求是什么,从面向对象的角度来考虑,烤面包机做为一个物理实体,它具有生产厂商、型号和面包机状态等相关属性;同时,它也表现出烤面包、取消烤面包、面包机重置等行为,并且当面包机检测到某种情况时,也会发出通知。其详细信息如下:

2.基本实现

面对烤面包机的需求,我们先尝试着去设计一个小熊牌的烤面包机,Toaster类定义烤面包机的属性,可以使用POJO(Plain Old Java Object)定义方式;ToasterService定义烤面包机的行为;BearToaster为小熊烤面包机的具体实现,当其检测到无面包可烤的情况时,会通知Human子类Boy or Girl,client在调用代码构建BearToaster和Human子类对象,其类关系图如下所示:

上图只是简单地设计,考虑到可扩展性、可维护性等因素,至少还需要进一步考虑:如何构造烤面包机对象、如何进行事件的通知以及服务依赖关系如何设置等问题。带着这些问题,我们看下OpenDaylight中是如何实现的?

3.ODL实现

3.1.Yang基础

Yang是一种专门针对NETCONF而设计的建模语言,使用树形结构描述数据,具有良好的可读性,具有数据描述和接口描述两种功能。其基本信息如下所示:

更详细的Yang信息,请参考http://www.sdnlab.com/resource/12292.html。

在OpenDaylight中,Yang也被用作一个通用建模语言。Yang文件有两种格式,一种是来定义数据和接口,另一种是定义依赖注入、启动配置等信息。在Toaster实例中,这两种格式的文件分别体现为toaster.yang和toaster-provider-impl.yang。

3.2.Toaster数据模型

3.2.1.Yang数据模型定义

Toaster的Yang建模文件toaster.yang位于toaster/api/src/main/yang/目录下,用于表示Toaster的对外接口以及数据结构,其内容框架如下图所示:

3.2.2.Yang模型代码生成

Yang文件定义好后,我们可以使用Yang Tools进行Yang语法解析、语义模型以及Java文件的映射,这样做可以极大地提高了编程效率。下面我们来分析下Yang 与Java文件之间的映射关系,toaster.yang生成的代码文件如下所示:

首先,来看下包路径的映射关系,toaster.yang文件中定义信息如下:

所以,从定义来看,包路径的映射关系如下:

其次,用来描述数据的Container标识映射到ToasterData.java;用来定义RPC方法的RPC标识映射为ToasterService.java;用来描述异步通知方法的notification标识映射为ToasterListener.java。它们的映射关系如下图所示:

RPC操作和Notification异步通知各自对应接口文件,文件内包含对应相应的方法,如ToasterService文件定义如下,比较简单。

再次,我们来详细说明如何来构造烤面包机的数据?Yang Tools根据Container生成类或接口文件ToasterData、Toaster和ToasterBuilder,其中ToasterData、Toaster是接口类,而ToasterBuilder为具体实例的建造者。其类关系图如下所示:

通俗一点来解释,客户小A想要一台烤面包机(小熊牌、型号R7等),便找ToasterBuilder,让其帮忙构建一台烤面包机,此时ToasterBuilder为难了,因为其只能构建一些零件,不掌握整装技术,怎么办呢?找整装设计师吧,于是ToasterImpl产生了,告诉ToasterBuilder如何一步一步去完成,ToasterBuilder和ToasterImpl相互配合就构建出了小A的烤面包机。

最后,通过上面的分析,我们可以更详细地得到Yang Tools将Yang文件映射为Java文件的关系图,如下所示:

3.3.Toaster的代码实现

从Toaster.yang模型生成的代码可以看出,当前已经定义如何构建Toaster数据以及相关的操作接口,下面我们来看下如何实现一个烤面包机? 在OpenDaylight中,定义了一个品牌为OpenDaylight的烤面包机,它实现了ToasterService、DataChangeListener、AutoCloseable等接口,类关系图大致如下所示:

其中,OpenDaylightToaster类本身定义如下:

在这里,我们主要关注buildToaster、makeToast和onDataChanged三个方法。

1.Toaster的构建方法buildToaster

buildToaster的实现是基于Yang Tools生成的Java类,如下所示:

2. 烤面包makeToast

首先我们来看下,makeToast方法的基本实现逻辑,如下图所示:

首先,读取烤面包机的状态。在OpenDaylight中,所有数据都保存在DataStore中,并且数据以树形结构存储,而DataBroker是访问MD-SAL数据存储的接口,它提供了3种访问方式只读、只写和读写,分别对应newReadOnlyTransaction、newWriteOnlyTransaction和newReadWriteTransaction,具体代码如下所示:

其中TOASTER_IID定义为InstanceIdentifier类型,作为Toaster的实例标识符,表示Toaster在Yang数据树中的位置的唯一标识符,Futures.transform方法返回一个新的ListenableFuture,该值是在参数readFuture 的基础上进行asynFunc 处理后产生的结果。

其次,修改Toaster为工作状态。tx.put方法第一个参数为OPERATIONAL,代表DataStore中存储的数据类型;第三个参数为设置Toaster工作状态为down,具体代码如下:

再次,从状态判断到烤面包或者重试或者报错的过程,使用异步调用的方式,形如:

最后,Task任务进行面包的烘烤,烤面包的代码仅仅进行sleep一段时间。如果遇到outOfBread时,则会发送相应的通知。具体代码如下:

3.onDataChanged通知方法

Toaster中所有的数据都存储在DataStore,当DataStore中的数据发生变化时会通过DataChangeListener触发事件通知,事件通知需要做的事情放在onDataChange方法中实现。具体代码逻辑比较简单,首先获取数据对象,如果该数据对象是Toaster,那么进行一些简单的赋值操作,具体实现如下:

3.4.Toaster服务的Yang配置

到目前为止,已经对烤面包机的数据及接口进行了定义,并实现了品牌为OpenDaylight的烤面包机。这样,如何通过调用接口就能访问OpenDaylight烤面包机的方法,进一步说,我们知道OpenDaylightToaster是基于MD-SAL实现的,那如何使得OpenDaylightToaster与MD-SAL关联起来呢?我们知道,几乎所有的应用程序都必须读取一些配置信息,这些信息通常是通过配置文件来完成的,比如XML或properties文件。对于像OpenDaylight运行于OSGI平台上的应用程序,依赖于哪些包或者服务,以及这些依赖是必须的还是可选的,这些信息都是非常关键的。

这涉及到Config Subsystem,它通过YANG模型来表达Module(模块)配置、依赖和状态数据,具体来说就是通过yang schema来定义配置信息,具体依赖值由config.xml提供,在Toaster实例中toaster-provider-impl.yang和03-toaster-sample.xml。

首先,我们来看下toaster-provider-impl.yang文件的定义,通过import引入依赖模块;通过identity指定Toaster模块标识;通过augment增加类型为toaster-provider-impl的可选节点。

上述Yang文件映射为Java类,需要关注ToasterProviderModule和ToasterProviderModuleFactory,前者的createInstance方法可用来实现OpendaylightToaster实例,后者被MD-SAL调用 ,实例化ToasterProviderModule。下图列出createInstance方法的实现细节,红色部分进行OpenDaylightToaster实例的构建及其对依赖的获取。

其次,我们再来看下03-toaster-sample.xml文件,具体内容如下:

在之间,定义toaster-provider-impl模块和它所需的依赖配置(toaster-provider-impl.yang)。

至此,有关一个原始的OpenDaylightToaster就可以了,当然了,真正测试时,你还需要修改feature.xml和pom.xml,然后进行编译、打包。

原文发布于微信公众号 - SDNLAB(SDNLAB)

原文发表时间:2016-09-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏十月梦想

php代码之网站显示安全运行时间代码

上述就可实现网站计时功能,结合数组函数实现,后续可是使用js获取倒计时,时时显示!

1202
来自专栏人人都是极客

环形缓冲区的实现

队列 (Queue):是一种先进先出(First In First Out ,简称 FIFO)的线性表,只允许在一端插入(入队),在另一端进行删除(出队)。

2574
来自专栏逍遥剑客的游戏开发

MPQ 文件系统完成

1894
来自专栏小灰灰

Quick-Task 动态脚本支持框架之Groovy脚本加载执行

上一篇简答说了如何判断有任务动态添加、删除或更新,归于一点就是监听文件的变化,判断目录下的Groovy文件是否有新增删除和改变,从而判定是否有任务的变更;

1031
来自专栏深度学习那些事儿

提升python项目完成效率的调试方法技巧(上)

效率提升是极为重要的事情,我们的时间本来就不充裕,不应该过多将时间浪费在调试过程中。对于大型项目光有dubug是不够的,如果需要提高产品调试进度,必须需要采取一...

3927
来自专栏吉浦迅科技

在cuda的核函数中可以按地址调用普通变量么?

请问在cuda的核函数中可以按地址调用普通变量么? GPU世界论坛 bbs.gpuworld.cn Hi, 楼主, 完全无问题,从Fermi起引入卡内统...

3777
来自专栏吉浦迅科技

DAY20:阅读Surface Memory

2132
来自专栏calmound

知识点提纲

操作系统: 1. 进程的有哪几种状态,状态转换图,及导致转换的事件。 2. 进程与线程的区别。 3. 进程通信的几种方式。 4. 线程同步几种方式。(一定要会写...

3558
来自专栏生信技能树

rMATS这款差异可变剪切分析软件的使用体验

rMATS最近刚现在出了rMATS 4.0.1版,相比之间的rMATS 3.2.5版,其用C,Python,Cython重写了该软件,运算速度提升了100倍,并...

9454
来自专栏Crossin的编程教室

【每周一坑】螺旋矩阵

今天这题,看起来挺简单,实际写出来并不容易。在以前公司我曾把它做过招聘的笔试题,结果惨不忍睹,不得不拿掉。 输出如图的螺旋矩阵: 1 2 3 4...

3637

扫码关注云+社区

领取腾讯云代金券