Implemented storage interface
This commit is contained in:
parent
8b3914eba5
commit
e0a5fa281b
@ -4,7 +4,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@ -20,9 +19,10 @@ type Collection[T any] interface {
|
||||
|
||||
// collection is a hash map of homogeneous data.
|
||||
type collection[T any] struct {
|
||||
data sync.Map
|
||||
name string
|
||||
directory string
|
||||
data sync.Map
|
||||
storage Storage[T]
|
||||
name string
|
||||
root string
|
||||
}
|
||||
|
||||
// New creates a new collection with the given name.
|
||||
@ -35,7 +35,6 @@ func New[T any](directories ...string) (*collection[T], error) {
|
||||
}
|
||||
|
||||
directories = append([]string{home, ".ocean"}, directories...)
|
||||
directories = append(directories, name)
|
||||
directory := filepath.Join(directories...)
|
||||
err = os.MkdirAll(directory, 0700)
|
||||
|
||||
@ -44,11 +43,12 @@ func New[T any](directories ...string) (*collection[T], error) {
|
||||
}
|
||||
|
||||
c := &collection[T]{
|
||||
name: directories[len(directories)-1],
|
||||
directory: directory,
|
||||
name: name,
|
||||
root: directory,
|
||||
storage: &DirectoryStorage[T]{},
|
||||
}
|
||||
|
||||
return c, c.loadFromDisk()
|
||||
return c, c.storage.Init(c)
|
||||
}
|
||||
|
||||
// All returns a channel of all objects in the collection.
|
||||
@ -100,7 +100,7 @@ func (c *collection[T]) Get(key string) (*T, error) {
|
||||
// Set sets the value for the given key.
|
||||
func (c *collection[T]) Set(key string, value *T) {
|
||||
c.data.Store(key, value)
|
||||
err := c.writeFileToDisk(key, value)
|
||||
err := c.storage.Set(key, value)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -114,7 +114,7 @@ func (c *collection[T]) Delete(key string) {
|
||||
}
|
||||
|
||||
c.data.Delete(key)
|
||||
os.Remove(c.keyFile(key))
|
||||
c.storage.Delete(key)
|
||||
}
|
||||
|
||||
// Exists returns whether or not the key exists.
|
||||
@ -130,72 +130,3 @@ func (c *collection[T]) Clear() {
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// keyFile returns the file path for the given key.
|
||||
func (c *collection[T]) keyFile(key string) string {
|
||||
return filepath.Join(c.directory, key+".json")
|
||||
}
|
||||
|
||||
// loadFromDisk loads the collection data from the disk.
|
||||
func (c *collection[T]) loadFromDisk() error {
|
||||
dir, err := os.Open(c.directory)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer dir.Close()
|
||||
files, err := dir.Readdirnames(0)
|
||||
|
||||
for _, key := range files {
|
||||
fileError := c.loadFileFromDisk(key)
|
||||
|
||||
if fileError != nil {
|
||||
return fileError
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// loadFileFromDisk loads a single file from the disk.
|
||||
func (c *collection[T]) loadFileFromDisk(fileName string) error {
|
||||
file, err := os.Open(filepath.Join(c.directory, fileName))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value := new(T)
|
||||
decoder := NewDecoder(file)
|
||||
err = decoder.Decode(value)
|
||||
|
||||
if err != nil {
|
||||
file.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
key := strings.TrimSuffix(fileName, ".json")
|
||||
c.data.Store(key, value)
|
||||
return file.Close()
|
||||
}
|
||||
|
||||
// writeFileToDisk writes the value for the key to disk as a JSON file.
|
||||
func (c *collection[T]) writeFileToDisk(key string, value *T) error {
|
||||
fileName := c.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()
|
||||
}
|
||||
|
100
DirectoryStorage.go
Normal file
100
DirectoryStorage.go
Normal file
@ -0,0 +1,100 @@
|
||||
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.loadFromDisk()
|
||||
}
|
||||
|
||||
// Set saves the value in a file.
|
||||
func (ds *DirectoryStorage[T]) Set(key string, value *T) error {
|
||||
return ds.writeFileToDisk(key, value)
|
||||
}
|
||||
|
||||
// Delete deletes the file for the given key.
|
||||
func (ds *DirectoryStorage[T]) Delete(key string) error {
|
||||
return os.Remove(ds.keyFile(key))
|
||||
}
|
||||
|
||||
// keyFile returns the file path for the given key.
|
||||
func (ds *DirectoryStorage[T]) keyFile(key string) string {
|
||||
return filepath.Join(ds.directory, key+".json")
|
||||
}
|
||||
|
||||
// loadFromDisk loads the collection data from the disk.
|
||||
func (ds *DirectoryStorage[T]) loadFromDisk() 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.loadFileFromDisk(fileName)
|
||||
|
||||
if fileError != nil {
|
||||
return fileError
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// loadFileFromDisk loads a single file from the disk.
|
||||
func (ds *DirectoryStorage[T]) loadFileFromDisk(fileName string) error {
|
||||
file, err := os.Open(filepath.Join(ds.directory, fileName))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value := new(T)
|
||||
decoder := NewDecoder(file)
|
||||
err = decoder.Decode(value)
|
||||
|
||||
if err != nil {
|
||||
file.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
key := strings.TrimSuffix(fileName, ".json")
|
||||
ds.collection.data.Store(key, value)
|
||||
return file.Close()
|
||||
}
|
||||
|
||||
// writeFileToDisk writes the value for the key to disk as a JSON file.
|
||||
func (ds *DirectoryStorage[T]) writeFileToDisk(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()
|
||||
}
|
69
FileStorage.go
Normal file
69
FileStorage.go
Normal file
@ -0,0 +1,69 @@
|
||||
package ocean
|
||||
|
||||
// import (
|
||||
// "bufio"
|
||||
// "encoding/json"
|
||||
// "io"
|
||||
// "os"
|
||||
// "path/filepath"
|
||||
// )
|
||||
//
|
||||
// type FileStorage[T any] struct {
|
||||
// collection *collection[T]
|
||||
// dirty chan struct{}
|
||||
// }
|
||||
//
|
||||
// func (fs *FileStorage[T]) Init(c *collection[T]) error {
|
||||
// fs.collection = c
|
||||
// fileName := filepath.Join(c.root, c.name+".dat")
|
||||
// stream, err := os.OpenFile(fileName, os.O_RDONLY, 0600)
|
||||
//
|
||||
// if os.IsNotExist(err) {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// defer stream.Close()
|
||||
// return fs.readRecords(stream)
|
||||
// }
|
||||
//
|
||||
// func (fs *FileStorage[T]) Set(key string, value *T) error {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// func (fs *FileStorage[T]) Delete(key string) error {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// // readRecords reads the entire collection.
|
||||
// func (fs *FileStorage[T]) readRecords(stream io.Reader) error {
|
||||
// var (
|
||||
// key string
|
||||
// value []byte
|
||||
// )
|
||||
//
|
||||
// scanner := bufio.NewScanner(stream)
|
||||
//
|
||||
// for scanner.Scan() {
|
||||
// if key == "" {
|
||||
// key = scanner.Text()
|
||||
// continue
|
||||
// }
|
||||
//
|
||||
// value = scanner.Bytes()
|
||||
// object := new(T)
|
||||
// err := json.Unmarshal(value, object)
|
||||
//
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// fs.collection.data.Store(key, object)
|
||||
// key = ""
|
||||
// }
|
||||
//
|
||||
// return nil
|
||||
// }
|
7
Storage.go
Normal file
7
Storage.go
Normal file
@ -0,0 +1,7 @@
|
||||
package ocean
|
||||
|
||||
type Storage[T any] interface {
|
||||
Init(c *collection[T]) error
|
||||
Set(key string, value *T) error
|
||||
Delete(key string) error
|
||||
}
|
Loading…
Reference in New Issue
Block a user