package writecachebadger import ( "context" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" 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" "github.com/dgraph-io/badger/v4" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) // Get returns object from write-cache. // // Returns an error of type apistatus.ObjectNotFound if the requested object is missing in write-cache. func (c *cache) Get(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) { _, span := tracing.StartSpanFromContext(ctx, "writecache.Get", trace.WithAttributes( attribute.String("address", addr.EncodeToString()), )) defer span.End() obj, err := c.getInternal(addr) return obj, metaerr.Wrap(err) } func (c *cache) getInternal(addr oid.Address) (*objectSDK.Object, error) { found := false storageType := writecache.StorageTypeUndefined startedAt := time.Now() defer func() { c.metrics.Get(time.Since(startedAt), found, storageType) }() k := addr2key(addr) value, err := Get(c.db, k[:]) if err == nil { obj := objectSDK.New() found = true storageType = writecache.StorageTypeDB return obj, obj.Unmarshal(value) } return nil, logicerr.Wrap(apistatus.ObjectNotFound{}) } // Head returns object header from write-cache. // // Returns an error of type apistatus.ObjectNotFound if the requested object is missing in write-cache. func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) { _, span := tracing.StartSpanFromContext(ctx, "writecache.Head", trace.WithAttributes( attribute.String("address", addr.EncodeToString()), )) defer span.End() obj, err := c.getInternal(addr) if err != nil { return nil, metaerr.Wrap(err) } return obj.CutPayload(), nil } // Get fetches object from the underlying database. // Key should be a stringified address. // // Returns an error of type apistatus.ObjectNotFound if the requested object is missing in db. func Get(db *badger.DB, key []byte) ([]byte, error) { var value []byte err := db.View(func(tx *badger.Txn) error { it, err := tx.Get(key) if err != nil { if err == badger.ErrKeyNotFound { return logicerr.Wrap(apistatus.ObjectNotFound{}) } return err } v, err := it.ValueCopy(nil) if err != nil { return err } value = v return nil }) return value, metaerr.Wrap(err) }