2022-03-04 16:59:26 +01:00

96 lines
1.6 KiB
Go

package store
import (
"crypto/sha1"
"encoding/hex"
"errors"
"fmt"
"os"
"path/filepath"
"gitlab.celogeek.com/photos/api/internal/photoserrors"
)
type Store struct {
Path string
}
type Chunk struct {
*Store
Sum string
Bytes []byte
}
func (s *Store) NewChunk(b []byte) *Chunk {
sum := sha1.New()
sum.Write(b)
sumString := hex.EncodeToString(sum.Sum(nil))
return &Chunk{s, sumString, b}
}
func (s *Store) LoadChunk(sum string) (*Chunk, error) {
c := &Chunk{s, sum, nil}
if !c.FileExists() {
return nil, fmt.Errorf("chunk %s doesn't exists", sum)
}
b, err := os.ReadFile(c.Filename())
if err != nil {
return nil, err
}
c.Bytes = b
return c, nil
}
func (c *Chunk) Dir() string {
return filepath.Join(c.Path, "storage", c.Sum[0:1], c.Sum[1:2])
}
func (c *Chunk) Filename() string {
return filepath.Join(c.Dir(), c.Sum)
}
func (c *Chunk) FileExists() bool {
fs, err := os.Stat(c.Filename())
if errors.Is(err, os.ErrNotExist) {
return false
}
return !fs.IsDir()
}
func (c *Chunk) Mkdir() error {
return os.MkdirAll(c.Dir(), 0755)
}
func (c *Chunk) Save() error {
if c.FileExists() {
return photoserrors.ErrStoreChunkAlreadyExists
}
if err := c.Mkdir(); err != nil {
return err
}
fs, err := os.Create(c.Filename())
if err != nil {
return err
}
defer fs.Close()
_, err = fs.Write(c.Bytes)
return err
}
func (s *Store) Combine(sumb []string) (string, uint64, error) {
sum := sha1.New()
size := uint64(0)
for _, sb := range sumb {
c, err := s.LoadChunk(sb)
if err != nil {
return "", 0, err
}
sum.Write(c.Bytes)
size += uint64(len(c.Bytes))
}
return hex.EncodeToString(sum.Sum(nil)), size, nil
}