forked from TrueCloudLab/frostfs-node
Initial commit
Initial public review release v0.10.0
This commit is contained in:
commit
dadfd90dcd
276 changed files with 46331 additions and 0 deletions
126
lib/transformer/restore.go
Normal file
126
lib/transformer/restore.go
Normal file
|
@ -0,0 +1,126 @@
|
|||
package transformer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/object"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
// ObjectRestorer is an interface of object restorer.
|
||||
ObjectRestorer interface {
|
||||
Type() object.Transform_Type
|
||||
Restore(context.Context, ...Object) ([]Object, error)
|
||||
}
|
||||
|
||||
restorePipeline struct {
|
||||
ObjectRestorer
|
||||
*sync.RWMutex
|
||||
items map[object.Transform_Type]ObjectRestorer
|
||||
}
|
||||
|
||||
splitRestorer struct{}
|
||||
)
|
||||
|
||||
var errEmptyObjList = errors.New("object list is empty")
|
||||
|
||||
var errMissingParentLink = errors.New("missing parent link")
|
||||
|
||||
func (s *restorePipeline) Restore(ctx context.Context, srcObjs ...Object) ([]Object, error) {
|
||||
if len(srcObjs) == 0 {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
var (
|
||||
objs = srcObjs
|
||||
err error
|
||||
)
|
||||
|
||||
for {
|
||||
_, th := objs[0].LastHeader(object.HeaderType(object.TransformHdr))
|
||||
if th == nil {
|
||||
break
|
||||
}
|
||||
|
||||
transform := th.Value.(*object.Header_Transform).Transform
|
||||
|
||||
tr, ok := s.items[transform.Type]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("missing restorer (%s)", transform.Type)
|
||||
}
|
||||
|
||||
if objs, err = tr.Restore(ctx, objs...); err != nil {
|
||||
return nil, errors.Wrapf(err, "restoration failed (%s)", transform.Type)
|
||||
}
|
||||
}
|
||||
|
||||
return objs, nil
|
||||
}
|
||||
|
||||
// NewRestorePipeline is a constructor of the pipeline of object restorers.
|
||||
func NewRestorePipeline(t ...ObjectRestorer) ObjectRestorer {
|
||||
m := make(map[object.Transform_Type]ObjectRestorer, len(t))
|
||||
|
||||
for i := range t {
|
||||
m[t[i].Type()] = t[i]
|
||||
}
|
||||
|
||||
return &restorePipeline{
|
||||
RWMutex: new(sync.RWMutex),
|
||||
items: m,
|
||||
}
|
||||
}
|
||||
|
||||
func (*splitRestorer) Type() object.Transform_Type {
|
||||
return object.Transform_Split
|
||||
}
|
||||
|
||||
func (*splitRestorer) Restore(ctx context.Context, objs ...Object) ([]Object, error) {
|
||||
if len(objs) == 0 {
|
||||
return nil, errEmptyObjList
|
||||
}
|
||||
|
||||
chain, err := GetChain(objs...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get chain of objects")
|
||||
}
|
||||
|
||||
obj := chain[len(chain)-1]
|
||||
|
||||
var (
|
||||
size uint64
|
||||
p = make([]byte, 0, len(chain[0].Payload)*len(chain))
|
||||
)
|
||||
|
||||
for j := 0; j < len(chain); j++ {
|
||||
p = append(p, chain[j].Payload...)
|
||||
size += chain[j].SystemHeader.PayloadLength
|
||||
}
|
||||
|
||||
obj.SystemHeader.PayloadLength = size
|
||||
obj.Payload = p
|
||||
|
||||
parent, err := lastLink(&obj, object.Link_Parent)
|
||||
if err != nil {
|
||||
return nil, errMissingParentLink
|
||||
}
|
||||
|
||||
obj.SystemHeader.ID = parent
|
||||
|
||||
err = deleteTransformer(&obj, object.Transform_Split)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []Object{obj}, nil
|
||||
}
|
||||
|
||||
// SplitRestorer is a splitted object restorer's constructor.
|
||||
func SplitRestorer() ObjectRestorer {
|
||||
return new(splitRestorer)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue