package engine import ( "context" "errors" "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "golang.org/x/sync/errgroup" ) func (e *StorageEngine) exists(ctx context.Context, addr oid.Address) (bool, error) { var shPrm shard.ExistsPrm shPrm.SetAddress(addr) var exists atomic.Bool eg, egCtx := errgroup.WithContext(ctx) egCtx, cancel := context.WithCancel(egCtx) defer cancel() e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { select { case <-egCtx.Done(): return true default: } eg.Go(func() error { res, err := sh.Exists(egCtx, shPrm) if err != nil { if errors.Is(err, context.Canceled) { return err } if client.IsErrObjectAlreadyRemoved(err) { return err } var siErr *objectSDK.SplitInfoError if errors.As(err, &siErr) { return err } if shard.IsErrObjectExpired(err) { return err } if !client.IsErrObjectNotFound(err) { e.reportShardError(sh, "could not check existence of object in shard", err) } return nil } if res.Exists() { exists.Store(true) cancel() } return nil }) return false }) err := eg.Wait() if client.IsErrObjectAlreadyRemoved(err) { return false, new(apistatus.ObjectAlreadyRemoved) } return exists.Load(), nil }