• 沒有找到結果。

3.   將動態敏捷測試應用在網路服務

3.2   P REFIX - BASED REPLAY

Prefix-based replay 基本上是依賴 proxy 來完成,當 SOAP message 傳入的時候,

這時 proxy 會先將 SOAP request 另外開一個 thread 來處理,所以每一個 request

35

都是一個獨立的 thread 來處理。所以這時的狀況,大家就變成 concurrent 在執行,

所以我們必須利用 semaphore 來確保同一時間只有一個一個 thread 進入 critical section 取得 version number。再配合上 entry protocol 與 exit protocol 來完成 prefix-based replay 的動作。

Figure 3.3 Proxy

要完成 prefix-based replay 主要是由幾個部分所組成,第一個部分就是 monitor,

當程式執行到 entry protocol 時,如果 mode 為 monitor 時,這時就要執行 monitor 的動作,而 monitor 的用意,就是將這時候的資訊給記錄下來,如果 mode 為 replay 時,這時就要執行 replay 的動作,replay 就是要根據我們推出來的 race variants 的 order 來執行,但是後面還是會做 monitor,所以 replay 是搭配 monitor 在做的。

36

不管 mode 是 monitor 還是 replay,每次執行之後都會有 event log 產生。

所以我們先來看看,整個 EventLog 的資料結構,整個資料結構如下圖所示:

Figure 3.4 eventLog data structure

eventID 為一個 structure,裡邊存放 prcid 與 evnseq。execinfo 則是在執行 entry protocol 與 exit protocol 之後,會將其紀錄起來的一個 structure。而 eventlog 則是 將 execinfo 這個 sturcture 收集進來,以及 RWOP、valuename、LOCCTR 組合而 成 eventlog 這個 structure。以下我們會用 code 輔佐,解釋每一個 parameter 的意 義。

public class EvntLog {

37 public String RWOP, VarName, Mode;

public int VarVersion, VarValue, LOCCTR;

public EvntLog(ExecInfo tmpExecInfo, String RWOP, String VarName,

int LOCCTR) {

this.RWOP = new String(RWOP);

this.VarName = new String(VarName);

this.Mode = new String(tmpExecInfo.Mode);

this.VarVersion = tmpExecInfo.Version;

this.VarValue = tmpExecInfo.Value;

this.LOCCTR = LOCCTR;

}

}

Figure 3.5 EventLog

eventLog 的結構如 fiquere3.5,一共有八個 item 的資訊,RWOP 是 string type 的 value 記錄這個動作是 read 或是 write 的 operation,這個是依據是否有 update 資料 來判定,如果有 update 資料就為 write operation,反之就為 read operation。varname 也是 string type 的 value 記錄 value 的名字,這個 value 通常是直接從 request message

38

的參數中直接取出來。mode 則是記錄現在執行的 mode 是 monitor 還是 replay。

varversion、varvalue、LOCCTR 都是 integer type 的 value。varversion 是記錄 value 的 verison number,version number 是由 exit protocol 來領取。varvalue 就是存放

value 的值,可以從 request message 當中 query 出來。LOCCTR 則是記錄現在程式 運行到哪一個部分,這個數值可以由 BPEL process 當中設立一個 global 變數來存 取。

package RaceGraph;

public class EventNode {

public EventID EvnID;

public int VarVersion, LOCCTR;

public String VarName, Mode, RWOP;

public boolean Flag;

public EventNode() {

EvnID = new EventID();

VarName = new String("");

VarVersion = -1;

RWOP = new String("");

39 Mode = new String("");

LOCCTR = -1;

}

}

Figure 3.6 EventNode

由於在進入 entry protocol 之時,其中有一個參數為 eventnode,所以我們先來看 一下 eventvode 的結構是什麼,eventvode 就是 racegraph 當中的 node,裡面的結 構也大致跟 eventlog 一樣,唯一不同的地方,就是多了一個 evnid 。

package RaceGraph;

public class EventID {

public int PrcID;

public int EvnSeq;

public EventID() {

PrcID = -1;

EvnSeq = -1;

}

40

public void set(int PrcID, int EvnSeq) {

this.PrcID = PrcID;

this.EvnSeq = EvnSeq;

}

public void set(EventID theEvnID) {

this.set(theEvnID.PrcID, theEvnID.EvnSeq);

}

}

Figure 3.7 Eventid

eventid 裡有兩個 value,一個是 prcid,就是指 processid 用來記錄這是哪一個 process 所產生的。另一個為 evnseq,用來記錄這個 event 的 sequence。

當進入 entry protocol 時,如果 mode 為 monitor,就開始進行 monitor 的動作。一 開始會先搶 semaphore,搶到了才能進去將資訊記錄起來。接下來會進入 Exit

protocol,然後 valverison 會先加 1 然後將 versionnumber、value 與 mode 暫時存放 到 execinfo 去,都完成了之後,再將 semaphore 放掉。

public void Entry(EventNode evnt, int ProcID, ExecMode mode,

ArrivalList Arrivals) {

41 if (mode.equals("monitor")) {

this.Smphr.down();

// VersionNum = VersionNumber.addVersionNum();

} else if (mode.equals("replay")) {

if (evnt == null) {

Arrivals.setArvl(ProcID);

while (!Arrivals.isAlltrue()) {

synchronized (Arrivals) {

try {

System.out.println(ProcID);

Arrivals.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

mode.set("monitor");

} else if (evnt.RWOP.equals("W")) {

while (this.Version != (evnt.VarVersion - 1));

42

while (this.totalReaders[evnt.VarVersion -

1].intValue() != 0);

} else {

System.out.println("SharedVariable.WriteEntry(): " +

"Error! Evnet["

+ evnt.EvnID.PrcID + "," + evnt.EvnID.EvnSeq

+ "] should be a write operation.");

}

}

}

Figure 3.8 Entry protocol

public ExecInfo Exit(ExecMode mode, int AdjRemWriters) {

ExecInfo tmpInfo;

if (mode.equals("monitor")) {

this.Version = this.Version+1;

this.RemWriters = this.RemWriters + AdjRemWriters;

int tmpVersion = this.Version;

int tmpValue = this.Value;

43

tmpInfo = new ExecInfo(tmpVersion, tmpValue, mode.get());

this.Smphr.up();

} else {

tmpInfo = new ExecInfo(this.Version+1, this.Value,

mode.get());

this.Version = this.Version+1;

this.RemWriters = this.RemWriters + AdjRemWriters;

// FinishNumber.addFinishNum();

}

return tmpInfo;

}

Figure 3.9 Exit protocol

相關文件