-
Notifications
You must be signed in to change notification settings - Fork 0
/
manifest.go
112 lines (101 loc) · 2.29 KB
/
manifest.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
package godb
import (
"io"
"os"
"path"
"sync"
"time"
"github.com/jakub-galecki/godb/common"
"github.com/tinylib/msgp/msgp"
)
// todo??: use protobuf
//go:generate msgp
type Manifest struct {
f *os.File
mu sync.Mutex
Id string
L0 []string // id's of the sst files
Levels [][]string // id's of the sst files
Table string
CreatedAt int64
Path string
BlockSize uint64
MaxLevels int
// seqNum is a global counter for memtable writes to distinguish between new and old entries.
SeqNum uint64
// nextFileNumber indicates next file number that will be assigned to wal and memtable.
NextFileNumber uint64
LastFlushedFileNumber uint64
}
func newManifest(id string, dir, table string, blockSize uint64, maxLevels int) (*Manifest, error) {
mFile, err := common.CreateFile(path.Join(dir, common.MANIFEST))
if err != nil {
return nil, err
}
m := &Manifest{
Id: id,
f: mFile,
L0: []string{},
Levels: make([][]string, 0, maxLevels),
Table: table,
CreatedAt: time.Now().UnixNano(),
Path: dir,
BlockSize: blockSize,
MaxLevels: maxLevels,
SeqNum: 1,
}
return m, nil
}
func readManifest(dir string) (*Manifest, error) {
m := &Manifest{}
f, err := os.Open(path.Join(dir, common.MANIFEST))
if err != nil {
return nil, err
}
err = m.DecodeMsg(msgp.NewReader(f))
if err != nil {
if err := f.Close(); err != nil {
return nil, err
}
return nil, err
}
if err := f.Close(); err != nil {
return nil, err
}
f, err = os.OpenFile(path.Join(dir, common.MANIFEST), os.O_RDWR, 0666)
if err != nil {
return nil, err
}
m.f = f
return m, nil
}
func (m *Manifest) addSst(level int, sstId string) {
if level == 0 {
m.L0 = append(m.L0, sstId)
return
}
m.Levels[level] = append(m.Levels[level], sstId)
}
// This should be somehow optimized because now we have to remove file content and write new Manifest
func (m *Manifest) fsync() error {
m.mu.Lock()
defer m.mu.Unlock()
if err := m.f.Truncate(0); err != nil {
return err
}
if _, err := m.f.Seek(0, io.SeekStart); err != nil {
return err
}
w := msgp.NewWriter(m.f)
err := m.EncodeMsg(w)
if err != nil {
return err
}
if err := w.Flush(); err != nil {
return err
}
if err := m.f.Sync(); err != nil {
return err
}
return nil
}