Module 是指繼承了 IFloodlightModule 接口的類服務器
IFloodlightModule的相關注釋ide
Defines an interface for loadable Floodlight modules. At a high level, these functions are called in the following order: getModuleServices() : 得到模塊實現的服務列表 getServiceImpls(); 實例化並返回:服務實現類-實現此服務的對象 映射 getModuleDependencies() : 得到模塊依賴的列表 init() : internal initializations (<em>don't</em> touch other modules) startUp() : external initializations (<em>do</em> touch other modules)
全部可加載的模塊都有這幾種方法,在接下來的加載模塊時須要使用到。
每一個具體的模塊都會重寫這幾個函數,下面舉個 FloodlightProvider 的例子。函數
@Override public Collection<Class<? extends IFloodlightService>> getModuleServices() { Collection<Class<? extends IFloodlightService>> services = new ArrayList<Class<? extends IFloodlightService>>(1); services.add(IFloodlightProviderService.class); return services; }
得到 FloodlightProvider 的服務 IFloodlightProviderServiceoop
@Override public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { controller = new Controller(); Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); m.put(IFloodlightProviderService.class, controller); return m; }
返回服務實現類和實現用的對象的Map。spa
@Override public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { Collection<Class<? extends IFloodlightService>> dependencies = new ArrayList<Class<? extends IFloodlightService>>(4); dependencies.add(IStorageSourceService.class); dependencies.add(IPktInProcessingTimeService.class); dependencies.add(IRestApiService.class); dependencies.add(IDebugCounterService.class); dependencies.add(IOFSwitchService.class); dependencies.add(IThreadPoolService.class); dependencies.add(ISyncService.class); return dependencies; }
返回依賴的列表命令行
init(),startup(),到對應的模塊去看就能夠了。
有的模塊是沒有服務依賴的,好比 ThreadPool模塊。debug
Service 是指繼承了 IFloodlightService 接口的類。code
public abstract interface IFloodlightService { // This space is intentionally left blank....don't touch it }
模塊使用getModuleServices()方法能夠得到對應的服務列表,能夠到源碼去看對應的服務功能。對象
CmdLineSetting 定義了命令行參數的格式繼承
public static final String DEFAULT_CONFIG_FILE = "src/main/resources/floodlightdefault.properties"; @Option(name="-cf", aliases="--configFile", metaVar="FILE", usage="Floodlight configuration file") private String configFile = DEFAULT_CONFIG_FILE;
若是沒有使用-cf指定配置文件路徑,則使用默認路徑「src/main/resources/floodlightdefault.properties」
CmdLineParser 解析命令參數
CmdLineParser parser = new CmdLineParser(settings) parser.parserArgument(args)
moduleContext=fml.loadModulesFromConfig(settings.getModuleFile())
settings.getModuleFile()提供配置文件的路徑
這個方法比較重要的是這個 ServiceLoader,返回服務加載器
ServiceLoader<IFloodlightModule> moduleLoader = ServiceLoader.load(IFloodlightModule.class, cl);
ServiceLoader 爲了註冊服務,須要在類路徑 src/main/resources/META_INF/services文件夾內列好註冊服務的模塊,能夠獲得繼承了 IFloodlightModule 接口的實現類
使用moduleLoader.iterator()迭代器去填充moduleNameMap,moduleServiceMap,ServiceMap
moduleNameMap 模塊名稱-模塊對象 Map
moduleServiceMAP 模塊名稱-模塊服務 Map
ServiceMap 模塊服務-模塊名稱 Map
取配置文件的一條參數配置net.floodlightcontroller.forwarding.Forwarding.match=in-port, vlan, mac, ip, transport舉例
key:net.floodlightcontroller.forwarding.Forwarding.match
String configKey=key.substring(LastPeriod+1)
獲到的就是 match,即 configKey=match
String systemKey = System.getProperty(key); if (systemKey != null) { configValue = systemKey; } else { configValue = prop.getProperty(key); }
若是系統屬性已經存在,則使用系統屬性的值,若是不存在,則configValue = prop.getProperty(key);【即 configValue 在此處爲in-port, vlan, mac, ip, transport】
FloodlightModuleLoader 類下的方法
public void addConfigParam(IFloodlightModule mod, String key, String value) { Map<String, String> moduleParams = configParams.get(mod.getClass()); if (moduleParams == null) { moduleParams = new HashMap<String, String>(); configParams.put(mod.getClass(), moduleParams); } moduleParams.put(key, value); }
得到模塊的服務實例
Map<Class<? extends IFloodlightService>, IFloodlightService> simpls = module.getServiceImpls();
添加服務到 floodlightModuleContext
if (floodlightModuleContext.getServiceImpl(s.getKey()) == null) { floodlightModuleContext.addService(s.getKey(), s.getValue());
遍歷已加載模塊集,開始初始化模塊,調用模塊的方法:init
for (IFloodlightModule module : moduleSet) { // init the module if (logger.isDebugEnabled()) { logger.debug("Initializing " + module.getClass().getCanonicalName()); } module.init(floodlightModuleContext); }
遍歷已加載模塊集,調用每一個模塊的啓動方法
for (IFloodlightModule m : moduleSet) { if (logger.isDebugEnabled()) { logger.debug("Starting " + m.getClass().getCanonicalName()); } m.startUp(floodlightModuleContext); }
返回公共環境變量
返回一個不可修改的已加載模塊序列,若是沒被初始化則返回 null
public List<IFloodlightModule> getModuleList() { if (loadedModuleList == null) return Collections.emptyList(); else return Collections.unmodifiableList(loadedModuleList); }
runModules()
for (IFloodlightModule m : getModuleList()) { for (Method method : m.getClass().getDeclaredMethods()) { Run runAnnotation = method.getAnnotation(Run.class); if (runAnnotation != null) { RunMethod runMethod = new RunMethod(m, method); if(runAnnotation.mainLoop()) { mainLoopMethods.add(runMethod); } else { runMethod.run(); } } } }
for 循環遍歷模塊中的方法,找到@run註解的方法爲主方法,如下的就是 FloodlightProvider 提供的 run 方法
@Run(mainLoop=true) public void run() throws FloodlightModuleException { controller.run(); }
運行控制器的模塊
mainLoopMethods.get(0).run();