-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathio.go
123 lines (115 loc) · 2.4 KB
/
io.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 d
import (
"bufio"
"encoding/json"
"flag"
"fmt"
"io"
"os"
"path/filepath"
"sync/atomic"
"github.com/cheggaaa/pb"
"github.com/liuzl/dict"
"github.com/liuzl/store"
"zliu.org/goutil"
)
var (
dir = flag.String("dict_dir", "dicts", "dir for dicts")
)
type Record struct {
K string `json:"k"`
V map[string]interface{} `json:"v"`
}
func Load(name string) (*Dictionary, error) {
kvDir := filepath.Join(*dir, name, "kv")
cedarDir := filepath.Join(*dir, name, "cedar")
kv, err := store.NewLevelStore(kvDir)
if err != nil {
return nil, err
}
cedar := dict.New()
if _, err = os.Stat(cedarDir); err == nil {
err = cedar.LoadFromFile(cedarDir, "gob")
if err != nil {
return nil, err
}
} else if !os.IsNotExist(err) {
return nil, err
}
d := &Dictionary{Name: name, kv: kv, cedar: cedar}
go d.flush()
return d, nil
}
func (d *Dictionary) Save() error {
cedarDir := filepath.Join(*dir, d.Name, "cedar")
fmt.Println(cedarDir, "saving")
if err := d.cedar.SaveToFile(cedarDir, "gob"); err != nil {
return err
}
atomic.StoreInt64(&d.changed, 0)
atomic.StoreInt64(&d.updated, 0)
return nil
}
func (d *Dictionary) Dump(path string) error {
wf, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600)
if err != nil {
return err
}
defer wf.Close()
err = d.kv.ForEach(nil, func(key, value []byte) (bool, error) {
var v map[string]interface{}
if err := store.BytesToObject(value, &v); err != nil {
return false, err
}
b, err := json.Marshal(&Record{string(key), v})
if err != nil {
return false, err
}
if _, err = wf.Write(append(b, '\n')); err != nil {
return false, err
}
return true, nil
})
if err != nil {
return err
}
return nil
}
func Build(src, dst string) (*Dictionary, error) {
count, err := goutil.FileLineCount(src)
if err != nil {
return nil, err
}
if count <= 0 {
return nil, fmt.Errorf("empty src file: %s", src)
}
d, err := Load(dst)
if err != nil {
return nil, err
}
fd, err := os.Open(src)
if err != nil {
return nil, err
}
defer fd.Close()
var rec Record
br := bufio.NewReader(fd)
bar := pb.StartNew(count)
for {
b, c := br.ReadBytes('\n')
if c == io.EOF {
break
}
if err = json.Unmarshal(b, &rec); err != nil {
return nil, err
}
if err = d.Update(rec.K, rec.V); err != nil {
return nil, err
}
bar.Increment()
}
if err = d.Save(); err != nil {
return nil, err
}
return d, nil
}