-
Notifications
You must be signed in to change notification settings - Fork 4
/
rdb.go
92 lines (82 loc) · 1.81 KB
/
rdb.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
package main
import (
"fmt"
"github.com/tidwall/mmap"
"github.com/xgzlucario/rotom/internal/iface"
"os"
"time"
)
type Rdb struct {
}
func NewRdb() *Rdb {
return &Rdb{}
}
func (r *Rdb) SaveDB() (err error) {
// create tmp file
fname := fmt.Sprintf("%s.rdb", time.Now().Format(time.RFC3339))
fs, err := os.Create(fname)
if err != nil {
return err
}
writer := iface.NewWriter(make([]byte, 0, KB))
writer.WriteUint64(uint64(db.dict.data.Len()))
db.dict.data.All(func(k string, v any) bool {
// format: {objectType, ttl, key, value}
objectType := getObjectType(v)
writer.WriteUint8(uint8(objectType))
ttl, _ := db.dict.expire.Get(k)
writer.WriteVarint(int(ttl))
writer.WriteString(k)
switch objectType {
case TypeString:
writer.WriteBytes(v.([]byte))
case TypeInteger:
writer.WriteVarint(v.(int))
default:
v.(iface.Encoder).WriteTo(writer)
}
return true
})
// flush
_, err = fs.Write(writer.Bytes())
if err != nil {
return err
}
err = fs.Close()
if err != nil {
return err
}
return os.Rename(fname, configGetDbFileName())
}
func (r *Rdb) LoadDB() error {
// Read file data by mmap.
data, err := mmap.Open(configGetDbFileName(), false)
if len(data) == 0 {
return nil
}
if err != nil {
return err
}
rd := iface.NewReader(data)
n := rd.ReadUint64()
for range n {
// format: {objectType, ttl, key, value}
objectType := rd.ReadUint8()
ttl := rd.ReadVarint()
key := rd.ReadString()
switch ObjectType(objectType) {
case TypeString:
db.dict.SetWithTTL(key, rd.ReadBytes(), ttl)
case TypeInteger:
db.dict.SetWithTTL(key, int(rd.ReadVarint()), ttl)
default:
val := type2c[ObjectType(objectType)]()
if val == nil {
panic(fmt.Sprintf("unknown object type: %v", objectType))
}
val.ReadFrom(rd)
db.dict.SetWithTTL(key, val, ttl)
}
}
return nil
}