2021-05-08 16:03:21 +00:00
|
|
|
package syncstore
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
)
|
|
|
|
|
|
|
|
type FSStore struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewFSStore(path string) (*FSStore, error) {
|
|
|
|
p, err := filepath.Abs(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
err = os.MkdirAll(p, 0700)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
var s = new(FSStore)
|
|
|
|
s.path = p
|
|
|
|
return s, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (drv *FSStore) storePath(id string) string {
|
|
|
|
return filepath.Join(drv.path, id[0:3], fmt.Sprintf("%s.json", id))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (drv *FSStore) RawSave(s *Blob) error {
|
|
|
|
body, err := json.Marshal(s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
filename := drv.storePath(s.ID)
|
|
|
|
dirname := filepath.Dir(filename)
|
|
|
|
err = os.Mkdir(dirname, 0700)
|
|
|
|
if err != nil && !os.IsExist(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
f, err := os.CreateTemp(dirname, "tmp-"+s.ID+".*")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-05-16 20:21:07 +00:00
|
|
|
tempname := f.Name()
|
2021-05-08 16:03:21 +00:00
|
|
|
_, err = f.Write(body)
|
2021-05-16 20:21:07 +00:00
|
|
|
err2 := f.Close()
|
2021-05-08 16:03:21 +00:00
|
|
|
if err != nil {
|
|
|
|
_ = os.Remove(f.Name())
|
|
|
|
return err
|
|
|
|
}
|
2021-05-16 20:21:07 +00:00
|
|
|
if err2 != nil {
|
|
|
|
return err2
|
|
|
|
}
|
|
|
|
return os.Rename(tempname, filename)
|
2021-05-08 16:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (drv *FSStore) RawLoad(id string) (*Blob, error) {
|
|
|
|
body, err := ioutil.ReadFile(drv.storePath(id))
|
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
return nil, SyncNotFoundError
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s := new(Blob)
|
|
|
|
err = json.Unmarshal(body, s)
|
|
|
|
return s, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (drv *FSStore) Exists(id string) bool {
|
|
|
|
st, err := os.Stat(drv.storePath(id))
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return (!st.IsDir()) && (st.Size() > 0)
|
|
|
|
}
|