2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-09-28 07:59:27 +01:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package filestore
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/zeebo/errs"
|
2019-06-05 14:06:06 +01:00
|
|
|
monkit "gopkg.in/spacemonkeygo/monkit.v2"
|
2018-09-28 07:59:27 +01:00
|
|
|
|
|
|
|
"storj.io/storj/storage"
|
|
|
|
)
|
|
|
|
|
2019-06-05 14:06:06 +01:00
|
|
|
var (
|
|
|
|
// Error is the default filestore error class
|
|
|
|
Error = errs.Class("filestore error")
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-06-05 14:06:06 +01:00
|
|
|
mon = monkit.Package()
|
|
|
|
|
|
|
|
_ storage.Blobs = (*Store)(nil)
|
|
|
|
)
|
2018-09-28 07:59:27 +01:00
|
|
|
|
|
|
|
// Store implements a blob store
|
|
|
|
type Store struct {
|
|
|
|
dir *Dir
|
|
|
|
}
|
|
|
|
|
|
|
|
// New creates a new disk blob store in the specified directory
|
|
|
|
func New(dir *Dir) *Store {
|
|
|
|
return &Store{dir}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewAt creates a new disk blob store in the specified directory
|
|
|
|
func NewAt(path string) (*Store, error) {
|
|
|
|
dir, err := NewDir(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, Error.Wrap(err)
|
|
|
|
}
|
|
|
|
return &Store{dir}, nil
|
|
|
|
}
|
|
|
|
|
2019-03-18 10:55:06 +00:00
|
|
|
// Close closes the store.
|
|
|
|
func (store *Store) Close() error { return nil }
|
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
// Open loads blob with the specified hash
|
2019-06-05 14:06:06 +01:00
|
|
|
func (store *Store) Open(ctx context.Context, ref storage.BlobRef) (_ storage.BlobReader, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
file, err := store.dir.Open(ctx, ref)
|
2019-06-03 10:17:09 +01:00
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
return nil, err
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
2019-06-03 10:17:09 +01:00
|
|
|
return nil, Error.Wrap(err)
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
2019-03-11 08:06:56 +00:00
|
|
|
return newBlobReader(file), nil
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
// Delete deletes blobs with the specified ref
|
2019-06-05 14:06:06 +01:00
|
|
|
func (store *Store) Delete(ctx context.Context, ref storage.BlobRef) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
err = store.dir.Delete(ctx, ref)
|
2019-03-11 08:06:56 +00:00
|
|
|
return Error.Wrap(err)
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// GarbageCollect tries to delete any files that haven't yet been deleted
|
2019-06-05 14:06:06 +01:00
|
|
|
func (store *Store) GarbageCollect(ctx context.Context) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
err = store.dir.GarbageCollect(ctx)
|
2019-03-11 08:06:56 +00:00
|
|
|
return Error.Wrap(err)
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
// Create creates a new blob that can be written
|
|
|
|
// optionally takes a size argument for performance improvements, -1 is unknown size
|
2019-06-05 14:06:06 +01:00
|
|
|
func (store *Store) Create(ctx context.Context, ref storage.BlobRef, size int64) (_ storage.BlobWriter, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
file, err := store.dir.CreateTemporaryFile(ctx, size)
|
2018-09-28 07:59:27 +01:00
|
|
|
if err != nil {
|
2019-03-11 08:06:56 +00:00
|
|
|
return nil, Error.Wrap(err)
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
2019-03-11 08:06:56 +00:00
|
|
|
return newBlobWriter(ref, store, file), nil
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
2019-03-18 10:55:06 +00:00
|
|
|
|
|
|
|
// FreeSpace returns how much space left in underlying directory
|
|
|
|
func (store *Store) FreeSpace() (int64, error) {
|
|
|
|
info, err := store.dir.Info()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return info.AvailableSpace, nil
|
|
|
|
}
|