-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfile.go
More file actions
114 lines (91 loc) · 1.94 KB
/
Copy pathfile.go
File metadata and controls
114 lines (91 loc) · 1.94 KB
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
package memdb
import (
"fmt"
"io"
"os"
"github.com/pkg/errors"
"github.com/tidwall/resp"
)
var ErrOpenFile = errors.New("opening file")
type fileStorage struct {
file *os.File
}
type command int8
const (
commandSET command = iota
commandDEL
)
type fileItem struct {
item
command command
}
func openFileStorage(path string) (*fileStorage, error) {
var err error
fs := &fileStorage{}
fs.file, err = os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0666)
if err != nil {
return nil, err
}
return fs, nil
}
type readResult struct {
item fileItem
err error
}
func (fs *fileStorage) read() chan *readResult {
results := make(chan *readResult)
go func() {
rd := resp.NewReader(fs.file)
for {
result := readResult{}
v, _, err := rd.ReadValue()
if err == io.EOF {
break
}
if err != nil {
result.err = err
break
}
if v.Type() == resp.Array {
for i, v := range v.Array() {
switch i {
case 0:
command := v.String()
if command == "set" {
result.item.command = commandSET
} else if command == "del" {
result.item.command = commandDEL
}
case 1:
result.item.key = dbKey(v.String())
case 2:
result.item.value = v.String()
}
}
results <- &result
}
}
close(results)
}()
return results
}
func (fs *fileStorage) write(items ...fileItem) error {
writer := resp.NewWriter(fs.file)
for _, item := range items {
row := make([]resp.Value, 0)
if item.command == commandSET {
row = append(row, resp.StringValue("set"), resp.StringValue(string(item.key)), resp.StringValue(item.value))
} else if item.command == commandDEL {
row = append(row, resp.StringValue("del"), resp.StringValue(string(item.key)))
} else {
panic(fmt.Sprintf("unknwon command %d", item.command))
}
if err := writer.WriteArray(row); err != nil {
return err
}
}
return nil
}
func (fs *fileStorage) close() error {
return fs.file.Close()
}