Initial commit: SRDB - High-performance LSM-Tree database
- Core engine with MemTable, SST, WAL - B+Tree indexing for SST files - Leveled compaction strategy - Multi-table database management - Schema validation and secondary indexes - Query builder with complex conditions - Web UI with HTMX for data visualization - Command-line tools for diagnostics
This commit is contained in:
251
manifest/version_set.go
Normal file
251
manifest/version_set.go
Normal file
@@ -0,0 +1,251 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// VersionSet 版本集合管理器
|
||||
type VersionSet struct {
|
||||
// 当前版本
|
||||
current *Version
|
||||
|
||||
// MANIFEST 文件
|
||||
manifestFile *os.File
|
||||
manifestWriter *Writer
|
||||
manifestNumber int64
|
||||
|
||||
// 下一个文件编号
|
||||
nextFileNumber atomic.Int64
|
||||
|
||||
// 最后序列号
|
||||
lastSequence atomic.Int64
|
||||
|
||||
// 目录
|
||||
dir string
|
||||
|
||||
// 锁
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewVersionSet 创建版本集合
|
||||
func NewVersionSet(dir string) (*VersionSet, error) {
|
||||
vs := &VersionSet{
|
||||
dir: dir,
|
||||
}
|
||||
|
||||
// 确保目录存在
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 读取 CURRENT 文件
|
||||
currentFile := filepath.Join(dir, "CURRENT")
|
||||
data, err := os.ReadFile(currentFile)
|
||||
|
||||
if err != nil {
|
||||
// CURRENT 不存在,创建新的 MANIFEST
|
||||
return vs, vs.createNewManifest()
|
||||
}
|
||||
|
||||
// 读取 MANIFEST 文件
|
||||
manifestName := strings.TrimSpace(string(data))
|
||||
manifestPath := filepath.Join(dir, manifestName)
|
||||
|
||||
// 恢复版本信息
|
||||
version, err := vs.recoverFromManifest(manifestPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vs.current = version
|
||||
vs.nextFileNumber.Store(version.NextFileNumber)
|
||||
vs.lastSequence.Store(version.LastSequence)
|
||||
|
||||
// 解析 MANIFEST 编号
|
||||
fmt.Sscanf(manifestName, "MANIFEST-%d", &vs.manifestNumber)
|
||||
|
||||
// 打开 MANIFEST 用于追加
|
||||
file, err := os.OpenFile(manifestPath, os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vs.manifestFile = file
|
||||
vs.manifestWriter = NewWriter(file)
|
||||
|
||||
return vs, nil
|
||||
}
|
||||
|
||||
// createNewManifest 创建新的 MANIFEST
|
||||
func (vs *VersionSet) createNewManifest() error {
|
||||
// 生成新的 MANIFEST 文件名
|
||||
vs.manifestNumber = vs.nextFileNumber.Add(1)
|
||||
manifestName := fmt.Sprintf("MANIFEST-%06d", vs.manifestNumber)
|
||||
manifestPath := filepath.Join(vs.dir, manifestName)
|
||||
|
||||
// 创建 MANIFEST 文件
|
||||
file, err := os.Create(manifestPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vs.manifestFile = file
|
||||
vs.manifestWriter = NewWriter(file)
|
||||
|
||||
// 创建初始版本
|
||||
vs.current = NewVersion()
|
||||
|
||||
// 写入初始版本
|
||||
edit := NewVersionEdit()
|
||||
nextFile := vs.manifestNumber
|
||||
edit.SetNextFileNumber(nextFile)
|
||||
lastSeq := int64(0)
|
||||
edit.SetLastSequence(lastSeq)
|
||||
|
||||
err = vs.manifestWriter.WriteEdit(edit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 同步到磁盘
|
||||
err = vs.manifestFile.Sync()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新 CURRENT 文件
|
||||
return vs.updateCurrent(manifestName)
|
||||
}
|
||||
|
||||
// recoverFromManifest 从 MANIFEST 恢复版本
|
||||
func (vs *VersionSet) recoverFromManifest(manifestPath string) (*Version, error) {
|
||||
// 打开 MANIFEST 文件
|
||||
file, err := os.Open(manifestPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
reader := NewReader(file)
|
||||
|
||||
// 创建初始版本
|
||||
version := NewVersion()
|
||||
|
||||
// 读取所有 VersionEdit
|
||||
for {
|
||||
edit, err := reader.ReadEdit()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 应用变更
|
||||
version.Apply(edit)
|
||||
}
|
||||
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// updateCurrent 更新 CURRENT 文件
|
||||
func (vs *VersionSet) updateCurrent(manifestName string) error {
|
||||
currentPath := filepath.Join(vs.dir, "CURRENT")
|
||||
tmpPath := currentPath + ".tmp"
|
||||
|
||||
// 1. 写入临时文件
|
||||
err := os.WriteFile(tmpPath, []byte(manifestName+"\n"), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. 原子性重命名
|
||||
err = os.Rename(tmpPath, currentPath)
|
||||
if err != nil {
|
||||
os.Remove(tmpPath)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LogAndApply 记录并应用版本变更
|
||||
func (vs *VersionSet) LogAndApply(edit *VersionEdit) error {
|
||||
vs.mu.Lock()
|
||||
defer vs.mu.Unlock()
|
||||
|
||||
// 1. 创建新版本
|
||||
newVersion := vs.current.Clone()
|
||||
|
||||
// 2. 应用变更
|
||||
newVersion.Apply(edit)
|
||||
|
||||
// 3. 写入 MANIFEST
|
||||
err := vs.manifestWriter.WriteEdit(edit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 4. 同步到磁盘
|
||||
err = vs.manifestFile.Sync()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 5. 更新当前版本
|
||||
vs.current = newVersion
|
||||
|
||||
// 6. 更新原子变量
|
||||
if edit.NextFileNumber != nil {
|
||||
vs.nextFileNumber.Store(*edit.NextFileNumber)
|
||||
}
|
||||
if edit.LastSequence != nil {
|
||||
vs.lastSequence.Store(*edit.LastSequence)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCurrent 获取当前版本
|
||||
func (vs *VersionSet) GetCurrent() *Version {
|
||||
vs.mu.RLock()
|
||||
defer vs.mu.RUnlock()
|
||||
return vs.current
|
||||
}
|
||||
|
||||
// GetNextFileNumber 获取下一个文件编号
|
||||
func (vs *VersionSet) GetNextFileNumber() int64 {
|
||||
return vs.nextFileNumber.Load()
|
||||
}
|
||||
|
||||
// AllocateFileNumber 分配文件编号
|
||||
func (vs *VersionSet) AllocateFileNumber() int64 {
|
||||
return vs.nextFileNumber.Add(1)
|
||||
}
|
||||
|
||||
// GetLastSequence 获取最后序列号
|
||||
func (vs *VersionSet) GetLastSequence() int64 {
|
||||
return vs.lastSequence.Load()
|
||||
}
|
||||
|
||||
// SetLastSequence 设置最后序列号
|
||||
func (vs *VersionSet) SetLastSequence(seq int64) {
|
||||
vs.lastSequence.Store(seq)
|
||||
}
|
||||
|
||||
// Close 关闭 VersionSet
|
||||
func (vs *VersionSet) Close() error {
|
||||
vs.mu.Lock()
|
||||
defer vs.mu.Unlock()
|
||||
|
||||
if vs.manifestFile != nil {
|
||||
return vs.manifestFile.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user