2020-07-10 14:17:51 +00:00
|
|
|
package fsbucket
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"path/filepath"
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/bucket"
|
2020-07-10 14:17:51 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Get value by key.
|
2020-07-24 13:54:03 +00:00
|
|
|
func (b *Bucket) Get(key []byte) ([]byte, error) {
|
2020-07-10 14:17:51 +00:00
|
|
|
p := path.Join(b.dir, stringifyKey(key))
|
|
|
|
if _, err := os.Stat(p); os.IsNotExist(err) {
|
2020-07-24 13:54:03 +00:00
|
|
|
return nil, bucket.ErrNotFound
|
2020-07-10 14:17:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ioutil.ReadFile(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set value by key.
|
2020-07-24 13:54:03 +00:00
|
|
|
func (b *Bucket) Set(key, value []byte) error {
|
2020-07-10 14:17:51 +00:00
|
|
|
p := path.Join(b.dir, stringifyKey(key))
|
|
|
|
|
|
|
|
return ioutil.WriteFile(p, value, b.perm)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Del value by key.
|
2020-07-24 13:54:03 +00:00
|
|
|
func (b *Bucket) Del(key []byte) error {
|
2020-07-10 14:17:51 +00:00
|
|
|
p := path.Join(b.dir, stringifyKey(key))
|
|
|
|
if _, err := os.Stat(p); os.IsNotExist(err) {
|
2020-07-24 13:54:03 +00:00
|
|
|
return bucket.ErrNotFound
|
2020-07-10 14:17:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return os.Remove(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Has checks key exists.
|
2020-07-24 13:54:03 +00:00
|
|
|
func (b *Bucket) Has(key []byte) bool {
|
2020-07-10 14:17:51 +00:00
|
|
|
p := path.Join(b.dir, stringifyKey(key))
|
|
|
|
_, err := os.Stat(p)
|
|
|
|
|
|
|
|
return err == nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func listing(root string, fn func(path string, info os.FileInfo) error) error {
|
|
|
|
return filepath.Walk(root, func(p string, info os.FileInfo, err error) error {
|
|
|
|
if err != nil || info.IsDir() {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if fn == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return fn(p, info)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Size of bucket.
|
2020-07-24 13:54:03 +00:00
|
|
|
func (b *Bucket) Size() (size int64) {
|
2020-07-10 14:17:51 +00:00
|
|
|
err := listing(b.dir, func(_ string, info os.FileInfo) error {
|
|
|
|
size += info.Size()
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
size = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// List all bucket items.
|
2020-07-24 13:54:03 +00:00
|
|
|
func (b *Bucket) List() ([][]byte, error) {
|
2020-07-10 14:17:51 +00:00
|
|
|
buckets := make([][]byte, 0)
|
|
|
|
|
|
|
|
err := listing(b.dir, func(p string, info os.FileInfo) error {
|
|
|
|
buckets = append(buckets, decodeKey(info.Name()))
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
return buckets, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Filter bucket items by closure.
|
2020-07-24 13:54:03 +00:00
|
|
|
func (b *Bucket) Iterate(handler bucket.FilterHandler) error {
|
2020-07-10 14:17:51 +00:00
|
|
|
return listing(b.dir, func(p string, info os.FileInfo) error {
|
|
|
|
key := decodeKey(info.Name())
|
|
|
|
val, err := ioutil.ReadFile(p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !handler(key, val) {
|
2020-07-24 13:54:03 +00:00
|
|
|
return bucket.ErrIteratingAborted
|
2020-07-10 14:17:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close bucket (just empty).
|
2020-07-24 13:54:03 +00:00
|
|
|
func (b *Bucket) Close() error {
|
2020-07-10 14:17:51 +00:00
|
|
|
return os.RemoveAll(b.dir)
|
|
|
|
}
|