107 lines
2.2 KiB
Go
Raw Normal View History

2023-07-10 14:27:41 +00:00
package storage
2023-07-07 16:05:52 +00:00
import (
"os"
"path/filepath"
"strings"
2023-07-10 14:27:41 +00:00
"git.akyoto.dev/go/ocean"
2023-07-07 16:05:52 +00:00
)
2023-07-10 14:27:41 +00:00
// Directory creates a directory and stores every record in a separate file.
type Directory[T any] struct {
collection ocean.Collection[T]
2023-07-07 16:05:52 +00:00
directory string
}
// Init loads all existing records from the directory.
2023-07-10 14:27:41 +00:00
func (ds *Directory[T]) Init(c ocean.Collection[T]) error {
2023-07-07 16:05:52 +00:00
ds.collection = c
2023-07-10 14:27:41 +00:00
ds.directory = filepath.Join(c.Root(), c.Name())
2023-07-07 16:05:52 +00:00
os.Mkdir(ds.directory, 0700)
2023-07-08 15:26:36 +00:00
return ds.read()
2023-07-07 16:05:52 +00:00
}
// Set saves the value in a file.
2023-07-10 14:27:41 +00:00
func (ds *Directory[T]) Set(key string, value *T) error {
2023-07-08 15:26:36 +00:00
return ds.writeFile(key, value)
2023-07-07 16:05:52 +00:00
}
// Delete deletes the file for the given key.
2023-07-10 14:27:41 +00:00
func (ds *Directory[T]) Delete(key string) error {
2023-07-07 16:05:52 +00:00
return os.Remove(ds.keyFile(key))
}
2023-07-10 14:27:41 +00:00
// Sync does nothing when using directory storage.
func (ds *Directory[T]) Sync() {}
2023-07-08 15:26:36 +00:00
// read loads the collection data from the disk.
2023-07-10 14:27:41 +00:00
func (ds *Directory[T]) read() error {
2023-07-07 16:05:52 +00:00
dir, err := os.Open(ds.directory)
if err != nil {
return err
}
defer dir.Close()
files, err := dir.Readdirnames(0)
for _, fileName := range files {
2023-07-08 15:26:36 +00:00
fileError := ds.readFile(fileName)
2023-07-07 16:05:52 +00:00
if fileError != nil {
return fileError
}
}
return err
}
2023-07-08 15:26:36 +00:00
// readFile loads a single file from the disk.
2023-07-10 14:27:41 +00:00
func (ds *Directory[T]) readFile(fileName string) error {
2023-07-08 15:26:36 +00:00
fileName = filepath.Join(ds.directory, fileName)
file, err := os.Open(fileName)
2023-07-07 16:05:52 +00:00
if err != nil {
return err
}
2023-07-08 15:26:36 +00:00
defer file.Close()
2023-07-07 16:05:52 +00:00
value := new(T)
decoder := NewDecoder(file)
err = decoder.Decode(value)
if err != nil {
return err
}
key := strings.TrimSuffix(fileName, ".json")
2023-07-10 14:27:41 +00:00
ds.collection.Data().Store(key, value)
2023-07-08 15:26:36 +00:00
return nil
2023-07-07 16:05:52 +00:00
}
2023-07-08 15:26:36 +00:00
// writeFile writes the value for the key to disk as a JSON file.
2023-07-10 14:27:41 +00:00
func (ds *Directory[T]) writeFile(key string, value *T) error {
2023-07-07 16:05:52 +00:00
fileName := ds.keyFile(key)
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
if err != nil {
return err
}
encoder := NewEncoder(file)
err = encoder.Encode(value)
if err != nil {
file.Close()
return err
}
return file.Close()
}
2023-07-08 15:26:36 +00:00
// keyFile returns the file path for the given key.
2023-07-10 14:27:41 +00:00
func (ds *Directory[T]) keyFile(key string) string {
2023-07-08 15:26:36 +00:00
return filepath.Join(ds.directory, key+".json")
}