我倾向于把事情简单化,Nox的运行基本上涵盖了如下几个过程:
1、openflow协议报文交互
2、处理逻辑以及事件生成
3、事件分发及应用回调处理
4、应用管理与部署
把Nox说得更简单点就是:生产事件-->消费事件。至于如何生产,如何消费则是进一步需要细化了解的地方。
运行过程的总结中“事件分发”衔接了协议报文交互与应用逻辑,是Nox的核心之一,这次先打通“事件分发”这一脉。
下图是实现一个简单的事件分发组件的模型:
事件分发在整个应用中只需要一个对象来完成,因此,Nox实现了一个单态的event dispatcher,其内部主要维护了如上模型图中的三样东西。event dispather是事件的消费者,所有的事件都交给他来处理。
打个比方吧,event dispatcher就如同银行,总部制定了银行可以从事的各项业务(Application),并规定了各业务该如何办理,要填哪些表格,要做哪些记录,分发出去卡、还是凭证、还是一个U盾等等吧,银行的业务人员(线程)只需要按照这个规程进行办事就可以了。当然,银行最先需要的就是开个店面(init),还要有熟悉规程的业务人员(工作线程),这样,我们才可以去银行办理各种业务(事件,当然,这里的比喻还是有差别的,event dispatcher的事件可以激活一系列的业务的处理函数),办理业务的人多了,就需要排队(post到任务队列),直到叫到你的号的时候,才能真正开始办理(回调处理);如果你是个VIP,恭喜你,你立马就能办理业务了(dispatch调用)。
1、组件定义: 下面是Event_dispatcher类的一个实现示例
// event_dispatcher.hh
class Event_dispatcher
{
public:
static Event_dispatcher *get_instance();
static void init();
void start();
void shutdown();
void register_handler(const Event_name& event_name,
const Event_handler& handler,
int order);
void post(const Event& event);
void dispatch(const Event& event) const;
boost::asio::io_service& get_io_service();
private:
typedef std::multiset<Event_handler_wrapper> Call_chain;
typedef boost::unordered_map<Event_name, Call_chain> Call_chain_map;
static Event_dispatcher *event_dispatcher;
Event_dispatcher();
void _create_work_thread();
/* the io_service object and work */
boost::asio::io_service io;
boost::asio::io_service::work work;
/* number of threads to spawn */
size_t n_threads; // 暂未使用
boost::thread_group tg;
Call_chain_map call_chain_map;
};
// event_dispatcher.cc
Event_dispatcher *Event_dispatcher::event_dispatcher = NULL;
void Event_dispatcher::init()
{
printf("### Event_dispatcher: init ... \n");
if (!event_dispatcher)
{
event_dispatcher = new Event_dispatcher();
}
}
void Event_dispatcher::start()
{
tg.join_all();
}
void Event_dispatcher::shutdown()
{
io.stop();
}
void Event_dispatcher::register_handler(const Event_name& event_name,
const Event_handler& handler,
int order)
{
printf("### Event_dispatcher: Registering event '%s' handler by order %d.\n",
event_name.c_str(), order);
Event_handler_wrapper ehw(handler, order);
call_chain_map[event_name].insert(ehw);
}
void Event_dispatcher::post(const Event& event)
{
printf("### Event_dispatcher: post event ... \n");
io.post(boost::bind(&Event_dispatcher::dispatch, this, boost::cref(event)));
}
void Event_dispatcher::dispatch(const Event& event) const
{
printf("### Event_dispatcher: dispatch ... \n");
const Event_name& event_name = event.get_name();
Call_chain_map::const_iterator it = call_chain_map.find(event_name);
if (it != call_chain_map.end())
{
const Call_chain& call_chain = it->second;
BOOST_FOREACH(const Event_handler_wrapper& ehw, call_chain)
{
try
{
printf("### Event_dispatcher: dispatch event %s ........ \n", event.get_name().c_str());
if (ehw(event) == STOP)
{
break;
}
}
catch (const std::exception& e)
{
break;
}
}
}
}
boost::asio::io_service& Event_dispatcher::get_io_service()
{
return io;
}
Event_dispatcher *Event_dispatcher::get_instance()
{
return Event_dispatcher::event_dispatcher;
}
void Event_dispatcher::_create_work_thread()
{
printf("### Event_dispatcher: creating thread ... \n");
tg.create_thread(boost::bind(&boost::asio::io_service::run, &io));
}
Event_dispatcher::Event_dispatcher()
: io(), work(io)
{
printf("### Event_dispatcher: constructor ... \n");
_create_work_thread();
}
// event_handler_wrapper.cc 辅助类定义
typedef boost::function<Event_handler_signature> Event_handler;
class Event_handler_wrapper
{
public:
Event_handler_wrapper(const Event_handler& eh, int p)
: event_handler(eh), priority(p)
{
}
bool operator<(const Event_handler_wrapper& that) const
{
return priority < that.priority;
}
Disposition operator()(const Event& event) const
{
assert(!event_handler.empty());
return event_handler(event);
}
private:
Event_handler event_handler;
int priority;
};
2、组件使用: 下面开始是完成一个shutdown事件的相关代码
// event.hh
typedef std::string Event_name;
class Event
{
public:
virtual ~Event() {}
Event_name get_name() const { return name; }
protected:
Event(const Event_name& name_) : name(name_) {}
//void set_name(const Event_name& name_) { name = name_; }
private:
const Event_name name;
};
// shutdown_event.hh
class Shutdown_event : public Event
{
public:
Shutdown_event() : Event(static_get_name()) { }
static const Event_name static_get_name()
{
return "Shutdown_event";
}
};
void register_shutdown();
// shutdown_event.cc
static boost::function<void()> post_shutdown;
static void _signal_to_shutdown(int param)
{
printf("### shutdown event: post shutdown event on signal %d.\n", param);
post_shutdown();
}
static Disposition _shutdown_handler(Event_dispatcher *event_dispatcher,
const Event& event)
{
printf("### handle shutting down event.\n");
event_dispatcher->shutdown();
return CONTINUE;
}
static void _register_shutdown_signal()
{
signal(SIGTERM, _signal_to_shutdown);
signal(SIGINT, _signal_to_shutdown);
signal(SIGHUP, _signal_to_shutdown);
signal(SIGABRT, _signal_to_shutdown);
}
void register_shutdown()
{
Event_dispatcher *event_dispatcher = Event_dispatcher::get_instance();
event_dispatcher->register_handler(Shutdown_event::static_get_name(),
boost::bind(&_shutdown_handler, event_dispatcher, _1),
9999);
post_shutdown = boost::bind(&Event_dispatcher::post, event_dispatcher, Shutdown_event());
_register_shutdown_signal();
}
3、展示: 下面是修改main函数中的代码,编译执行
// main.cc修改的部分
int main(int argc, char *argv[])
{
_show_welcome(argv[0]);
Event_dispatcher::init();
register_shutdown();
Event_dispatcher::get_instance()->start();
return 0;
}
编译执行结果如下:
root@ubuntu:/home/y09002/My-Nox# make all
g++ -g -rdynamic -lboost_system -lboost_thread\
main.cc event_dispatcher/event_dispatcher.cc event/shutdown_event.cc -o My_Nox
root@ubuntu:/home/y09002/My-Nox# ./My_Nox
################### Welcome to use My_Nox! ###################
### Event_dispatcher: init ...
### Event_dispatcher: constructor ...
### Event_dispatcher: creating thread ...
### Event_dispatcher: Registering event 'Shutdown_event' handler by order 9999.
^C### shutdown event: post shutdown event on signal 2.
### Event_dispatcher: post event ...
### Event_dispatcher: dispatch ...
### Event_dispatcher: dispatch event Shutdown_event ........
### handle shutting down event.
按下ctrl+c之后,看到post了shutdown事件,然后dispatch了,最后habdle了。不过shutdown事件演示的跟Nox的实现稍微有所差别,我也没有把Event_dispatcher类归属于Nox实现中所说的Component类,毕竟Event_dispatcher真有必要统一抽象成Component,然后放在kernel中与其他Component一样管理吗,而且有Component_context的必要么?不纳入Component的继承层次也许是更好的选择。