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.
bog/dataswamp/swamp_service.go

164 lines
3.3 KiB
Go

package dataswamp
import (
"caj-larsson/bog/dataswamp/namespace"
"caj-larsson/bog/dataswamp/swampfile"
"io"
"strconv"
"time"
// "errors"
// "fmt"
)
type SwampFileService struct {
namespace_repo namespace.Repository
swamp_file_repo swampfile.Repository
default_allowance_bytes int64
default_allowance_duration time.Duration
logger Logger
}
func NewSwampFileService(
namespace_repo namespace.Repository,
swamp_file_repo swampfile.Repository,
da_bytes int64,
da_duration time.Duration,
logger Logger,
) SwampFileService {
return SwampFileService{namespace_repo, swamp_file_repo, da_bytes, da_duration, logger}
}
func (s SwampFileService) getOrCreateNs(namespace_in string) *namespace.Namespace {
ns, err := s.namespace_repo.GetByName(namespace_in)
if err == namespace.ErrNotExists {
new_ns := namespace.Namespace{
0,
namespace_in,
time.Now(),
s.default_allowance_duration,
namespace.FileSizeQuota{s.default_allowance_bytes, 0},
namespace.FileStat{0, 0},
namespace.FileStat{0, 0},
namespace.FileStat{0, 0},
}
created_ns, err := s.namespace_repo.Create(new_ns)
if err != nil {
panic(err)
}
return created_ns
}
if err != nil {
panic(err)
}
return ns
}
func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, size int64) error {
ns := s.getOrCreateNs(ref.UserAgent)
r, err := ref.Clean(true)
if err != nil {
return err
}
if !ns.FileQuota.Allows(size) {
return namespace.ErrExceedQuota
}
f, err := s.swamp_file_repo.Create(r.Path, strconv.FormatInt(ns.ID, 10))
if err != nil {
return err
}
ns.Usage = ns.Usage.Add(-f.Size())
written, err := io.CopyN(f, src, size)
if written < size {
s.swamp_file_repo.Delete(r.Path, strconv.FormatInt(ns.ID, 10))
return swampfile.ErrContentSizeExaggerated
}
var buf = make([]byte, 1)
overread, err := src.Read(buf)
if overread > 0 || err != io.EOF {
s.swamp_file_repo.Delete(r.Path, strconv.FormatInt(ns.ID, 10))
return swampfile.ErrContentSizeExceeded
}
f.Close()
uq, err := ns.FileQuota.Add(size)
if err != nil {
return err
}
ns.FileQuota = *uq
ns.Usage = ns.Usage.Add(size)
ns.Upload = ns.Upload.Add(size)
s.namespace_repo.Update(ns.ID, *ns)
return nil
}
func (s SwampFileService) OpenOutFile(ref swampfile.FileReference) (swampfile.SwampOutFile, error) {
ns := s.getOrCreateNs(ref.UserAgent)
r, err := ref.Clean(true)
if err != nil {
return nil, err
}
f, err := s.swamp_file_repo.Open(r.Path, strconv.FormatInt(ns.ID, 10))
if err != nil {
return nil, err
}
ns.Download = ns.Download.Add(f.Size())
s.namespace_repo.Update(ns.ID, *ns)
return f, nil
}
func (s SwampFileService) NamespaceStats() ([]namespace.Namespace, error) {
return s.namespace_repo.All()
}
func (s SwampFileService) CleanUpExpiredFiles() error {
s.logger.Info("Cleaning up expired files")
nss, err := s.namespace_repo.All()
if err != nil {
return err
}
for _, ns := range nss {
expiry := time.Now().Add(-ns.AllowanceDuration)
dfs, err := s.swamp_file_repo.DeleteOlderThan(strconv.FormatInt(ns.ID, 10), expiry)
for _, df := range dfs {
dq, err := ns.FileQuota.Remove(df.Size)
if err != nil {
dq.CurrentUsage = 0
}
ns.FileQuota = *dq
}
if err != nil {
panic(err)
}
s.namespace_repo.Update(ns.ID, ns)
}
return nil
}