You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
2.1 KiB
Go

package database
import (
"encoding/json"
"log"
"os"
"git.phc.dm.unipi.it/phc/storage/store"
)
type Database interface {
Buckets() ([]string, error)
CreateBucket(bucket string, options ...any) error
Bucket(bucket string) (store.Store, error)
}
type bucketInfo struct {
Name string `json:"name"`
Path string `json:"path"`
}
type jsonDB struct {
file string
BucketsInfo map[string]bucketInfo `json:"buckets"`
}
func NewJSON(file string) Database {
db := &jsonDB{
file: file,
BucketsInfo: map[string]bucketInfo{},
}
err := db.load()
if err != nil {
panic(err)
}
return db
}
func (db *jsonDB) setup() error {
if _, err := os.Stat(db.file); !os.IsNotExist(err) {
return nil
}
log.Printf("missing %q, creating empty database file", db.file)
f, err := os.Create(db.file)
defer f.Close()
if err != nil {
return err
}
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
if err := enc.Encode(&db); err != nil {
return err
}
return nil
}
func (db *jsonDB) store() error {
f, err := os.Create(db.file)
defer f.Close()
if err != nil {
return err
}
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
if err := enc.Encode(&db); err != nil {
return err
}
return nil
}
func (db *jsonDB) load() error {
if err := db.setup(); err != nil {
return err
}
f, err := os.Open(db.file)
defer f.Close()
if err != nil {
return err
}
if err := json.NewDecoder(f).Decode(&db); err != nil {
return err
}
return nil
}
func (db *jsonDB) Buckets() ([]string, error) {
db.load()
buckets := make([]string, 0, len(db.BucketsInfo))
for _, b := range db.BucketsInfo {
buckets = append(buckets, b.Name)
}
return buckets, nil
}
func (db *jsonDB) CreateBucket(bucket string, options ...any) error {
db.load()
defer db.store()
bi := bucketInfo{Name: bucket, Path: bucket + "/"}
if len(options) > 0 {
bi.Path = options[0].(string)
}
db.BucketsInfo[bucket] = bi
return nil
}
func (db *jsonDB) Bucket(bucket string) (store.Store, error) {
b := db.BucketsInfo[bucket]
return &store.DirStore{
BaseDir: b.Path,
Prefix: 2,
}, nil
}