|
|
|
@ -3,6 +3,7 @@ package dataswamp
|
|
|
|
|
import (
|
|
|
|
|
"caj-larsson/bog/dataswamp/namespace"
|
|
|
|
|
"caj-larsson/bog/dataswamp/swampfile"
|
|
|
|
|
"caj-larsson/bog/util"
|
|
|
|
|
"io"
|
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
|
|
|
@ -10,56 +11,29 @@ import (
|
|
|
|
|
// "fmt"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type SwampFileService struct {
|
|
|
|
|
namespace_repo namespace.Repository
|
|
|
|
|
swamp_file_repo swampfile.Repository
|
|
|
|
|
default_allowance_bytes int64
|
|
|
|
|
default_allowance_duration time.Duration
|
|
|
|
|
logger Logger
|
|
|
|
|
type DataSwampService struct {
|
|
|
|
|
ns_svc namespace.NamespaceService
|
|
|
|
|
swamp_file_repo swampfile.Repository
|
|
|
|
|
logger util.Logger
|
|
|
|
|
eventBus util.EventBus
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewSwampFileService(
|
|
|
|
|
namespace_repo namespace.Repository,
|
|
|
|
|
func NewDataSwampService(
|
|
|
|
|
ns_svc namespace.NamespaceService,
|
|
|
|
|
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}
|
|
|
|
|
logger util.Logger,
|
|
|
|
|
) *DataSwampService {
|
|
|
|
|
s := DataSwampService{ns_svc, swamp_file_repo, logger, *util.NewEventBus()}
|
|
|
|
|
ns_svc.Wire(s.eventBus.Register, s.eventBus.Handle)
|
|
|
|
|
return &s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 DataSwampService) NamespaceStats() []namespace.Namespace {
|
|
|
|
|
return s.ns_svc.All()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, size int64) error {
|
|
|
|
|
ns := s.getOrCreateNs(ref.UserAgent)
|
|
|
|
|
func (s DataSwampService) SaveFile(ref swampfile.FileReference, src io.Reader, size int64) error {
|
|
|
|
|
ns := s.ns_svc.GetOrCreateNs(ref.UserAgent)
|
|
|
|
|
|
|
|
|
|
r, err := ref.Clean(true)
|
|
|
|
|
|
|
|
|
@ -74,13 +48,23 @@ func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, s
|
|
|
|
|
f, err := s.swamp_file_repo.Create(r.Path, strconv.FormatInt(ns.ID, 10))
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
// TODO: convert this into a different error.
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.eventBus.Handle(*util.NewEvent("FileUsed", struct {
|
|
|
|
|
Name string
|
|
|
|
|
Size int64
|
|
|
|
|
}{
|
|
|
|
|
ns.Name,
|
|
|
|
|
f.Size(),
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
// TODO: rewrite this into an interruptable loop that emits downloaded events
|
|
|
|
|
written, err := io.CopyN(f, src, size)
|
|
|
|
|
|
|
|
|
|
if written < size {
|
|
|
|
|
s.swamp_file_repo.Delete(r.Path, strconv.FormatInt(ns.ID, 10))
|
|
|
|
|
s.swamp_file_repo.Delete(r.Path, strconv.FormatInt(ns.ID, 10)) //
|
|
|
|
|
return swampfile.ErrContentSizeExaggerated
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -94,20 +78,19 @@ func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
s.eventBus.Handle(*util.NewEvent("FileRecieved", struct {
|
|
|
|
|
Name string
|
|
|
|
|
Size int64
|
|
|
|
|
}{
|
|
|
|
|
ns.Name,
|
|
|
|
|
written,
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s SwampFileService) OpenOutFile(ref swampfile.FileReference) (swampfile.SwampOutFile, error) {
|
|
|
|
|
ns := s.getOrCreateNs(ref.UserAgent)
|
|
|
|
|
func (s DataSwampService) OpenOutFile(ref swampfile.FileReference) (swampfile.SwampOutFile, error) {
|
|
|
|
|
ns := s.ns_svc.GetOrCreateNs(ref.UserAgent)
|
|
|
|
|
|
|
|
|
|
r, err := ref.Clean(true)
|
|
|
|
|
|
|
|
|
@ -121,41 +104,31 @@ func (s SwampFileService) OpenOutFile(ref swampfile.FileReference) (swampfile.Sw
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ns.Download = ns.Download.Add(f.Size())
|
|
|
|
|
s.namespace_repo.Update(ns.ID, *ns)
|
|
|
|
|
s.eventBus.Handle(*util.NewEvent("FileSent", f.Size()))
|
|
|
|
|
|
|
|
|
|
return f, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s SwampFileService) NamespaceStats() ([]namespace.Namespace, error) {
|
|
|
|
|
return s.namespace_repo.All()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s SwampFileService) CleanUpExpiredFiles() error {
|
|
|
|
|
func (s DataSwampService) CleanUpExpiredFiles() error {
|
|
|
|
|
s.logger.Info("Cleaning up expired files")
|
|
|
|
|
nss, err := s.namespace_repo.All()
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, ns := range nss {
|
|
|
|
|
for _, ns := range s.ns_svc.All() {
|
|
|
|
|
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)
|
|
|
|
|
for _, df := range dfs {
|
|
|
|
|
s.eventBus.Handle(*util.NewEvent("FileDeleted", struct {
|
|
|
|
|
Name string
|
|
|
|
|
Size int64
|
|
|
|
|
}{
|
|
|
|
|
ns.Name,
|
|
|
|
|
df.Size,
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|