2021-01-28 15:58:57 +00:00
|
|
|
package container
|
|
|
|
|
|
|
|
import (
|
2022-05-12 16:37:46 +00:00
|
|
|
"crypto/sha256"
|
2021-05-18 08:12:51 +00:00
|
|
|
"fmt"
|
|
|
|
|
2023-03-07 13:38:26 +00:00
|
|
|
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
|
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
2021-01-28 15:58:57 +00:00
|
|
|
)
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// AnnounceLoadPrm groups parameters of AnnounceLoad operation.
|
|
|
|
type AnnounceLoadPrm struct {
|
2022-06-28 07:01:05 +00:00
|
|
|
a container.SizeEstimation
|
2022-01-31 13:34:01 +00:00
|
|
|
key []byte
|
2021-11-12 15:14:55 +00:00
|
|
|
|
|
|
|
client.InvokePrmOptional
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// SetAnnouncement sets announcement.
|
2022-06-28 07:01:05 +00:00
|
|
|
func (a2 *AnnounceLoadPrm) SetAnnouncement(a container.SizeEstimation) {
|
2022-01-31 13:34:01 +00:00
|
|
|
a2.a = a
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// SetReporter sets public key of the reporter.
|
|
|
|
func (a2 *AnnounceLoadPrm) SetReporter(key []byte) {
|
|
|
|
a2.key = key
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// AnnounceLoad saves container size estimation calculated by storage node
|
2023-02-05 15:59:38 +00:00
|
|
|
// with key in FrostFS system through Container contract call.
|
2022-01-31 13:34:01 +00:00
|
|
|
//
|
|
|
|
// Returns any error encountered that caused the saving to interrupt.
|
|
|
|
func (c *Client) AnnounceLoad(p AnnounceLoadPrm) error {
|
2022-05-12 16:37:46 +00:00
|
|
|
binCnr := make([]byte, sha256.Size)
|
2022-06-28 07:01:05 +00:00
|
|
|
p.a.Container().Encode(binCnr)
|
2022-05-12 16:37:46 +00:00
|
|
|
|
2021-11-09 20:52:29 +00:00
|
|
|
prm := client.InvokePrm{}
|
2022-01-29 13:06:36 +00:00
|
|
|
prm.SetMethod(putSizeMethod)
|
2022-06-28 07:01:05 +00:00
|
|
|
prm.SetArgs(p.a.Epoch(), binCnr, p.a.Value(), p.key)
|
2022-01-31 13:34:01 +00:00
|
|
|
prm.InvokePrmOptional = p.InvokePrmOptional
|
2021-11-09 20:52:29 +00:00
|
|
|
|
|
|
|
err := c.client.Invoke(prm)
|
2021-05-18 08:12:51 +00:00
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return fmt.Errorf("could not invoke method (%s): %w", putSizeMethod, err)
|
2021-05-18 08:12:51 +00:00
|
|
|
}
|
|
|
|
return nil
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// EstimationID is an identity of container load estimation inside Container contract.
|
|
|
|
type EstimationID []byte
|
2021-01-28 15:58:57 +00:00
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// 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) {
|
2021-11-09 20:52:29 +00:00
|
|
|
invokePrm := client.TestInvokePrm{}
|
2022-01-29 13:06:36 +00:00
|
|
|
invokePrm.SetMethod(listSizesMethod)
|
2022-03-11 09:28:34 +00:00
|
|
|
invokePrm.SetArgs(epoch)
|
2021-11-09 20:52:29 +00:00
|
|
|
|
|
|
|
prms, err := c.client.TestInvoke(invokePrm)
|
2021-01-28 15:58:57 +00:00
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not perform test invocation (%s): %w", listSizesMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
} else if ln := len(prms); ln != 1 {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("unexpected stack item count (%s): %d", listSizesMethod, ln)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
prms, err = client.ArrayFromStackItem(prms[0])
|
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listSizesMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
res := make([]EstimationID, 0, len(prms))
|
2021-01-28 15:58:57 +00:00
|
|
|
for i := range prms {
|
|
|
|
id, err := client.BytesFromStackItem(prms[i])
|
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not get ID byte array from stack item (%s): %w", listSizesMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
res = append(res, id)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// Estimation is a structure of single container load estimation
|
|
|
|
// reported by storage node.
|
2021-01-28 15:58:57 +00:00
|
|
|
type Estimation struct {
|
2022-01-31 13:34:01 +00:00
|
|
|
Size uint64
|
2021-01-28 15:58:57 +00:00
|
|
|
|
|
|
|
Reporter []byte
|
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// Estimations is a structure of grouped container load estimation inside Container contract.
|
2021-01-28 15:58:57 +00:00
|
|
|
type Estimations struct {
|
2022-05-31 17:00:41 +00:00
|
|
|
ContainerID cid.ID
|
2021-01-28 15:58:57 +00:00
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
Values []Estimation
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
// 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))
|
2021-01-28 15:58:57 +00:00
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
prms, err := c.client.TestInvoke(prm)
|
2021-01-28 15:58:57 +00:00
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not perform test invocation (%s): %w", getSizeMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
} else if ln := len(prms); ln != 1 {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("unexpected stack item count (%s): %d", getSizeMethod, ln)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
prms, err = client.ArrayFromStackItem(prms[0])
|
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not get stack items of estimation fields from stack item (%s): %w", getSizeMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
} else if ln := len(prms); ln != 2 {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("unexpected stack item count of estimations fields (%s)", getSizeMethod)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-05-31 17:00:41 +00:00
|
|
|
rawCnr, err := client.BytesFromStackItem(prms[0])
|
2021-01-28 15:58:57 +00:00
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not get container ID byte array from stack item (%s): %w", getSizeMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
prms, err = client.ArrayFromStackItem(prms[1])
|
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not get estimation list array from stack item (%s): %w", getSizeMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
var cnr cid.ID
|
|
|
|
|
2022-05-31 17:00:41 +00:00
|
|
|
err = cnr.Decode(rawCnr)
|
2022-05-12 16:37:46 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("decode container ID: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
v2 := new(v2refs.ContainerID)
|
2022-05-31 17:00:41 +00:00
|
|
|
v2.SetValue(rawCnr)
|
2022-01-31 13:34:01 +00:00
|
|
|
res := &Estimations{
|
2022-05-31 17:00:41 +00:00
|
|
|
ContainerID: cnr,
|
2022-01-31 13:34:01 +00:00
|
|
|
Values: make([]Estimation, 0, len(prms)),
|
|
|
|
}
|
2021-01-28 15:58:57 +00:00
|
|
|
|
|
|
|
for i := range prms {
|
|
|
|
arr, err := client.ArrayFromStackItem(prms[i])
|
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not get estimation struct from stack item (%s): %w", getSizeMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
} else if ln := len(arr); ln != 2 {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("unexpected stack item count of estimation fields (%s)", getSizeMethod)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
reporter, err := client.BytesFromStackItem(arr[0])
|
2021-01-28 15:58:57 +00:00
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not get reporter byte array from stack item (%s): %w", getSizeMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
sz, err := client.IntFromStackItem(arr[1])
|
2021-01-28 15:58:57 +00:00
|
|
|
if err != nil {
|
2022-01-29 13:06:36 +00:00
|
|
|
return nil, fmt.Errorf("could not get estimation size from stack item (%s): %w", getSizeMethod, err)
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
res.Values = append(res.Values, Estimation{
|
|
|
|
Reporter: reporter,
|
|
|
|
Size: uint64(sz),
|
|
|
|
})
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 13:34:01 +00:00
|
|
|
return res, nil
|
2021-01-28 15:58:57 +00:00
|
|
|
}
|