forked from TrueCloudLab/frostfs-node
Evgenii Stratonikov
df055fead5
Besides VM stack item limit we also have restrictions on the size of
JSON for a stackitem, which is 128k. This limit is much harder to
calculate, because JSON representation includes type and the encoding is
different for different items. Thus is makes no sense to invent our own
default, so use the one provided by neo-go. But for container listing we
know exactly what we process, so use big enough value, which is tested.
Introduced in be8607a1f6
.
Refs #902
Refs https://github.com/nspcc-dev/neo-go/blob/v0.105.0/pkg/vm/stackitem/json.go#L353
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
62 lines
1.8 KiB
Go
62 lines
1.8 KiB
Go
package container
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
)
|
|
|
|
// ContainersOf returns a list of container identifiers belonging
|
|
// to the specified user of FrostFS system. If idUser is nil, returns the list of all containers.
|
|
//
|
|
// If remote RPC does not support neo-go session API, fallback to List() method.
|
|
func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) {
|
|
var rawID []byte
|
|
|
|
if idUser != nil {
|
|
rawID = idUser.WalletBytes()
|
|
}
|
|
|
|
var cidList []cid.ID
|
|
cb := func(item stackitem.Item) error {
|
|
rawID, err := client.BytesFromStackItem(item)
|
|
if err != nil {
|
|
return fmt.Errorf("could not get byte array from stack item (%s): %w", containersOfMethod, err)
|
|
}
|
|
|
|
var id cid.ID
|
|
|
|
err = id.Decode(rawID)
|
|
if err != nil {
|
|
return fmt.Errorf("decode container ID: %w", err)
|
|
}
|
|
|
|
cidList = append(cidList, id)
|
|
return nil
|
|
}
|
|
|
|
// We would like to have batch size as big as possible,
|
|
// to reduce the number of round-trips and avoid creating sessions.
|
|
// The limit depends on 2 things:
|
|
// 1. VM limits: max 2048 items on stack.
|
|
// 2. JSON encoded size for the item with type = 128k.
|
|
// It turns out, that for container ID the second limit is hit first,
|
|
// 512 is big enough value and it is beautiful.
|
|
const batchSize = 512
|
|
|
|
cnrHash := c.client.ContractAddress()
|
|
err := c.client.Morph().TestInvokeIterator(cb, batchSize, cnrHash, containersOfMethod, rawID)
|
|
if err != nil {
|
|
if errors.Is(err, unwrap.ErrNoSessionID) {
|
|
return c.List(idUser)
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return cidList, nil
|
|
}
|