Files
srdb/sst/manager.go

285 lines
5.6 KiB
Go
Raw Normal View History

package sst
import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"sync"
)
// Manager SST 文件管理器
type Manager struct {
dir string
readers []*Reader
mu sync.RWMutex
}
// NewManager 创建 SST 管理器
func NewManager(dir string) (*Manager, error) {
// 确保目录存在
err := os.MkdirAll(dir, 0755)
if err != nil {
return nil, err
}
mgr := &Manager{
dir: dir,
readers: make([]*Reader, 0),
}
// 恢复现有的 SST 文件
err = mgr.recover()
if err != nil {
return nil, err
}
return mgr, nil
}
// recover 恢复现有的 SST 文件
func (m *Manager) recover() error {
// 查找所有 SST 文件
files, err := filepath.Glob(filepath.Join(m.dir, "*.sst"))
if err != nil {
return err
}
for _, file := range files {
// 跳过索引文件
filename := filepath.Base(file)
if strings.HasPrefix(filename, "idx_") {
continue
}
// 打开 SST Reader
reader, err := NewReader(file)
if err != nil {
return err
}
m.readers = append(m.readers, reader)
}
return nil
}
// CreateSST 创建新的 SST 文件
// fileNumber: 文件编号(由 VersionSet 分配)
func (m *Manager) CreateSST(fileNumber int64, rows []*Row) (*Reader, error) {
return m.CreateSSTWithLevel(fileNumber, rows, 0) // 默认创建到 L0
}
// CreateSSTWithLevel 创建新的 SST 文件到指定层级
// fileNumber: 文件编号(由 VersionSet 分配)
func (m *Manager) CreateSSTWithLevel(fileNumber int64, rows []*Row, level int) (*Reader, error) {
m.mu.Lock()
defer m.mu.Unlock()
sstPath := filepath.Join(m.dir, fmt.Sprintf("%06d.sst", fileNumber))
// 创建文件
file, err := os.Create(sstPath)
if err != nil {
return nil, err
}
writer := NewWriter(file)
// 写入所有行
for _, row := range rows {
err = writer.Add(row)
if err != nil {
file.Close()
os.Remove(sstPath)
return nil, err
}
}
// 完成写入
err = writer.Finish()
if err != nil {
file.Close()
os.Remove(sstPath)
return nil, err
}
file.Close()
// 打开 SST Reader
reader, err := NewReader(sstPath)
if err != nil {
return nil, err
}
// 添加到 readers 列表
m.readers = append(m.readers, reader)
return reader, nil
}
// Get 从所有 SST 文件中查找数据
func (m *Manager) Get(seq int64) (*Row, error) {
m.mu.RLock()
defer m.mu.RUnlock()
// 从后往前查找(新的文件优先)
for i := len(m.readers) - 1; i >= 0; i-- {
reader := m.readers[i]
row, err := reader.Get(seq)
if err == nil {
return row, nil
}
}
return nil, fmt.Errorf("key not found: %d", seq)
}
// GetReaders 获取所有 Readers用于扫描
func (m *Manager) GetReaders() []*Reader {
m.mu.RLock()
defer m.mu.RUnlock()
// 返回副本
readers := make([]*Reader, len(m.readers))
copy(readers, m.readers)
return readers
}
// GetMaxSeq 获取所有 SST 中的最大 seq
func (m *Manager) GetMaxSeq() int64 {
m.mu.RLock()
defer m.mu.RUnlock()
maxSeq := int64(0)
for _, reader := range m.readers {
header := reader.GetHeader()
if header.MaxKey > maxSeq {
maxSeq = header.MaxKey
}
}
return maxSeq
}
// Count 获取 SST 文件数量
func (m *Manager) Count() int {
m.mu.RLock()
defer m.mu.RUnlock()
return len(m.readers)
}
// ListFiles 列出所有 SST 文件
func (m *Manager) ListFiles() []string {
m.mu.RLock()
defer m.mu.RUnlock()
files := make([]string, 0, len(m.readers))
for _, reader := range m.readers {
files = append(files, reader.path)
}
return files
}
// CompactionConfig Compaction 配置
// 已废弃:请使用 compaction 包中的 Manager
type CompactionConfig struct {
Threshold int // 触发阈值SST 文件数量)
BatchSize int // 每次合并的文件数量
}
// DefaultCompactionConfig 默认配置
// 已废弃:请使用 compaction 包中的 Manager
var DefaultCompactionConfig = CompactionConfig{
Threshold: 10,
BatchSize: 10,
}
// ShouldCompact 检查是否需要 Compaction
// 已废弃:请使用 compaction 包中的 Manager
func (m *Manager) ShouldCompact(config CompactionConfig) bool {
m.mu.RLock()
defer m.mu.RUnlock()
return len(m.readers) > config.Threshold
}
// Compact 执行 Compaction
// 已废弃:请使用 compaction 包中的 Manager
// 注意:此方法已不再维护,不应在新代码中使用
func (m *Manager) Compact(config CompactionConfig) error {
// 此方法已废弃,不再实现
return fmt.Errorf("Compact is deprecated, please use compaction.Manager")
}
// sortRows 按 seq 排序
func sortRows(rows []*Row) {
sort.Slice(rows, func(i, j int) bool {
return rows[i].Seq < rows[j].Seq
})
}
// Delete 删除指定的 SST 文件(预留接口)
func (m *Manager) Delete(fileNumber int64) error {
m.mu.Lock()
defer m.mu.Unlock()
sstPath := filepath.Join(m.dir, fmt.Sprintf("%06d.sst", fileNumber))
return os.Remove(sstPath)
}
// Close 关闭所有 SST Readers
func (m *Manager) Close() error {
m.mu.Lock()
defer m.mu.Unlock()
for _, reader := range m.readers {
reader.Close()
}
m.readers = nil
return nil
}
// Stats 统计信息
type Stats struct {
FileCount int
TotalSize int64
MinSeq int64
MaxSeq int64
}
// GetStats 获取统计信息
func (m *Manager) GetStats() *Stats {
m.mu.RLock()
defer m.mu.RUnlock()
stats := &Stats{
FileCount: len(m.readers),
MinSeq: -1,
MaxSeq: -1,
}
for _, reader := range m.readers {
header := reader.GetHeader()
if stats.MinSeq == -1 || header.MinKey < stats.MinSeq {
stats.MinSeq = header.MinKey
}
if stats.MaxSeq == -1 || header.MaxKey > stats.MaxSeq {
stats.MaxSeq = header.MaxKey
}
// 获取文件大小
if stat, err := os.Stat(reader.path); err == nil {
stats.TotalSize += stat.Size()
}
}
return stats
}