-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup.go
125 lines (94 loc) · 1.75 KB
/
setup.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
124
125
package lunar
import (
"errors"
"os"
"github.com/purehyperbole/lunar/header"
"github.com/purehyperbole/lunar/table"
"github.com/purehyperbole/rad"
)
func (db *DB) setup(datapath string) error {
var err error
var rt *table.Table
db.index = rad.New()
if db.compaction && exists(datapath) {
backup := datapath + ".backup"
if exists(backup) {
return errors.New("could not backup data file")
}
err = os.Rename(datapath, backup)
if err != nil {
return err
}
rt, err = table.New(backup)
} else {
rt, err = table.New(datapath)
}
if err != nil {
return err
}
db.data, err = table.New(datapath)
if err != nil {
return err
}
if exists(datapath) {
return db.reload(rt, db.data)
}
return nil
}
func (db *DB) reload(rt, wt *table.Table) error {
var pos int64
dsz := rt.Size()
for {
if pos+header.HeaderSize > dsz {
return nil
}
// read header
data, err := rt.Read(header.HeaderSize, pos)
if err != nil {
return err
}
h := header.Deserialize(data)
if h.KeySize() < 1 {
if !db.compaction {
wt.SetPosition(pos)
}
break
}
// skip old records
if db.compaction && h.Xmax() > 0 {
continue
}
// get key from data
key := make([]byte, h.KeySize())
kd, err := rt.Read(h.KeySize(), pos+header.HeaderSize)
if err != nil {
return err
}
copy(key, kd)
np := pos
if db.compaction {
data, err := rt.Read(h.TotalSize(), pos)
if err != nil {
return err
}
np, err = wt.Write(data)
if err != nil {
return err
}
}
db.index.Insert(key, &entry{
size: h.TotalSize(),
offset: np,
})
pos = pos + h.TotalSize()
}
db.data = wt
return nil
}
func exists(path string) bool {
_, err := os.Stat(path)
if err != nil {
return false
}
return true
}