这几天由于P2Psim的分析进度不是很快,所以一直也就没有更新分析笔记,希望大家见谅。在前几篇中,我已经大体介绍了P2Psim的初始化过程。对初始化的分析,到上篇就告一段落。由于我是一边分析一边写笔记,所以有些细节方面可能存在遗漏和错误。如果各位在自己的分析中发现,不妨联系我。在每篇笔记的图片中,有我的邮件地址的水印。
    接着之前的分析,本篇主要介绍了P2Psim的运行机制。这部分的理解,是以后用P2Psim来添加自己的p2p协议的基础。这篇的介绍不涉及太多细节,因为在我的分析中,发现Node类的实现中有太多的细节需要说。所以在这里我只是给大家一个总体的介绍。如果大家去做代码分析,我建议大家分析sillyprotocol,而不要一上手就去看Chord协议。我个人的感觉是,Chord协议涉及太多协议本身的机制,它的机制本身的复杂性,很大程度上会干扰大家对仿真中的消息机制的分析。而sillyprotocol几乎没有什么代码和任何协议机制。因此是一个很好的切入点。
   按照惯例,我给出了分析的简单图例。由于这图是用office的onenote画的,虽然画起来很方便,但是onenote的画图功能实在太弱了,所以不同意义的先只能用颜色区别,而无法用线形来区别,大家只能凑合着看了。
   图中左上角的EventQueue是我介绍的切入点。在之前,我介绍过,他的运行机制就是在不停的调用他的advance()函数从消息队列里面取出事件,然后每次取出消息就去kick一下消息发生器类EventGenerator,然后再对取出的每个event对象,调用其execute()函数来完成相应的操作。那么EventQueue中消息的来源主要是两个: EventGenerator类或其子类;和Node类。
   先看EventGenerator类。这个类在把自己注册到EventQueue实例里面的时候就把仿真结束消息(exit)和各个peer加入仿真的消息(join)加入了队列。前者是SimEvent类型的消息,后者是P2PEvent消息。SimEvent类型的消息只有一个用途,就是结束仿真。P2PEvent事件的用途就是通知各个peer在不同的时候做不同的事情,比如join,crash和lookup这些。不同于其他的仿真软件,如OverSim,P2Psim中P2PEvent事件是由EventGenerator做中心控制的,而不是由各个peer自己控制的。换而言之,EventGenrator控制了全体peer的行为模式。这点简化对于homegeneous的仿真而言是好的,写代码就容易多了。如果要做geterougenous的仿真就困难一点了,不过也不是大问题。
   第二个事件的发生源是Node类。Node类封装peer作为网络结点的角色。对上层p2p协议,Node提供了RPC调用接口。然后把对应的RPC请求和应答转换成网络报文的传输。在仿真中,报文的发送和接受都被转换成NetEvent网络事件。当Node要发网络数据包的时候,他就从Topology对象提供的接口计算出报文到达的延时,然后生成一个报文到达的NetSim事件,放到EventQueue里面,等待EventQueue到时候进行处理。
   介绍完事件的发生源,再说说事件的处理。之前说过,EventQueue在取出Event时候,会调用其execut函数来处理事件。对于不同类型的事件,其execute机制不同。 最简单的是SimEvent的,立刻就通知系统结束仿真了,具体代码各位自己去看。其次是P2PEvent。如果消息对于的操作是EventGenerator让peer join或者crash,他只是把protocol中对应的_alive进行置位和清位。如果是其他操作,如chord中的lookup,这类。他会对应找到protocol对象中的函数调用来完成处理。比如lookup事件, P2PEvent 就把Event中对应的node对象找出来,调用他的lookup()函数.
   如果处理的是NetEvent事件,它的execute会根据事件的类型进行区别对待。之前我提到,Node会把RPC操作转变为网络报文传输,因此NetEvent对应不同网络报文也分两类:请求和应答。如果这个事件对应的是请求,它就让系统为对应的接收结点生成一个新task来跑Node::receive()函数,让node来接收这个“网络数据包”。否则,他就把这个数据包发送到对应的channel去,让等待接收RPC回应的node的()来接收这个回应。
P2Psim分析笔记(6)- 仿真中的事件机制_第1张图片