Peersim.cdsim:
从类CDSimulator的函数nextExperiment()中可读出Cycle Driven Simulation是怎样执行的。首先是创建整个网络,相应的语句是Network.reset(),也就是创建了许多网络节点。接着是runInitializers(),也就是初始化。然后就是loadControls(),装载控制数组。
在Cycle Driven Simulation部分编程的核心就是实现inits[]和controls[]这两个数组。
注意到初始化数组inits[]和控制数组controls[]的每个元素的基类都是peersim.core.Control,可见对整个网络的控制都是有Control类的execute()函数来直接执行的。
Peersim.config:
两个主要的类是Configuration和ParsedProperties。Configuration类的构造函数是私有的,就是说这个类无法被构造,再者它的函数全部是静态函数,所以这个类只充当了一个函数包装袋的作用。——它把功能相关的函数集中放在了一起。ParseStream()两个函数完成了配置文件的阅读。
Peersim.core:
这是核心类库。里面的CommonState类维持了系统模拟时的一些全局变量,比如当前时间(time),当前节点(node),当前的protocol identifier(pid),当前的实验状态(phase)。
Network类负责创建整个网络,具体的说就是创建很多个网络节点。这个工作主要是由它的成员函数reset()完成的。这是一个静态类,构造函数是私有的。Network.reset()在每次实验中被调用且只被调用一次,调用者是CDSimulator.nextExperiment()或EDSimulator.nextExperiment()。Reset()函数其实只生成了一个节点,其他节点都是克隆的,也就是说这是一个同构网络;同时我们注意到,Node接口没有非静态的成员变量,也就是说无论这个网络中设置了多少个节点,所需占有的内存空间不变,而且很小——因为成员函数和静态数据成员在整个内存中只有一份拷贝。但是事实上,Network.reset()函数中并不是真的就用Node接口来创建了很多个节点——缺省情况下用GeneralNode类来生成第一个模版节点,配置文件中声明若干节点类,则以节点类来创建第一个模版节点。当然,之后还是会调用clone()类来生成其余节点。
再看GeneralNode类,这个类实现了接口Node,并作为缺省情况下的节点来使用——所以我们有理由相信这个类实现了peersim设计者脑中的节点所应当具备的特性。GeneralNode类的非静态数据成员有序数index,身份证号ID,和协议数组protocol[]。由于这些数据成员是非静态的,所以在实际模拟中,设用着设了多少个节点,相应的就会有多少个index,ID和数组protocol[]。
接下来的一个类就是ModifiableNode,这个类继承了GeneralNode类。如其名字所示,它是可被修改的节点,体现在其成员函数public void setProtocol(int pid, Protocolprot)。
与节点类ModifiableNode和GeneralNode有着很大关联的一个接口是Fallible——可以阵亡,在网络中表现为退出整个网络。
再看protocol接口,它是被放在容器(实现Node的类)中的。这个接口很简单,只有一个clone()函数。Protocol,也就是协议,是用来处理节点和节点之间的联系的,也就是负责路由的。
那么来看IdleProtocol类。IdleProtocol类中维持了一个非静态变量,即protocol Node[] neighbors,存储了与本节点邻接的节点。
Peersim.dynamics:
注意到这个类库中的很多类都继承自wireGraph这个抽象类,那么先从它开始看。
WireGraph抽象类定义了execute()函数,这个函数是用来调用wire()函数的。
在peersim.dynamics类库中,继承WireGraph的类包括WireByMethod,WireFormFile,WireKOut,WireRegRootedTree,WireRingLattice,WireScaleFreeBA,WireScaleFreeDM,wireStar,WireWS。这些类或是提供了一种连接网络的方案,或是将网络连接成某一种拓扑结构。
再看DynamicNetwrok类,实现了Control接口。这个类通过增加节点和移去节点来模拟网络的抖动。执行的函数是execute(),而它又调用了add()和remove()两个函数来做具体的增加和删除工作。
本类库中的另一个重要接口是NodeInitilizer,只包含一个函数,即publicvoid initialize(Node n)。这是针对某个节点的启动工作,留给后面的类来实现。
Peersim.edsim:
最重要的类是EDSimulator,也就是Events Driven Simulation的执行者,具体执行的函数是EDSimulator.nextExperiment()。总的来说,EventsDriven Simulation肯定是比Cycle Driven Simulation复杂一些。
其核心机制维持一个事件队列——这个队列以堆的形式存在,这涉及到本类库的接口PriorityQ和继承它的类heap。也就是说,实际中采用一个heap的对象来存放事件的队列。在模拟的过程中,不断地会有事件加入这个队列,也会不断的有事件被拿出队列来执行。结合nextExperiment()和executeNext()来看,模拟在两种情况下才会结束——一种是队列为空,也就是没有事件可以被执行;另一种是执行的总时间到了,也就是endtime到了。
再看nextExperiment()的具体执行流程。首先是创建整个网络,相应的语句是Network.reset(),也就是创建了很多个网络节点。接着是初始化那个堆heap,然后是runInitializers(),也就是几个inits[]数组中的几个control对象依次执行初始化。然后是scheduleControls()。
下面就是Event DrivenSimulation最核心的部分——队列操作。在这一步,不断的会有事件(Event)进入队列,也不断地有事件被取出队列来执行。
应该指出,peersim.core类库中有一个类是和edsim配合使用的,这个类是Scheduler,其中有几个参数分别叫from,step和until——这是一个计时用的类。里面用一个active()函数来反映有没有超时。