package blobtree import ( "context" "errors" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) func (b *BlobTree) Exists(ctx context.Context, prm common.ExistsPrm) (common.ExistsRes, error) { var ( startedAt = time.Now() success = false ) defer func() { b.cfg.metrics.Exists(time.Since(startedAt), success, prm.StorageID != nil) }() _, span := tracing.StartSpanFromContext(ctx, "BlobTree.Exists", trace.WithAttributes( attribute.String("path", b.cfg.rootPath), attribute.String("address", prm.Address.EncodeToString()), attribute.String("storage_id", storageIDToIdxStringSafe(prm.StorageID)), )) defer span.End() var res common.ExistsRes var err error if idx, ok := tryParseIdxFromStorageID(prm.StorageID); ok { res, err = b.existsFromIdx(prm.Address, idx) } else { res, err = b.findAndCheck(prm.Address) } success = err == nil return res, err } func (b *BlobTree) existsFromIdx(addr oid.Address, idx uint64) (common.ExistsRes, error) { dir := b.getDirectoryPath(addr) path := b.getFilePath(dir, idx) b.fileLock.RLock(path) defer b.fileLock.RUnlock(path) records, err := b.readFileContent(path) if err != nil { return common.ExistsRes{}, err } for i := range records { if records[i].Address.Equals(addr) { return common.ExistsRes{ Exists: true, }, nil } } return common.ExistsRes{}, nil } func (b *BlobTree) findAndCheck(addr oid.Address) (common.ExistsRes, error) { dir := b.getDirectoryPath(addr) _, err := b.findFileIdx(dir, addr) if err != nil { var notFound *apistatus.ObjectNotFound if errors.As(err, ¬Found) { return common.ExistsRes{}, nil } return common.ExistsRes{}, err } return common.ExistsRes{Exists: true}, nil }