-
Notifications
You must be signed in to change notification settings - Fork 0
/
db.go
123 lines (112 loc) · 2.94 KB
/
db.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package db
import (
"io/fs"
"os"
"sync"
"github.com/he-wen-yao/bitcask-kvdb/util"
)
type (
bitCaskDB struct {
mu *sync.RWMutex
options *Options
// 记录每个类型的 older 个数
olderFidNum map[logType]uint8
// string 索引映射树
strIndex *strIndex
// 活跃的文件
activeLogFiles map[logType]*logFile
// 日志类型对应文件ID
logTypeFIds map[logType][]int
}
)
// DefaultBitCaskDB 创建一个 bitCaskDB 实例
func DefaultBitCaskDB() *bitCaskDB {
return &bitCaskDB{
options: DefaultOptions(),
mu: new(sync.RWMutex),
olderFidNum: make(map[logType]uint8),
strIndex: NewStrIndex(),
activeLogFiles: make(map[logType]*logFile),
}
}
// NewBitCaskDB 根据 Options 配置创建 bitCaskDB 实列
func NewBitCaskDB(options *Options) *bitCaskDB {
return &bitCaskDB{
options: options,
mu: new(sync.RWMutex),
olderFidNum: make(map[logType]uint8),
strIndex: NewStrIndex(),
activeLogFiles: make(map[logType]*logFile),
}
}
// Run 运行实例
func (db *bitCaskDB) Run() (err error) {
dbLog.Printf("bitCaskDB start run .....")
// 如果不存在此目录则创建
err = db.CreateDirIfExist(db.options.DBDirPath)
if err != nil {
return
}
db.logTypeFIds = map[logType][]int{}
err = db.loadStringLogData()
return
}
// CreateLogFile 创建日志文件
func (db *bitCaskDB) CreateLogFile(logType logType) error {
// 如果不存在此目录则创建
db.mu.Lock()
defer db.mu.Unlock()
if db.activeLogFiles[logType] != nil {
return nil
}
file, err := NewLogFile(db.options.DBDirPath, logType)
if err != nil {
return err
}
db.activeLogFiles[logType] = file
return nil
}
// AppendLog 向日志文件中追加日志
func (db *bitCaskDB) AppendLog(key, value string, logType logType, otType uint16) (*logFile, int64, error) {
// 创建 logType 对应的 日志文件
if err := db.CreateLogFile(logType); err != nil {
return nil, 0, err
}
// 获取 logType 对应的 activeLogFile
activeLogFile := db.activeLogFiles[logType]
lf := NewLogEntry(key, value, otType)
err := activeLogFile.AppendEntry(lf)
if err != nil {
return nil, 0, err
}
return activeLogFile, lf.GetSize(), nil
}
// RedLogEntry 读取指定日志类型的日志记录
func (db *bitCaskDB) RedLogEntry(lt logType, offset int64) (*logEntry, error) {
le, err := db.activeLogFiles[lt].ReadLogEntry(offset)
if err != nil {
return nil, err
}
return le, nil
}
// CreateDirIfExist 如果目录不存在则创建,存在则忽略
func (db *bitCaskDB) CreateDirIfExist(dirPath string) (err error) {
if !util.PathExist(dirPath) {
if err = os.MkdirAll(dirPath, os.ModePerm); err != nil {
return err
}
}
return nil
}
// ReaderDir 读取目录中的内容
func (db *bitCaskDB) ReadDir(dirPath string) (files []fs.DirEntry, err error) {
err = db.CreateDirIfExist(dirPath)
if err != err {
return nil, err
}
files, err = os.ReadDir(dirPath)
if err != nil {
return nil, err
}
return
}