本篇筆記,主要是跟蹤taskmain()函數中EventGenerateor::parse(event_file)。本篇主要涉及EventGenerator的構造流程,其中對churnEventGenerator類和ChornObserver類進行分析。下面的圖示給出了EventGenerateor::parse()函數的調用流程。
圖中EventGenerateor::parse()的調用很簡單,首先讀取eventfile 裡面關于eventgenerator和observer的名字。生成了一個generator執行個體,然後通過thread()把對應的eventgenerator的任務個激活。最後再生成observer執行個體。這裡我分析了ChurnEventGenerator 和ChurnObserver兩個類。按照我的了解Generator主要用于生成對應protocol的node的初始化事件,比如node什麼時候開始活過來,以及對eventqueue類執行個體化和進行激活等操作。observer 的設計本意是用來統計和記錄仿真中的各個事件。在P2Psim的設計中,observer的執行個體化中,observer把自己注冊到各個node對象中,這樣每次node發消息的時候,在消息隊列處理消息的時候,都會把這個消息上的observer拿出來,調用一下他們的kick()來修改observer中的統計資訊。
圖中,首先EventGenerator::parse()調用工廠模式生成了eventgenerator執行個體。我們以churnEventGenerator為例。churnEventGenerator在構造對象的時候,首先讀取了所需的參數。圖中列出了所有參數,這些參數的具體用途以後再分析(目前我也不清楚,呵呵)。然後執行個體化了消息隊列,并把自己注冊為消息隊列的observer,這是一個特殊的observer(具體的用途目前也不清楚,估計是每次消息隊列處理消息的時候,都能被調用一次)。
在消息隊列的執行個體化中,消息隊列eventqueue,建立了一個特别的channel,然後就調用自己的thread()觸發了run()函數變成一個并發任務。run函數首先會在這個channel上等待一個go消息(這個消息會由eventGenerator的執行個體觸發,見圖中黃綠色箭頭),當收到這個go消息,run()就循環調用advance()函數來處理消息隊列裡面的每個消息。在處理每個消息的時候,每個消息上的observer會被kick()一下,然後消息隊列會執行event上的execute()函數來處理這個消息對應的事務。
在EventGenerator::parse()生成eventgenerator後,第二件事情是調用了這個執行個體(churnEventGenerator為例)的thread函數,然後這個消息發生器對象就開始作為一個并發任務開始運作其run()函數了。在其run()函數中,我們可以看到generator的主要工作了:首先生成了一個仿真結束消息,然後從network執行個體中要來了所有的node資訊,把他們都維護在本地的資料結構裡面,并把wellknown結點告訴他們,這樣他們一開始就能知道他們到那裡去找access point。然後設定每個node加入p2p網絡的事件。當然,wellknown結點是最早加入的(不然别人找不到他了)。最後給eventqueue發一個go消息,eventqueue就開始處理消息了,整個仿真就開始了(但是由于沒有調用yield(),目前任務還沒進行切換,是以在實體上那些任務一個都跑不起來)。
再回到EventGenerator::parse(event_file)函數,最後一步是通過工廠模式建立了observer對象執行個體。以churnObserver為例,他的工作也很簡單,從Network對象執行個體裡面得到所有的node資訊,把自己的指針加入他們,這樣他們發送消息在消息隊列處理時observer就會被觸發了。
總結: eventGenerator 是注冊在eventQueue上的observer,而普通observer是注冊在node上的。
<a href="http://nathanxu.blog.51cto.com/attachment/200912/23/50836_1261549709lI1V.jpg"></a>
本文轉自nathanxu 51CTO部落格,原文連結:http://blog.51cto.com/nathanxu/247840,如需轉載請自行聯系原作者