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.

145 lines
2.7 KiB
Go

package store
import (
"fmt"
"io"
"os"
"path"
"git.phc.dm.unipi.it/phc/storage/utils"
)
type Store interface {
// Create a new object by reading from the given io.Reader and returns its new id
Create(r io.Reader) (string, error)
// Read the object identified by "id" into the given io.Writer
Read(id string, w io.Writer) error
// Update the object identified by "id" by reading from the given io.Reader
Update(id string, r io.Reader) error
// Delete the object with the given id
Delete(id string) error
}
//
// In Memory Byte Store
//
type memStore struct {
objects map[string][]byte
}
func NewMemStore() Store {
return &memStore{
objects: map[string][]byte{},
}
}
// Create a new object by reading from the given io.Reader and returns its new id
func (m *memStore) Create(r io.Reader) (string, error) {
id := utils.GenerateRandomString(16)
data, err := io.ReadAll(r)
if err != nil {
return "", err
}
m.objects[id] = data
return id, nil
}
// Read the object identified by "id" into the given io.Writer
func (m *memStore) Read(id string, w io.Writer) error {
data, found := m.objects[id]
if !found {
return fmt.Errorf("object with id %q not found", id)
}
if _, err := w.Write(data); err != nil {
return err
}
return nil
}
// Update the object identified by "id" by reading from the given io.Reader
func (m *memStore) Update(id string, r io.Reader) error {
data, err := io.ReadAll(r)
if err != nil {
return err
}
m.objects[id] = data
return nil
}
// Delete the object with the given id
func (m *memStore) Delete(id string) error {
if _, found := m.objects[id]; !found {
return fmt.Errorf("object with id %q not found", id)
}
delete(m.objects, id)
return nil
}
//
// Dir Store
//
type DirStore struct {
// BaseDir is the root folder of this Store
BaseDir string
// Prefix is the number of letters to use for the first layer of folders
Prefix int
}
func (d *DirStore) split(id string) (prefix, rest string) {
return id[:d.Prefix], id[d.Prefix:]
}
func (d *DirStore) Create(r io.Reader) (string, error) {
id := utils.GenerateRandomString(16)
prefix, rest := d.split(id)
os.MkdirAll(path.Join(d.BaseDir, prefix), os.ModePerm)
f, err := os.Create(path.Join(d.BaseDir, prefix, rest))
if err != nil {
return "", err
}
if _, err := io.Copy(f, r); err != nil {
return "", err
}
return id, nil
}
func (d *DirStore) Read(id string, w io.Writer) error {
prefix, rest := d.split(id)
f, err := os.Open(path.Join(d.BaseDir, prefix, rest))
if err != nil {
return err
}
if _, err := io.Copy(w, f); err != nil {
return err
}
return nil
}
func (d *DirStore) Update(id string, r io.Reader) error {
panic("TODO: Not implemented")
}
func (d *DirStore) Delete(id string) error {
panic("TODO: Not implemented")
}