Add GS Event handling mechanism analysis
This commit is contained in:
@@ -0,0 +1,327 @@
|
||||
# GS Event 處理機制分析
|
||||
|
||||
## 概述
|
||||
|
||||
GS (DtrGuiSrv) 的事件處理機制負責:
|
||||
- 定期輪詢 RAID 控制器的事件
|
||||
- 儲存事件到記憶體佇列
|
||||
- 記錄事件到檔案
|
||||
- 觸發 Email / SNMP 通知
|
||||
|
||||
## 架構流程
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ GS Event 處理架構 │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ PollingCtlrEvent (Thread) │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ while(1) { │ │ │
|
||||
│ │ │ for (每個控制器) { │ │ │
|
||||
│ │ │ GetCtlrEvent() ──► 取得 RAID 事件 │ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ │ ▼ │ │ │
|
||||
│ │ │ SaveInBandEvent() ──► 儲存到記憶體佇列 │ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ │ ▼ │ │ │
|
||||
│ │ │ RecEventToFile() ──► 寫入 Event Log 檔案 │ │ │
|
||||
│ │ │ } │ │ │
|
||||
│ │ │ sleep(30秒) │ │ │
|
||||
│ │ │ } │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ HandleInBandEventReq (GC 請求) │ │
|
||||
│ │ - 0x01: 取得單一事件 (Remove_InBand_Event) │ │
|
||||
│ │ - 0x02: 取得所有事件 │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ 事件處理動作 │ │
|
||||
│ │ - Email 通知 (IssueMailOut) │ │
|
||||
│ │ - SNMP Trap 發送 │ │
|
||||
│ │ - UI 更新 │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 主要函數
|
||||
|
||||
### 1. PollingCtlrEvent - 事件輪詢執行緒
|
||||
|
||||
```c
|
||||
// cPollingEvent.c:1397
|
||||
UCHAR PollingCtlrEvent(pid_t pid2) {
|
||||
while(1) {
|
||||
for(i=0; i<MAX_DTR_IN_HOST-1; i++) {
|
||||
pCtrlInfo = pGetgloDTRInfo(i);
|
||||
|
||||
// 只處理線上的控制器
|
||||
if(pCtrlInfo->bStatus != CTLR_STATUS_ALIVE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 取得控制器事件
|
||||
bStatus = GetCtlrEvent(i, &event_info);
|
||||
|
||||
// 處理每個事件
|
||||
while(event_info.bStatus) {
|
||||
// FW 更新事件處理
|
||||
if(event_info.bEventBuf[0] == FW_FLUSH_EVENT) {
|
||||
// 設定 FW 狀態
|
||||
}
|
||||
|
||||
// 儲存事件
|
||||
SaveInBandEvent(i, &event_info);
|
||||
|
||||
// 寫入檔案
|
||||
RecEventToFile(i, &event_info);
|
||||
}
|
||||
}
|
||||
|
||||
sleep(MAX_EVENT_POLLING_THREAD_TIME_DELAY); // 30秒
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. SaveInBandEvent - 儲存事件到記憶體
|
||||
|
||||
```c
|
||||
// cPollingEvent.c:1095
|
||||
UCHAR SaveInBandEvent(UCHAR bCtlrNo, PEVENT_INFO pEvent_info) {
|
||||
// 取得控制器的事件佇列
|
||||
sCtlrEvent = pGetEventFreeQ(bCtlrNo);
|
||||
|
||||
// 從空閒佇列取得一個 entry
|
||||
CurQ = sCtlrEvent->InBandFreeQ;
|
||||
|
||||
// 複製事件資料
|
||||
memcpy(CurQ->bEventBuf, pEvent_info->bEventBuf, MAX_EDB_SZ);
|
||||
|
||||
// 標記為有效
|
||||
CurQ->bStatus = TRUE;
|
||||
|
||||
return SYSOK;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. RecEventToFile - 寫入事件檔案
|
||||
|
||||
```c
|
||||
// cPollingEvent.c:1145
|
||||
void RecEventToFile(UCHAR bCtlrNo, PEVENT_INFO pEvent_info) {
|
||||
// 取得時間
|
||||
GetSystemDateTime(DateTimeBuf);
|
||||
|
||||
// 解析事件
|
||||
ParseEvent2(pEvent_info->bEventBuf, EventStrBuf, EventMailBuf);
|
||||
|
||||
// 寫入 Event Log 檔案
|
||||
pFile_EM = fopen(FileNameBuf, "a+");
|
||||
fprintf(pFile_EM, "%s\t%s\n", DateTimeBuf, EventStrBuf);
|
||||
fclose(pFile_EM);
|
||||
|
||||
// 建立 Email 通知檔案
|
||||
// (供 Email 發送服務讀取)
|
||||
}
|
||||
```
|
||||
|
||||
### 4. HandleInBandEventReq - GC 請求處理
|
||||
|
||||
```c
|
||||
// cPollingEvent.c:1478
|
||||
UCHAR HandleInBandEventReq(PNET_REQ_PACKAGE pReqPackage, SHORT iCtlrIndex) {
|
||||
switch(pReqPackage->pInBuffer[INBAND_EVENT_REQ_F_CMD_CODE]) {
|
||||
case 0x01: // 取得單一事件
|
||||
bStatus = Remove_InBand_Event(iCtlrIndex, &EventInfo);
|
||||
// 回傳事件資料
|
||||
break;
|
||||
|
||||
case 0x02: // 取得所有事件
|
||||
pEMH = pGetEventMsgHeader(iCtlrIndex);
|
||||
// 回傳所有事件 + 事件數量
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 事件結構
|
||||
|
||||
### EVENT_INFO
|
||||
|
||||
```c
|
||||
typedef struct _EVENT_INFO {
|
||||
UCHAR bStatus; // 事件狀態 (TRUE=有事件)
|
||||
UCHAR bEventBuf[MAX_EDB_SZ]; // 事件資料 (512 bytes)
|
||||
} EVENT_INFO, *PEVENT_INFO;
|
||||
```
|
||||
|
||||
### 事件類型
|
||||
|
||||
| Event Code | 說明 |
|
||||
|-----------|------|
|
||||
| FW_FLASH_EVENT | 韌體更新事件 |
|
||||
| 0x00-0xFF | 其他事件 |
|
||||
|
||||
## 事件命令碼
|
||||
|
||||
| Command | 值 | 說明 |
|
||||
|---------|-----|------|
|
||||
| Get InBand Event | 0x01 | 取得並移除一個事件 |
|
||||
| Get All InBand Event | 0x02 | 取得所有事件 |
|
||||
|
||||
## 通訊協議
|
||||
|
||||
### GC 請求
|
||||
|
||||
```
|
||||
Offset 0: Phase Code (0xFF)
|
||||
Offset 1: Request Code (0x00)
|
||||
Offset 2: Controller No
|
||||
Offset 3: Event Command (0x01/0x02)
|
||||
```
|
||||
|
||||
### GS 回應
|
||||
|
||||
```
|
||||
Offset 0-2: Phase/Request/Controller
|
||||
Offset 3: Status (0x50=Success)
|
||||
Offset 4: InBand Event Status
|
||||
Offset 5-8: Event Count (for 0x02)
|
||||
Offset 9+: Event Data
|
||||
```
|
||||
|
||||
## 資料結構
|
||||
|
||||
### 事件佇列
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ InBand Event Queue │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────┐ │
|
||||
│ │ Free Q │ ──► Event Entry 1 ──► Event Entry 2 │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐│
|
||||
│ │ Event Q Head ─────────────────────────► Tail ││
|
||||
│ │ [Event1] -> [Event2] -> [Event3] -> ... ││
|
||||
│ └─────────────────────────────────────────────────────────┘│
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### MAX_EVENT_NO
|
||||
|
||||
```
|
||||
#define MAX_EVENT_NO 512 // 每個控制器最大事件數
|
||||
#define MAX_EDB_SZ 512 // 每個事件大小
|
||||
```
|
||||
|
||||
## 輪詢週期
|
||||
|
||||
```c
|
||||
// cPollingEvent.c
|
||||
#define MAX_EVENT_POLLING_THREAD_TIME_DELAY 30 // 30 秒
|
||||
|
||||
sleep(MAX_EVENT_POLLING_THREAD_TIME_DELAY);
|
||||
```
|
||||
|
||||
## Email 通知
|
||||
|
||||
```c
|
||||
// 事件觸發 Email
|
||||
void RecEventToFile(UCHAR bCtlrNo, PEVENT_INFO pEvent_info) {
|
||||
// 解析事件
|
||||
ParseEvent2(pEvent_info->bEventBuf, EventStrBuf, EventMailBuf);
|
||||
|
||||
// 建立 Email 通知檔案
|
||||
// IssueMailOut(bCtlrNo, ...);
|
||||
}
|
||||
```
|
||||
|
||||
## GC 端對應
|
||||
|
||||
### Java 請求
|
||||
|
||||
```java
|
||||
// frmMain.java - EventPollingForSNMP()
|
||||
|
||||
// 發送請求
|
||||
bCmds[0] = (byte) 0xFF; // Phase Code
|
||||
bCmds[1] = (byte) 0x00; // Request Code
|
||||
bCmds[2] = (byte) 0x00; // Controller No
|
||||
bCmds[3] = (byte) 0x02; // Get InBand Event
|
||||
```
|
||||
|
||||
## 關鍵變數
|
||||
|
||||
```c
|
||||
// 全域變數
|
||||
PCTLR_EVENT glo_sCtlrEvent[MAX_DTR_IN_HOST]; // 每個控制器的事件
|
||||
PINBAND_EVENT_Q glo_sCtlrEventEntry[MAX_EVENT_NO]; // 事件 entry
|
||||
|
||||
UCHAR bPopEventMsg = FALSE; // 是否取出事件
|
||||
UCHAR bIssueMail = FALSE; // 是否發送郵件
|
||||
```
|
||||
|
||||
## 處理流程圖
|
||||
|
||||
```
|
||||
RAID Controller
|
||||
│
|
||||
│ In-Band Protocol
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ GetCtlrEvent() │ 取得事件
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ event_info.bStatus │ = TRUE?
|
||||
└──────────┬──────────┘
|
||||
Yes │
|
||||
▼
|
||||
┌─────┴─────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
SaveInBand RecEventToFile
|
||||
│ │
|
||||
│ ├──► Event Log File
|
||||
│ │
|
||||
│ └──► Email File (for IssueMailOut)
|
||||
│
|
||||
▼
|
||||
Event Queue (Memory)
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ HandleInBandEventReq│ GC 讀取事件
|
||||
│ (0x01 / 0x02) │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
▼
|
||||
GC Client
|
||||
```
|
||||
|
||||
## 常見錯誤碼
|
||||
|
||||
| 錯誤碼 | 說明 |
|
||||
|--------|------|
|
||||
| SYSOK | 成功 |
|
||||
| SYSFAIL_EVENT_EMPTY | 無事件 |
|
||||
| SYSFAIL_EVENT_NO_FREE_Q | 事件佇列已滿 |
|
||||
| SYSFAIL_EVENT_INVALID | 無效事件 |
|
||||
|
||||
## 實作重點
|
||||
|
||||
1. **記憶體佇列**: 使用 linked list 儲存事件
|
||||
2. **線程安全**: 使用 Semaphore 保護共享資源
|
||||
3. **事件去重**: 每個事件只處理一次
|
||||
4. **檔案記錄**: 所有事件寫入 Event Log
|
||||
5. **異步通知**: Email/SNMP 異步觸發
|
||||
Reference in New Issue
Block a user