Files
core/restream/store/json.go
2022-08-18 10:27:33 +03:00

147 lines
2.5 KiB
Go

package store
import (
gojson "encoding/json"
"fmt"
"os"
"sync"
"github.com/datarhei/core/v16/encoding/json"
"github.com/datarhei/core/v16/io/file"
"github.com/datarhei/core/v16/log"
)
type JSONConfig struct {
Dir string
Logger log.Logger
}
type jsonStore struct {
filename string
dir string
logger log.Logger
// Mutex to serialize access to the backend
lock sync.RWMutex
}
var version uint64 = 4
func NewJSONStore(config JSONConfig) Store {
s := &jsonStore{
filename: "db.json",
dir: config.Dir,
logger: config.Logger,
}
if s.logger == nil {
s.logger = log.New("JSONStore")
}
return s
}
func (s *jsonStore) Load() (StoreData, error) {
s.lock.Lock()
defer s.lock.Unlock()
data, err := s.load(version)
if err != nil {
return NewStoreData(), err
}
data.sanitize()
return data, nil
}
func (s *jsonStore) Store(data StoreData) error {
if data.Version != version {
return fmt.Errorf("invalid version (have: %d, want: %d)", data.Version, version)
}
s.lock.RLock()
defer s.lock.RUnlock()
err := s.store(data)
if err != nil {
return fmt.Errorf("failed to store data: %w", err)
}
return nil
}
func (s *jsonStore) store(data StoreData) error {
jsondata, err := gojson.MarshalIndent(&data, "", " ")
if err != nil {
return err
}
tmpfile, err := os.CreateTemp(s.dir, s.filename)
if err != nil {
return err
}
defer os.Remove(tmpfile.Name())
if _, err := tmpfile.Write(jsondata); err != nil {
return err
}
if err := tmpfile.Close(); err != nil {
return err
}
filename := s.dir + "/" + s.filename
if err := file.Rename(tmpfile.Name(), filename); err != nil {
return err
}
s.logger.WithField("file", filename).Debug().Log("Stored data")
return nil
}
type storeVersion struct {
Version uint64 `json:"version"`
}
func (s *jsonStore) load(version uint64) (StoreData, error) {
r := NewStoreData()
filename := s.dir + "/" + s.filename
_, err := os.Stat(filename)
if err != nil {
if os.IsNotExist(err) {
return r, nil
}
return r, err
}
jsondata, err := os.ReadFile(filename)
if err != nil {
return r, err
}
var db storeVersion
if err = gojson.Unmarshal(jsondata, &db); err != nil {
return r, json.FormatError(jsondata, err)
}
if db.Version != version {
return r, fmt.Errorf("unsupported version of the DB file (want: %d, have: %d)", version, db.Version)
}
if err = gojson.Unmarshal(jsondata, &r); err != nil {
return r, json.FormatError(jsondata, err)
}
s.logger.WithField("file", filename).Debug().Log("Read data")
return r, nil
}