2021-08-07 14:16:14 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"os"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
type metaStore struct {
|
|
|
|
ModuleAttributes map[string]moduleAttributeStore `json:"module_attributes"`
|
|
|
|
|
|
|
|
filename string
|
|
|
|
lock sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func newMetaStoreFromDisk(filename string) (*metaStore, error) {
|
|
|
|
out := &metaStore{
|
|
|
|
ModuleAttributes: map[string]moduleAttributeStore{},
|
|
|
|
filename: filename,
|
|
|
|
}
|
|
|
|
|
2021-08-22 13:23:23 +00:00
|
|
|
s, err := os.Stat(filename)
|
2021-08-07 14:16:14 +00:00
|
|
|
switch {
|
|
|
|
case err == nil:
|
|
|
|
// This is fine
|
|
|
|
|
|
|
|
case os.IsNotExist(err):
|
|
|
|
// No store yet, return empty store
|
|
|
|
return out, nil
|
|
|
|
|
|
|
|
default:
|
2021-08-22 13:23:23 +00:00
|
|
|
return nil, errors.Wrap(err, "getting file stats for store")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.IsDir() {
|
|
|
|
// A directory was provided
|
|
|
|
return nil, errors.New("store location is directory")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.Size() == 0 {
|
|
|
|
// An empty file was created, we don't care and will overwrite on save
|
|
|
|
return out, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err := os.Open(filename)
|
|
|
|
if err != nil {
|
2021-08-07 14:16:14 +00:00
|
|
|
return nil, errors.Wrap(err, "opening store")
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
return out, errors.Wrap(
|
|
|
|
json.NewDecoder(f).Decode(out),
|
|
|
|
"decoding store",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *metaStore) Save() error {
|
|
|
|
m.lock.RLock()
|
|
|
|
defer m.lock.RUnlock()
|
|
|
|
|
|
|
|
return m.save()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *metaStore) save() error {
|
|
|
|
f, err := os.Create(m.filename)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "creating storage file")
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
return errors.Wrap(
|
|
|
|
json.NewEncoder(f).Encode(m),
|
|
|
|
"encoding storage file",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *metaStore) Set(moduleID, key string, value interface{}) error {
|
|
|
|
m.lock.Lock()
|
|
|
|
defer m.lock.Unlock()
|
|
|
|
|
|
|
|
if m.ModuleAttributes[moduleID] == nil {
|
|
|
|
m.ModuleAttributes[moduleID] = make(moduleAttributeStore)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.ModuleAttributes[moduleID][key] = value
|
|
|
|
|
|
|
|
return errors.Wrap(m.save(), "saving store")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *metaStore) ReadWithLock(moduleID string, fn func(m moduleAttributeStore) error) error {
|
|
|
|
m.lock.RLock()
|
|
|
|
defer m.lock.RUnlock()
|
|
|
|
|
|
|
|
if m.ModuleAttributes[moduleID] == nil {
|
|
|
|
return fn(moduleAttributeStore{})
|
|
|
|
}
|
|
|
|
|
|
|
|
return fn(m.ModuleAttributes[moduleID])
|
|
|
|
}
|