frostfs-node/pkg/morph/client/container/load.go
Evgenii Stratonikov 32ec421ac7 [#1277] go.mod: Update api-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-26 17:27:41 +03:00

131 lines
4 KiB
Go

package container
import (
"fmt"
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
)
// EstimationID is an identity of container load estimation inside Container contract.
type EstimationID []byte
// ListLoadEstimationsByEpoch returns a list of container load estimations for to the specified epoch.
// The list is composed through Container contract call.
func (c *Client) ListLoadEstimationsByEpoch(epoch uint64) ([]EstimationID, error) {
invokePrm := client.TestInvokePrm{}
invokePrm.SetMethod(listSizesMethod)
invokePrm.SetArgs(epoch)
prms, err := c.client.TestInvoke(invokePrm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", listSizesMethod, err)
} else if ln := len(prms); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d", listSizesMethod, ln)
}
prms, err = client.ArrayFromStackItem(prms[0])
if err != nil {
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listSizesMethod, err)
}
res := make([]EstimationID, 0, len(prms))
for i := range prms {
id, err := client.BytesFromStackItem(prms[i])
if err != nil {
return nil, fmt.Errorf("could not get ID byte array from stack item (%s): %w", listSizesMethod, err)
}
res = append(res, id)
}
return res, nil
}
// Estimation is a structure of single container load estimation
// reported by storage node.
type Estimation struct {
Size uint64
Reporter []byte
}
// Estimations is a structure of grouped container load estimation inside Container contract.
type Estimations struct {
ContainerID cid.ID
Values []Estimation
}
// GetUsedSpaceEstimations returns a list of container load estimations by ID.
// The list is composed through Container contract call.
func (c *Client) GetUsedSpaceEstimations(id EstimationID) (*Estimations, error) {
prm := client.TestInvokePrm{}
prm.SetMethod(getSizeMethod)
prm.SetArgs([]byte(id))
prms, err := c.client.TestInvoke(prm)
if err != nil {
return nil, fmt.Errorf("could not perform test invocation (%s): %w", getSizeMethod, err)
} else if ln := len(prms); ln != 1 {
return nil, fmt.Errorf("unexpected stack item count (%s): %d", getSizeMethod, ln)
}
prms, err = client.ArrayFromStackItem(prms[0])
if err != nil {
return nil, fmt.Errorf("could not get stack items of estimation fields from stack item (%s): %w", getSizeMethod, err)
} else if ln := len(prms); ln != 2 {
return nil, fmt.Errorf("unexpected stack item count of estimations fields (%s)", getSizeMethod)
}
rawCnr, err := client.BytesFromStackItem(prms[0])
if err != nil {
return nil, fmt.Errorf("could not get container ID byte array from stack item (%s): %w", getSizeMethod, err)
}
prms, err = client.ArrayFromStackItem(prms[1])
if err != nil {
return nil, fmt.Errorf("could not get estimation list array from stack item (%s): %w", getSizeMethod, err)
}
var cnr cid.ID
err = cnr.Decode(rawCnr)
if err != nil {
return nil, fmt.Errorf("decode container ID: %w", err)
}
v2 := new(v2refs.ContainerID)
v2.SetValue(rawCnr)
res := &Estimations{
ContainerID: cnr,
Values: make([]Estimation, 0, len(prms)),
}
for i := range prms {
arr, err := client.ArrayFromStackItem(prms[i])
if err != nil {
return nil, fmt.Errorf("could not get estimation struct from stack item (%s): %w", getSizeMethod, err)
} else if ln := len(arr); ln != 2 {
return nil, fmt.Errorf("unexpected stack item count of estimation fields (%s)", getSizeMethod)
}
reporter, err := client.BytesFromStackItem(arr[0])
if err != nil {
return nil, fmt.Errorf("could not get reporter byte array from stack item (%s): %w", getSizeMethod, err)
}
sz, err := client.IntFromStackItem(arr[1])
if err != nil {
return nil, fmt.Errorf("could not get estimation size from stack item (%s): %w", getSizeMethod, err)
}
res.Values = append(res.Values, Estimation{
Reporter: reporter,
Size: uint64(sz),
})
}
return res, nil
}