frostfs-node/pkg/services/object_manager/transformer/fmt.go
Leonard Lyubich 121137c62b [#30] object_manager: Implement object transformers
Define object writer interface. Implement payload size limiter that
restricts payload size of the object. Implement object format moulder that
fill verification fields and finalizes object structure.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2020-10-02 11:25:35 +03:00

97 lines
2.3 KiB
Go

package transformer
import (
"crypto/ecdsa"
"github.com/nspcc-dev/neofs-api-go/pkg"
objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/pkg/errors"
)
type formatter struct {
nextTarget ObjectTarget
key *ecdsa.PrivateKey
obj *object.RawObject
sz uint64
}
// NewFormatTarget returns ObjectTarget instance that finalizes object structure
// and writes it to the next target.
//
// Chunks must be written before the WriteHeader call.
//
// Object changes:
// - sets version to current SDK version;
// - sets payload size to the total length of all written chunks;
// - calculates and sets verification fields (ID, Signature).
func NewFormatTarget(key *ecdsa.PrivateKey, nextTarget ObjectTarget) ObjectTarget {
return &formatter{
nextTarget: nextTarget,
key: key,
}
}
func (f *formatter) WriteHeader(obj *object.RawObject) error {
f.obj = obj
return nil
}
func (f *formatter) Write(p []byte) (n int, err error) {
n, err = f.nextTarget.Write(p)
f.sz += uint64(n)
return
}
func (f *formatter) Close() (*AccessIdentifiers, error) {
f.obj.SetVersion(pkg.SDKVersion())
f.obj.SetPayloadSize(f.sz)
var parID *objectSDK.ID
if par := f.obj.GetParent(); par != nil && par.ToV2().GetHeader() != nil {
rawPar := objectSDK.NewRawFromV2(par.ToV2())
if err := setIDAndSignature(f.key, rawPar); err != nil {
return nil, errors.Wrap(err, "could not finalize parent object")
}
parID = rawPar.GetID()
f.obj.SetParent(rawPar.Object())
}
if err := setIDAndSignature(f.key, f.obj.SDK()); err != nil {
return nil, errors.Wrap(err, "could not finalize object")
}
if err := f.nextTarget.WriteHeader(f.obj); err != nil {
return nil, errors.Wrap(err, "could not write header to next target")
}
if _, err := f.nextTarget.Close(); err != nil {
return nil, errors.Wrap(err, "could not close next target")
}
return new(AccessIdentifiers).
WithSelfID(f.obj.GetID()).
WithParentID(parID), nil
}
func setIDAndSignature(key *ecdsa.PrivateKey, obj *objectSDK.RawObject) error {
if err := objectSDK.CalculateAndSetID(obj); err != nil {
return errors.Wrap(err, "could not set identifier")
}
if err := objectSDK.CalculateAndSetSignature(key, obj); err != nil {
return errors.Wrap(err, "could not set signature")
}
return nil
}