frostfs-node/pkg/morph/client/container/load.go
Leonard Lyubich 1c6d37e821 [#328] morph/container: Add client methods related to size estimations
Implement API methods of the Container contracts client  corresponding
to the calls of the contract for storing the used space of the container
("putContainerSize", "getContainerSize", "listContainerSizes"). Extend
the wrapper over the client with methods abstracted from sidechen calls.
In particular, the method of storing the value will be used to record
the estimates of the used space of containers calculated by the network
participants.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2021-02-02 15:45:04 +03:00

207 lines
5.3 KiB
Go

package container
import (
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/pkg/errors"
)
// PutSizeArgs groups the arguments
// of "put container size" invocation call.
type PutSizeArgs struct {
epoch int64
size int64
cid []byte
reporterKey []byte
}
// SetEpoch sets the number of the epoch when
// size was estimated.
func (p *PutSizeArgs) SetEpoch(v uint64) {
p.epoch = int64(v)
}
// SetSize sets estimation of the container size.
func (p *PutSizeArgs) SetSize(v uint64) {
p.size = int64(v)
}
// SetContainerID sets identifier of the container
// being evaluated.
func (p *PutSizeArgs) SetContainerID(v []byte) {
p.cid = v
}
// SetReporterKey ыуеы public key of the storage node
// that collected size estimation.
func (p *PutSizeArgs) SetReporterKey(v []byte) {
p.reporterKey = v
}
// Put invokes the call of put container method
// of NeoFS Container contract.
func (c *Client) PutSize(args PutSizeArgs) error {
return errors.Wrapf(c.client.Invoke(
c.putSizeMethod,
args.epoch,
args.cid,
args.size,
args.reporterKey,
), "could not invoke method (%s)", c.putSizeMethod)
}
// ListSizesArgs groups the arguments
// of "list container sizes" test invoke call..
type ListSizesArgs struct {
epoch int64
}
// SetEpoch sets the number of the epoch to select
// the estimations.
func (p *ListSizesArgs) SetEpoch(v uint64) {
p.epoch = int64(v)
}
// ListSizesValues groups the stack items
// returned by "list container sizes" test invoke.
type ListSizesValues struct {
ids [][]byte
}
// Announcements returns list of identifiers of the
// container load estimations.
func (v *ListSizesValues) IDList() [][]byte {
return v.ids
}
// List performs the test invoke of "list container sizes"
// method of NeoFS Container contract.
func (c *Client) ListSizes(args ListSizesArgs) (*ListSizesValues, error) {
prms, err := c.client.TestInvoke(
c.listSizesMethod,
args.epoch,
)
if err != nil {
return nil, errors.Wrapf(err, "could not perform test invocation (%s)", c.listSizesMethod)
} else if ln := len(prms); ln != 1 {
return nil, errors.Errorf("unexpected stack item count (%s): %d", c.listSizesMethod, ln)
}
prms, err = client.ArrayFromStackItem(prms[0])
if err != nil {
return nil, errors.Wrapf(err, "could not get stack item array from stack item (%s)", c.listSizesMethod)
}
res := &ListSizesValues{
ids: make([][]byte, 0, len(prms)),
}
for i := range prms {
id, err := client.BytesFromStackItem(prms[i])
if err != nil {
return nil, errors.Wrapf(err, "could not get ID byte array from stack item (%s)", c.listSizesMethod)
}
res.ids = append(res.ids, id)
}
return res, nil
}
// GetSizeArgs groups the arguments
// of "get container size" test invoke call..
type GetSizeArgs struct {
id []byte
}
// SetID sets identifier of the container estimation.
func (p *GetSizeArgs) SetID(v []byte) {
p.id = v
}
type Estimation struct {
Size int64
Reporter []byte
}
type Estimations struct {
ContainerID []byte
Estimations []Estimation
}
// GetSizeValues groups the stack items
// returned by "get container size" test invoke.
type GetSizeValues struct {
est Estimations
}
// Estimations returns list of the container load estimations.
func (v *GetSizeValues) Estimations() Estimations {
return v.est
}
// GetContainerSize performs the test invoke of "get container size"
// method of NeoFS Container contract.
func (c *Client) GetContainerSize(args GetSizeArgs) (*GetSizeValues, error) {
prms, err := c.client.TestInvoke(
c.getSizeMethod,
args.id,
)
if err != nil {
return nil, errors.Wrapf(err, "could not perform test invocation (%s)", c.getSizeMethod)
} else if ln := len(prms); ln != 1 {
return nil, errors.Errorf("unexpected stack item count (%s): %d", c.getSizeMethod, ln)
}
prms, err = client.ArrayFromStackItem(prms[0])
if err != nil {
return nil, errors.Wrapf(err, "could not get stack items of estimation fields from stack item (%s)", c.getSizeMethod)
} else if ln := len(prms); ln != 2 {
return nil, errors.Errorf("unexpected stack item count of estimations fields (%s)", c.getSizeMethod)
}
es := Estimations{}
es.ContainerID, err = client.BytesFromStackItem(prms[0])
if err != nil {
return nil, errors.Wrapf(err, "could not get container ID byte array from stack item (%s)", c.getSizeMethod)
}
prms, err = client.ArrayFromStackItem(prms[1])
if err != nil {
return nil, errors.Wrapf(err, "could not get estimation list array from stack item (%s)", c.getSizeMethod)
}
es.Estimations = make([]Estimation, 0, len(prms))
for i := range prms {
arr, err := client.ArrayFromStackItem(prms[i])
if err != nil {
return nil, errors.Wrapf(err, "could not get estimation struct from stack item (%s)", c.getSizeMethod)
} else if ln := len(arr); ln != 2 {
return nil, errors.Errorf("unexpected stack item count of estimation fields (%s)", c.getSizeMethod)
}
e := Estimation{}
e.Reporter, err = client.BytesFromStackItem(arr[0])
if err != nil {
return nil, errors.Wrapf(err, "could not get reporter byte array from stack item (%s)", c.getSizeMethod)
}
e.Size, err = client.IntFromStackItem(arr[1])
if err != nil {
return nil, errors.Wrapf(err, "could not get estimation size from stack item (%s)", c.getSizeMethod)
}
es.Estimations = append(es.Estimations, e)
}
return &GetSizeValues{
est: es,
}, nil
}