102 lines
2.1 KiB
Go
102 lines
2.1 KiB
Go
package ocean
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// DirectoryStorage creates a directory and stores every record in a separate file.
|
|
type DirectoryStorage[T any] struct {
|
|
collection *collection[T]
|
|
directory string
|
|
}
|
|
|
|
// Init loads all existing records from the directory.
|
|
func (ds *DirectoryStorage[T]) Init(c *collection[T]) error {
|
|
ds.collection = c
|
|
ds.directory = filepath.Join(c.root, c.name)
|
|
os.Mkdir(ds.directory, 0700)
|
|
return ds.read()
|
|
}
|
|
|
|
// Set saves the value in a file.
|
|
func (ds *DirectoryStorage[T]) Set(key string, value *T) error {
|
|
return ds.writeFile(key, value)
|
|
}
|
|
|
|
// Delete deletes the file for the given key.
|
|
func (ds *DirectoryStorage[T]) Delete(key string) error {
|
|
return os.Remove(ds.keyFile(key))
|
|
}
|
|
|
|
// read loads the collection data from the disk.
|
|
func (ds *DirectoryStorage[T]) read() error {
|
|
dir, err := os.Open(ds.directory)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer dir.Close()
|
|
files, err := dir.Readdirnames(0)
|
|
|
|
for _, fileName := range files {
|
|
fileError := ds.readFile(fileName)
|
|
|
|
if fileError != nil {
|
|
return fileError
|
|
}
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// readFile loads a single file from the disk.
|
|
func (ds *DirectoryStorage[T]) readFile(fileName string) error {
|
|
fileName = filepath.Join(ds.directory, fileName)
|
|
file, err := os.Open(fileName)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer file.Close()
|
|
value := new(T)
|
|
decoder := NewDecoder(file)
|
|
err = decoder.Decode(value)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
key := strings.TrimSuffix(fileName, ".json")
|
|
ds.collection.data.Store(key, value)
|
|
return nil
|
|
}
|
|
|
|
// writeFile writes the value for the key to disk as a JSON file.
|
|
func (ds *DirectoryStorage[T]) writeFile(key string, value *T) error {
|
|
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()
|
|
}
|
|
|
|
// keyFile returns the file path for the given key.
|
|
func (ds *DirectoryStorage[T]) keyFile(key string) string {
|
|
return filepath.Join(ds.directory, key+".json")
|
|
}
|