From 20008f09d08b4ba735621433d76fbbb7116fab5a Mon Sep 17 00:00:00 2001 From: accusys Date: Sun, 29 Mar 2026 13:58:19 +0800 Subject: [PATCH] Add GS Event handling mechanism analysis --- GS_EventHandling.md | 327 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 GS_EventHandling.md diff --git a/GS_EventHandling.md b/GS_EventHandling.md new file mode 100644 index 0000000..e2ed64d --- /dev/null +++ b/GS_EventHandling.md @@ -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; ibStatus != 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 異步觸發