forked from TrueCloudLab/frostfs-node
If context has already been canceled, then there is no need to check other shards. At the same time, it is necessary to avoid handling context cancellation in each handler. Therefore, the context check has been moved to the shard iteration method, which now returns an error. Change-Id: I70030ace36593ce7d2b8376bee39fe82e9dbf88f Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
151 lines
3.9 KiB
Go
151 lines
3.9 KiB
Go
package engine
|
|
|
|
import (
|
|
"context"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// ContainerSizePrm groups parameters of ContainerSize operation.
|
|
type ContainerSizePrm struct {
|
|
cnr cid.ID
|
|
}
|
|
|
|
// ContainerSizeRes resulting values of ContainerSize operation.
|
|
type ContainerSizeRes struct {
|
|
size uint64
|
|
}
|
|
|
|
// ListContainersPrm groups parameters of ListContainers operation.
|
|
type ListContainersPrm struct{}
|
|
|
|
// ListContainersRes groups the resulting values of ListContainers operation.
|
|
type ListContainersRes struct {
|
|
containers []cid.ID
|
|
}
|
|
|
|
// SetContainerID sets the identifier of the container to estimate the size.
|
|
func (p *ContainerSizePrm) SetContainerID(cnr cid.ID) {
|
|
p.cnr = cnr
|
|
}
|
|
|
|
// Size returns calculated estimation of the container size.
|
|
func (r ContainerSizeRes) Size() uint64 {
|
|
return r.size
|
|
}
|
|
|
|
// Containers returns a list of identifiers of the containers in which local objects are stored.
|
|
func (r ListContainersRes) Containers() []cid.ID {
|
|
return r.containers
|
|
}
|
|
|
|
// ContainerSize returns the sum of estimation container sizes among all shards.
|
|
//
|
|
// Returns an error if executions are blocked (see BlockExecution).
|
|
func (e *StorageEngine) ContainerSize(ctx context.Context, prm ContainerSizePrm) (res ContainerSizeRes, err error) {
|
|
defer elapsed("ContainerSize", e.metrics.AddMethodDuration)()
|
|
|
|
err = e.execIfNotBlocked(func() error {
|
|
var csErr error
|
|
res, csErr = e.containerSize(ctx, prm)
|
|
return csErr
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
// ContainerSize calls ContainerSize method on engine to calculate sum of estimation container sizes among all shards.
|
|
func ContainerSize(ctx context.Context, e *StorageEngine, id cid.ID) (uint64, error) {
|
|
var prm ContainerSizePrm
|
|
|
|
prm.SetContainerID(id)
|
|
|
|
res, err := e.ContainerSize(ctx, prm)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return res.Size(), nil
|
|
}
|
|
|
|
func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) (ContainerSizeRes, error) {
|
|
var res ContainerSizeRes
|
|
err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) {
|
|
var csPrm shard.ContainerSizePrm
|
|
csPrm.SetContainerID(prm.cnr)
|
|
|
|
csRes, err := sh.ContainerSize(ctx, csPrm)
|
|
if err != nil {
|
|
e.reportShardError(ctx, sh, "can't get container size", err,
|
|
zap.Stringer("container_id", prm.cnr))
|
|
return false
|
|
}
|
|
|
|
res.size += csRes.Size()
|
|
|
|
return false
|
|
})
|
|
|
|
return res, err
|
|
}
|
|
|
|
// ListContainers returns a unique container IDs presented in the engine objects.
|
|
//
|
|
// Returns an error if executions are blocked (see BlockExecution).
|
|
func (e *StorageEngine) ListContainers(ctx context.Context, _ ListContainersPrm) (res ListContainersRes, err error) {
|
|
defer elapsed("ListContainers", e.metrics.AddMethodDuration)()
|
|
|
|
err = e.execIfNotBlocked(func() error {
|
|
var lcErr error
|
|
res, lcErr = e.listContainers(ctx)
|
|
return lcErr
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
// ListContainers calls ListContainers method on engine to get a unique container IDs presented in the engine objects.
|
|
func ListContainers(ctx context.Context, e *StorageEngine) ([]cid.ID, error) {
|
|
var prm ListContainersPrm
|
|
|
|
res, err := e.ListContainers(ctx, prm)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return res.Containers(), nil
|
|
}
|
|
|
|
func (e *StorageEngine) listContainers(ctx context.Context) (ListContainersRes, error) {
|
|
uniqueIDs := make(map[string]cid.ID)
|
|
|
|
if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) {
|
|
res, err := sh.ListContainers(ctx, shard.ListContainersPrm{})
|
|
if err != nil {
|
|
e.reportShardError(ctx, sh, "can't get list of containers", err)
|
|
return false
|
|
}
|
|
|
|
for _, cnr := range res.Containers() {
|
|
id := cnr.EncodeToString()
|
|
if _, ok := uniqueIDs[id]; !ok {
|
|
uniqueIDs[id] = cnr
|
|
}
|
|
}
|
|
|
|
return false
|
|
}); err != nil {
|
|
return ListContainersRes{}, err
|
|
}
|
|
|
|
result := make([]cid.ID, 0, len(uniqueIDs))
|
|
for _, v := range uniqueIDs {
|
|
result = append(result, v)
|
|
}
|
|
|
|
return ListContainersRes{
|
|
containers: result,
|
|
}, nil
|
|
}
|