2020-07-24 13:54:03 +00:00
|
|
|
package storage
|
2020-07-10 14:17:51 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"github.com/multiformats/go-multiaddr"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/object"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/service"
|
2020-07-24 13:54:03 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/localstore"
|
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/replication"
|
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/transport"
|
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
|
2020-07-10 14:17:51 +00:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// ObjectStorage is an interface of encapsulated ObjectReceptacle and ObjectSource pair.
|
|
|
|
ObjectStorage interface {
|
|
|
|
replication.ObjectReceptacle
|
|
|
|
replication.ObjectSource
|
|
|
|
}
|
|
|
|
|
|
|
|
objectStorage struct {
|
|
|
|
ls localstore.Localstore
|
2020-07-24 13:54:03 +00:00
|
|
|
executor transport.SelectiveContainerExecutor
|
2020-07-10 14:17:51 +00:00
|
|
|
log *zap.Logger
|
|
|
|
}
|
|
|
|
|
|
|
|
// ObjectStorageParams groups the parameters of ObjectStorage constructor.
|
|
|
|
ObjectStorageParams struct {
|
|
|
|
Localstore localstore.Localstore
|
2020-07-24 13:54:03 +00:00
|
|
|
SelectiveContainerExecutor transport.SelectiveContainerExecutor
|
2020-07-10 14:17:51 +00:00
|
|
|
Logger *zap.Logger
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
const objectSourceInstanceFailMsg = "could not create object source"
|
|
|
|
|
|
|
|
var errNilObject = errors.New("object is nil")
|
|
|
|
|
|
|
|
var errCouldNotGetObject = errors.New("could not get object from any node")
|
|
|
|
|
|
|
|
func (s *objectStorage) Put(ctx context.Context, params replication.ObjectStoreParams) error {
|
|
|
|
if params.Object == nil {
|
|
|
|
return errNilObject
|
|
|
|
} else if len(params.Nodes) == 0 {
|
|
|
|
if s.ls == nil {
|
|
|
|
return errEmptyLocalstore
|
|
|
|
}
|
|
|
|
return s.ls.Put(ctx, params.Object)
|
|
|
|
}
|
|
|
|
|
|
|
|
nodes := make([]multiaddr.Multiaddr, len(params.Nodes))
|
|
|
|
for i := range params.Nodes {
|
|
|
|
nodes[i] = params.Nodes[i].Node
|
|
|
|
}
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
return s.executor.Put(ctx, &transport.PutParams{
|
|
|
|
SelectiveParams: transport.SelectiveParams{
|
2020-07-10 14:17:51 +00:00
|
|
|
CID: params.Object.SystemHeader.CID,
|
|
|
|
Nodes: nodes,
|
|
|
|
TTL: service.NonForwardingTTL,
|
2020-07-24 13:54:03 +00:00
|
|
|
IDList: make([]object.ID, 1),
|
2020-07-10 14:17:51 +00:00
|
|
|
},
|
|
|
|
Object: params.Object,
|
|
|
|
Handler: func(node multiaddr.Multiaddr, valid bool) {
|
|
|
|
if params.Handler == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for i := range params.Nodes {
|
|
|
|
if params.Nodes[i].Node.Equal(node) {
|
|
|
|
params.Handler(params.Nodes[i], valid)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
func (s *objectStorage) Get(ctx context.Context, addr object.Address) (res *object.Object, err error) {
|
2020-07-10 14:17:51 +00:00
|
|
|
if s.ls != nil {
|
|
|
|
if has, err := s.ls.Has(addr); err == nil && has {
|
|
|
|
if res, err = s.ls.Get(addr); err == nil {
|
|
|
|
return res, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
if err = s.executor.Get(ctx, &transport.GetParams{
|
|
|
|
SelectiveParams: transport.SelectiveParams{
|
2020-07-10 14:17:51 +00:00
|
|
|
CID: addr.CID,
|
|
|
|
TTL: service.NonForwardingTTL,
|
2020-07-24 13:54:03 +00:00
|
|
|
IDList: []object.ID{addr.ObjectID},
|
|
|
|
Breaker: func(refs.Address) (cFlag transport.ProgressControlFlag) {
|
2020-07-10 14:17:51 +00:00
|
|
|
if res != nil {
|
2020-07-24 13:54:03 +00:00
|
|
|
cFlag = transport.BreakProgress
|
2020-07-10 14:17:51 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Handler: func(node multiaddr.Multiaddr, obj *object.Object) { res = obj },
|
|
|
|
}); err != nil {
|
|
|
|
return
|
|
|
|
} else if res == nil {
|
|
|
|
return nil, errCouldNotGetObject
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewObjectStorage encapsulates Localstore and SelectiveContainerExecutor
|
|
|
|
// and returns ObjectStorage interface.
|
|
|
|
func NewObjectStorage(p ObjectStorageParams) (ObjectStorage, error) {
|
|
|
|
if p.Logger == nil {
|
2020-07-24 13:54:03 +00:00
|
|
|
return nil, errors.Wrap(logger.ErrNilLogger, objectSourceInstanceFailMsg)
|
2020-07-10 14:17:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if p.Localstore == nil {
|
|
|
|
p.Logger.Warn("local storage not provided")
|
|
|
|
}
|
|
|
|
|
|
|
|
if p.SelectiveContainerExecutor == nil {
|
|
|
|
p.Logger.Warn("object container handler not provided")
|
|
|
|
}
|
|
|
|
|
|
|
|
return &objectStorage{
|
|
|
|
ls: p.Localstore,
|
|
|
|
executor: p.SelectiveContainerExecutor,
|
|
|
|
log: p.Logger,
|
|
|
|
}, nil
|
|
|
|
}
|