Files
rust_raidguardx/GS_Rust_Refactoring_Analysis.md
T
2026-03-29 14:28:31 +08:00

362 lines
10 KiB
Markdown

# GS (DtrGuiSrv) Rust 重構分析
## 概述
分析是否可將 GS (DtrGuiSrv) C 語言程式完整用 Rust 重構為 `raidguard_x_gui_server`
## 現有 GS 元件分析
### GS (C) 元件清單
| 檔案 | 功能 | 複雜度 | 依賴 |
|------|------|--------|------|
| cMain.c | 主程式入口、初始化 | 中 | 所有模組 |
| cNetWork.c | TCP 網路通訊 (Port 8922) | 高 | socket API |
| cInBand.c | In-Band API 處理 | 高 | RAID Driver |
| cPollingEvent.c | 事件輪詢執行緒 | 中 | 佇列、檔案 |
| cMail.c | Email 發送 (SMTP) | 中 | SMTP library |
| cShareMem.c | 共享記憶體 | 中 | POSIX SHM |
| cSrvConfig.c | 伺服器設定 | 低 | 檔案 I/O |
| cDTRIoCtl.c | RAID I/O Control | 高 | Driver API |
### 每個元件的關鍵功能
```
cMain.c
├── InitGUIServer() - 初始化
├── InitSMTP() - SMTP 初始化
├── InitRAIDCard() - RAID 卡初始化
└── Main Loop - 網路監聽
cNetWork.c
├── InitialSrvSocket() - 建立 TCP Server (Port 8922)
├── InitialClientSocket() - accept()
├── GUITrans() - TCP 傳輸 (Phase1 + Phase2)
└── ServerGUITrans() - 伺服器端傳輸
cInBand.c
├── HandleInBandReq() - 處理 In-Band 請求
├── HandleSrvConfigReq() - 處理伺服器設定
└── [RAID Driver I/O] - 與硬體通訊
cPollingEvent.c
├── PollingCtlrEvent() - 執行緒:輪詢事件
├── SaveInBandEvent() - 儲存到記憶體佇列
├── RecEventToFile() - 寫入事件檔案
└── HandleInBandEventReq() - 處理 GC 請求
cMail.c
├── InitMailEntryFreeQ() - 初始化郵件佇列
├── IssueMailOut() - 發送郵件
└── LoadMailAddrFromFile() - 載入郵件地址
cShareMem.c
├── InitialSHMForAllCtlr() - 初始化共享記憶體
└── 與 RAID Driver 共享資料
cDTRIoCtl.c
├── QuaryDTR() - 查詢 RAID 資訊
├── DevIoControl() - I/O Control
└── 硬體驅動程式介面
```
## 重構可行性分析
### 可以重構的部分 (✅)
| 元件 | Rust 方案 | 難度 |
|------|-----------|------|
| TCP 網路 | tokio, async-std | 中 |
| 協議解析 | nom, manual parsing | 低 |
| 事件輪詢 | tokio::spawn, interval | 低 |
| 設定管理 | serde_json, toml | 低 |
| 日誌系統 | tracing, log | 低 |
| Email 發送 | lettre | 中 |
| 錯誤處理 | thiserror, anyhow | 低 |
### 難以重構的部分 (⚠️)
| 元件 | 問題 | 建議 |
|------|------|------|
| cShareMem.c | POSIX 共享記憶體依賴 | 使用 rust-posix-shmem 或 FFI |
| cDTRIoCtl.c | RAID Driver I/O | 需要 FFI 綁定或重寫 Driver |
| 硬體驅動 | 低層級硬體存取 | 保持 C 或用 FFI |
### 需要 FFI 的部分
```rust
// 使用 FFI 呼叫現有 C 函數
#[repr(C)]
pub struct CtlrInfo {
pub bStatus: u8,
pub bCtlrSN: [c_char; 16],
// ...
}
extern "C" {
fn QuaryDTR(bDevNo: u8, bPageBuf: *mut u8, pbHeatsink: *mut u8) -> c_short;
fn DevIoControl(...) -> c_uchar;
fn GetCtlSemP(DeviceNum: c_short) -> c_short;
fn GetCtlSemV(DeviceNum: c_short) -> c_short;
}
```
## 現有 Rust 專案結構
```
raidguard_x_gui_server/
├── Cargo.toml # tokio, serde, tracing, lettre
├── src/
│ ├── main.rs # 入口
│ ├── lib.rs # library
│ ├── server.rs # TCP Server
│ ├── protocol/ # 協議解析
│ ├── handlers/ # 請求處理
│ ├── mock/ # 模擬數據
│ └── backend/ # 後端
```
## 重構架構建議
### 模組化設計
```
raidguard_x_gui_server/
├── src/
│ ├── main.rs
│ ├── lib.rs
│ │
│ ├── network/ # 網路通訊
│ │ ├── mod.rs
│ │ ├── server.rs # TCP Server (Port 8922)
│ │ ├── transport.rs # Phase1/Phase2 傳輸
│ │ └── client.rs # Client 連線管理
│ │
│ ├── protocol/ # 協議
│ │ ├── mod.rs
│ │ ├── request.rs # 請求解析
│ │ ├── response.rs # 回應封裝
│ │ └── error.rs # 協議錯誤
│ │
│ ├── inband/ # In-Band API
│ │ ├── mod.rs
│ │ ├── handler.rs # 請求處理
│ │ ├── page.rs # Page 資料
│ │ └── password.rs # 密碼處理
│ │
│ ├── event/ # 事件處理
│ │ ├── mod.rs
│ │ ├── queue.rs # 事件佇列
│ │ ├── polling.rs # 輪詢執行緒
│ │ └── storage.rs # 事件儲存
│ │
│ ├── email/ # Email 通知
│ │ ├── mod.rs
│ │ ├── smtp.rs # SMTP 發送
│ │ └── template.rs # 郵件範本
│ │
│ ├── config/ # 設定管理
│ │ ├── mod.rs
│ │ ├── server.rs # 伺服器設定
│ │ └── storage.rs # 設定儲存
│ │
│ ├── driver/ # RAID Driver (FFI)
│ │ ├── mod.rs
│ │ ├── ffi.rs # FFI 綁定
│ │ └── types.rs # C 類型包裝
│ │
│ └── logging/ # 日誌
│ └── mod.rs
```
### 技術選型
| 功能 | Rust 選擇 | 說明 |
|------|----------|------|
| 非同步 runtime | tokio | 完整 async/await 支援 |
| TCP 網路 | tokio::net | 內建 TCP 支援 |
| 協議解析 | nom / 手動 | 簡單協議,手動即可 |
| 序列化 | serde | JSON 支援 |
| Email | lettre | SMTP client |
| 日誌 | tracing | 結構化日誌 |
| 錯誤處理 | thiserror | 錯誤鏈 |
| 共享記憶體 | libc::sys::shm | FFI |
| 執行緒安全 | Arc<Mutex<>> | 內建 |
## 重構階段規劃
### Phase 1: 基礎設施 (1-2 週)
- [ ] 專案初始化 (現有)
- [ ] TCP Server (Port 8922)
- [ ] 協議解析 (Phase1/Phase2)
- [ ] 基本請求/回應處理
- [ ] 日誌系統
### Phase 2: In-Band API (2-3 週)
- [ ] GET_PAGE 處理 (0x01)
- [ ] SEND_PASSWORD 處理 (0x1D)
- [ ] 其他 OpCode 處理
- [ ] 與 RAID Driver FFI
### Phase 3: 事件系統 (1-2 週)
- [ ] 事件輪詢執行緒
- [ ] 事件佇列
- [ ] 事件儲存 (檔案)
- [ ] GC 事件查詢
### Phase 4: 通知系統 (1 週)
- [ ] Email 發送 (SMTP)
- [ ] SNMP Trap (可選)
- [ ] 設定管理
### Phase 5: 整合測試 (1-2 週)
- [ ] 單元測試
- [ ] 整合測試
- [ ] 效能優化
- [ ] 文檔
## 挑戰與解決方案
### 挑戰 1: RAID Driver I/O
**問題**: cDTRIoctl.c 需要與硬體驅動程式直接通訊
**解決方案**:
```rust
// 方案 A: FFI 呼叫現有 C 函數
#[link(name = "DtrIoCtl")]
extern "C" {
fn DevIoControl(...) -> c_uchar;
}
// 方案 B: 將 Driver 程式碼移植到 Rust
// (需要大量時間)
// 方案 C: 保持 GS 為 C,只重構 GUI 部分
// (推薦: 混合架構)
```
### 挑戰 2: 共享記憶體
**問題**: cShareMem.c 使用 POSIX 共享記憶體
**解決方案**:
```rust
// 使用 nix crate
use nix::sys::shm::{shmat, shmget, ShmFlags};
// 或使用 libc
use libc::{shmget, shmat, shmctl, IPC_RMID};
```
### 挑戰 3: 執行緒同步
**問題**: C 的 Semaphore 需要轉換
**解決方案**:
```rust
// Rust 建議使用
use std::sync::{Mutex, Semaphore, Arc};
// 或使用 tokio::sync
use tokio::sync::{Mutex, Semaphore};
```
### 挑戰 4: 相容性
**問題**: 需要完全相容現有 GC (Java) 協議
**解決方案**:
```rust
// 確保位元組級別完全相同
#[repr(C)]
struct RequestHeader {
pub req_type: u8,
pub phase_code: u8,
pub length: u16, // Little-endian
}
// 測試覆蓋所有現有功能
```
## 推薦策略
### 策略 A: 完全重構 (全部 Rust)
**優點**:
- 單一語言,維護簡單
- 記憶體安全
- 現代化生態
**缺點**:
- 需要 FFI 或重寫 Driver
- 開發時間長
**時間預估**: 3-4 個月
### 策略 B: 混合架構 (推薦)
```
┌─────────────────────────────────────────────────────────────┐
│ 混合架構 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ GC (Java) │ │ Rust Server │ │ C Driver │ │
│ │ Port 8922 │◄──►│ │◄──►│ (現有) │ │
│ │ │ │ │ │ │ │
│ └─────────────┘ └──────┬──────┘ └─────────────┘ │
│ │ │
│ 共享記憶體/FDI │
│ │
└─────────────────────────────────────────────────────────────┘
```
**優點**:
- 保留穩定的 C Driver
- Rust 處理網路/業務邏輯
- 逐步遷移
**缺點**:
- FFI 複雜度
**時間預估**: 2-3 個月
### 策略 C: 只重構 GUI Client
維持 GS 為 C 程式,只重構 GC (Java) 為 Rust GUI Client。
## 結論
**可以完整重構,但建議採用混合策略:**
1. **網路/協議/事件/Email** → Rust (可完全重構)
2. **RAID Driver/共享記憶體** → 保持 C 或 FFI
3. **優先順序**: 先重構 GC (Java→Rust) → 再考慮 GS
**主要原因**:
- Driver 層變動風險高
- GS 相對穩定,需求變化少
- GC (GUI) 更有現代化價值
## 現有程式碼利用率
```
raidguard_x_gui_server (現有)
├── ✅ network/server.rs → 可基於 cNetWork.c
├── ✅ protocol/ → 可基於 GS 協議
├── ⚠️ handlers/ → 需要實作 In-Band API
└── ❌ backend/ → 需要連接 RAID Driver
```
## 下一步建議
1. **短期**: 完成現有 Rust Server 與 GS 的替換
2. **中期**: FFI 整合現有 C Driver
3. **長期**: 逐步將 Driver 移植到 Rust (如有需要)