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
126
127
128
129
130
|
package nvdmirror
import (
"compress/gzip"
"encoding/json"
"io"
"os"
"time"
"github.com/pablotron/cvez/atomictemp"
)
// JSON file backed URL cache.
type JsonCache struct {
dirty bool // has the cache been modified?
path string // backing JSON file
vals map[string]Entry // entries
}
// Create new JSON cache.
func NewJsonCache(path string) (JsonCache, error) {
r := JsonCache {
path: path,
}
// open path
f, err := os.OpenFile(path, os.O_CREATE, 0640)
if err != nil {
return r, err
}
defer f.Close()
// stat file
st, err := f.Stat()
if err != nil {
return r, err
}
vals := make(map[string]Entry)
if st.Size() > 0 {
// create gzip reader
zr, err := gzip.NewReader(f)
if err != nil {
return r, err
}
// read/decode json
d := json.NewDecoder(zr)
if err := d.Decode(&vals); err != nil {
return r, err
}
}
// save path and values
r.path = path
r.vals = vals
// return success
return r, nil
}
// Get cache entry
func (me JsonCache) Get(s string) (map[string]string, bool) {
if e, ok := me.vals[s]; ok {
return e.Headers, ok
} else {
return nil, false
}
}
// Set cache entry.
func (me *JsonCache) Set(s string, headers map[string]string) error {
// mark cache as dirty
me.dirty = true
// copy map to internal storage
newHeaders := make(map[string]string)
for k, v := range(headers) {
newHeaders[k] = v
}
// update entry
me.vals[s] = Entry {
Time: time.Now(),
Headers: newHeaders,
}
// return success
return nil
}
// Remove cache entry, if it exists.
func (me *JsonCache) Delete(s string) error {
me.dirty = true
delete(me.vals, s)
return nil
}
// Save and close cache.
func (me *JsonCache) Close() error {
if !me.dirty {
// return success
return nil
}
// open temp output file
err := atomictemp.Create(me.path, func(w io.Writer) error {
// encode/compress JSON
zw := gzip.NewWriter(w)
e := json.NewEncoder(zw)
if err := e.Encode(me.vals); err != nil {
return err
}
// flush changes
if err := zw.Flush(); err != nil {
return err
}
// return success
return nil
})
if err != nil {
return err
}
// Mark cache as clean, return success.
me.dirty = false
return nil
}
|