2018-01-31 02:15:21 +01:00
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
|
2018-02-22 19:48:46 +01:00
|
|
|
"github.com/lbryio/lbry.go/errors"
|
2018-01-31 02:15:21 +01:00
|
|
|
)
|
|
|
|
|
2018-05-30 03:38:55 +02:00
|
|
|
// FileBlobStore is a local disk store.
|
2018-01-31 02:15:21 +01:00
|
|
|
type FileBlobStore struct {
|
|
|
|
dir string
|
|
|
|
|
|
|
|
initialized bool
|
|
|
|
}
|
|
|
|
|
2018-05-30 03:38:55 +02:00
|
|
|
// NewFileBlobStore returns an initialized file disk store pointer.
|
2018-01-31 02:15:21 +01:00
|
|
|
func NewFileBlobStore(dir string) *FileBlobStore {
|
|
|
|
return &FileBlobStore{dir: dir}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *FileBlobStore) path(hash string) string {
|
|
|
|
return path.Join(f.dir, hash)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *FileBlobStore) initOnce() error {
|
|
|
|
if f.initialized {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
defer func() { f.initialized = true }()
|
|
|
|
|
|
|
|
if stat, err := os.Stat(f.dir); err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
err2 := os.Mkdir(f.dir, 0755)
|
|
|
|
if err2 != nil {
|
|
|
|
return err2
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else if !stat.IsDir() {
|
|
|
|
return errors.Err("blob dir exists but is not a dir")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-05-30 03:38:55 +02:00
|
|
|
// Has returns T/F or Error if it the blob stored already. It will error with any IO disk error.
|
2018-01-31 02:15:21 +01:00
|
|
|
func (f *FileBlobStore) Has(hash string) (bool, error) {
|
|
|
|
err := f.initOnce()
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = os.Stat(f.path(hash))
|
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2018-05-30 03:38:55 +02:00
|
|
|
// Get returns the byte slice of the blob stored or will error if the blob doesn't exist.
|
2018-01-31 02:15:21 +01:00
|
|
|
func (f *FileBlobStore) Get(hash string) ([]byte, error) {
|
|
|
|
err := f.initOnce()
|
|
|
|
if err != nil {
|
|
|
|
return []byte{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
file, err := os.Open(f.path(hash))
|
|
|
|
if err != nil {
|
2018-02-07 21:21:20 +01:00
|
|
|
if os.IsNotExist(err) {
|
|
|
|
return []byte{}, errors.Err(ErrBlobNotFound)
|
|
|
|
}
|
2018-01-31 02:15:21 +01:00
|
|
|
return []byte{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return ioutil.ReadAll(file)
|
|
|
|
}
|
|
|
|
|
2018-05-30 03:38:55 +02:00
|
|
|
// Put stores the blob on disk or errors with any IO error.
|
2018-01-31 02:15:21 +01:00
|
|
|
func (f *FileBlobStore) Put(hash string, blob []byte) error {
|
|
|
|
err := f.initOnce()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return ioutil.WriteFile(f.path(hash), blob, 0644)
|
|
|
|
}
|
2018-02-02 22:49:20 +01:00
|
|
|
|
2018-05-30 03:38:55 +02:00
|
|
|
// PutSD stores the sd blob on the disk or errors with any IO error.
|
2018-02-02 22:49:20 +01:00
|
|
|
func (f *FileBlobStore) PutSD(hash string, blob []byte) error {
|
2018-05-30 03:38:55 +02:00
|
|
|
//Todo - need to handle when streaming hash is not present.
|
2018-02-02 22:49:20 +01:00
|
|
|
return f.Put(hash, blob)
|
|
|
|
}
|