diff options
Diffstat (limited to 'nvdmirror/jsoncache.go')
-rw-r--r-- | nvdmirror/jsoncache.go | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/nvdmirror/jsoncache.go b/nvdmirror/jsoncache.go new file mode 100644 index 0000000..7e84a94 --- /dev/null +++ b/nvdmirror/jsoncache.go @@ -0,0 +1,131 @@ +package nvdmirror + +import ( + "compress/gzip" + "encoding/json" + "os" + "path/filepath" + "time" +) + +// 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 + t, err := os.CreateTemp(filepath.Dir(me.path), "") + if err != nil { + return err + } + defer os.Remove(t.Name()) + + // encode/compress JSON + zw := gzip.NewWriter(t) + e := json.NewEncoder(zw) + if err = e.Encode(me.vals); err != nil { + return err + } + + // flush changes + if err = zw.Flush(); err != nil { + return err + } + + // rename to destination file + if err = os.Rename(t.Name(), me.path); err != nil { + return err + } + + // Mark cache as clean, return success. + me.dirty = false + return nil +} |