feat: 优化块

This commit is contained in:
Netlops 2025-04-23 18:36:17 +08:00
parent 4559bb2cd6
commit 3c1cc26896

View File

@ -35,6 +35,9 @@ type PowerLossTest struct {
blocksMap map[int]model.BlockStatus // 数据块状态映射 blocksMap map[int]model.BlockStatus // 数据块状态映射
} }
// 预生成的数据块数量常量
const PreGeneratedBlockCount = 1000
// NewPowerLossTest 创建断电测试 // NewPowerLossTest 创建断电测试
func NewPowerLossTest(cfg *config.Config, logger *logrus.Logger) *PowerLossTest { func NewPowerLossTest(cfg *config.Config, logger *logrus.Logger) *PowerLossTest {
baseTest := NewBaseTestCase( baseTest := NewBaseTestCase(
@ -93,6 +96,8 @@ func (t *PowerLossTest) Setup(ctx context.Context, recovery bool) error {
} }
} }
time.Sleep(10 * time.Second)
// 挂载缓存设备 // 挂载缓存设备
mountPoint := t.config.Server.MountPoint mountPoint := t.config.Server.MountPoint
t.setMessage(fmt.Sprintf("挂载缓存设备到 %s", mountPoint)) t.setMessage(fmt.Sprintf("挂载缓存设备到 %s", mountPoint))
@ -140,14 +145,14 @@ func (t *PowerLossTest) Run(ctx context.Context) (*model.TestResult, error) {
startTime := time.Now() startTime := time.Now()
var totalBytesWritten int var totalBytesWritten int
// 第一阶段 - 在内存中预先生成所有数据块 // 第一阶段 - 在内存中预先生成固定数量的数据块
t.setMessage("在内存中预生成数据块") t.setMessage(fmt.Sprintf("在内存中预生成 %d 个数据块", PreGeneratedBlockCount))
// 预先在内存中生成所有数据块 // 预先在内存中生成固定数量的数据块
blocksInMemory := make([]*model.TestBlock, t.totalBlocks) preGeneratedBlocks := make([]*model.TestBlock, PreGeneratedBlockCount)
checksumMap := make(map[int]string) checksumMap := make(map[int]string)
for i := 0; i < t.totalBlocks; i++ { for i := 0; i < PreGeneratedBlockCount; i++ {
select { select {
case <-ctx.Done(): case <-ctx.Done():
t.setStatus(StatusAborted) t.setStatus(StatusAborted)
@ -164,16 +169,20 @@ func (t *PowerLossTest) Run(ctx context.Context) (*model.TestResult, error) {
block := model.NewTestBlock(data, i) block := model.NewTestBlock(data, i)
// 存储到内存中 // 存储到内存中
blocksInMemory[i] = block preGeneratedBlocks[i] = block
checksumMap[i] = block.Checksum
// 更新进度 // 更新进度
if i > 0 && i%100 == 0 { progress := float64(i+1) / float64(PreGeneratedBlockCount) * 30 // 前30%进度用于生成
progress := float64(i+1) / float64(t.totalBlocks) * 30 // 前30%进度用于生成
t.setProgress(progress) t.setProgress(progress)
t.setMessage(fmt.Sprintf("已在内存中生成 %d/%d 个数据块", i, t.totalBlocks))
} }
} }
t.setMessage("预生成数据块完成,生成校验和映射")
// 为所有实际需要写入的块计算并存储校验和映射
for i := 0; i < t.totalBlocks; i++ {
blockIndex := i % PreGeneratedBlockCount
checksumMap[i] = preGeneratedBlocks[blockIndex].Checksum
} }
// 将校验和映射持久化到文件 // 将校验和映射持久化到文件
@ -202,15 +211,19 @@ func (t *PowerLossTest) Run(ctx context.Context) (*model.TestResult, error) {
t.setMessage("校验和映射已保存,准备断电测试,开始写入数据块...") t.setMessage("校验和映射已保存,准备断电测试,开始写入数据块...")
time.Sleep(3 * time.Second) // 给用户一些时间准备 time.Sleep(3 * time.Second) // 给用户一些时间准备
// 第二阶段 - 写入数据块到磁盘 // 第二阶段 - 写入数据块到磁盘,使用循环重复的预生成块
t.setMessage("写入数据块到磁盘 (请在适当时手动断电)") t.setMessage("写入数据块到磁盘 (请在适当时手动断电)")
for i, block := range blocksInMemory { for i := 0; i < t.totalBlocks; i++ {
select { select {
case <-ctx.Done(): case <-ctx.Done():
t.setStatus(StatusAborted) t.setStatus(StatusAborted)
return nil, ctx.Err() return nil, ctx.Err()
default: default:
// 获取预生成的块(循环使用)
blockIndex := i % PreGeneratedBlockCount
block := preGeneratedBlocks[blockIndex]
// 添加到数据块列表 // 添加到数据块列表
t.blocksMu.Lock() t.blocksMu.Lock()
t.blocks = append(t.blocks, block) t.blocks = append(t.blocks, block)
@ -244,7 +257,7 @@ func (t *PowerLossTest) Run(ctx context.Context) (*model.TestResult, error) {
t.writtenBlocks++ t.writtenBlocks++
totalBytesWritten += len(block.Data) totalBytesWritten += len(block.Data)
t.setMessage(fmt.Sprintf("同步数据到磁盘 (已写入 %d/%d 块)", i, t.totalBlocks)) t.setMessage(fmt.Sprintf("同步数据到磁盘 (已写入 %d/%d 块)", i+1, t.totalBlocks))
_, err = utils.ExecuteCommand("sync") _, err = utils.ExecuteCommand("sync")
if err != nil { if err != nil {
t.logger.Warnf("执行sync命令失败: %v", err) t.logger.Warnf("执行sync命令失败: %v", err)
@ -356,10 +369,11 @@ func (t *PowerLossTest) CheckIntegrity() *model.IntegrityInfo {
if storedChecksum, ok := checksumMap[i]; ok { if storedChecksum, ok := checksumMap[i]; ok {
expectedChecksum = storedChecksum expectedChecksum = storedChecksum
} else { } else {
// 回退到内存中的校验和 // 回退到内存中的校验和 - 现在需要考虑块的循环使用
t.blocksMu.RLock() t.blocksMu.RLock()
if i < len(t.blocks) && t.blocks[i] != nil { blockIndex := i % PreGeneratedBlockCount
expectedChecksum = t.blocks[i].Checksum if blockIndex < len(t.blocks) && t.blocks[blockIndex] != nil {
expectedChecksum = t.blocks[blockIndex].Checksum
} }
t.blocksMu.RUnlock() t.blocksMu.RUnlock()
} }