package writecachebadger import ( "context" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) // Put puts object to write-cache. // // Returns ErrReadOnly if write-cache is in R/O mode. // Returns ErrNotInitialized if write-cache has not been initialized yet. // Returns ErrOutOfSpace if saving an object leads to WC's size overflow. // Returns ErrBigObject if an objects exceeds maximum object size. func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, error) { _, span := tracing.StartSpanFromContext(ctx, "writecache.Put", trace.WithAttributes( attribute.String("address", prm.Address.EncodeToString()), attribute.Bool("dont_compress", prm.DontCompress), )) defer span.End() startedAt := time.Now() added := false storageType := writecache.StorageTypeUndefined defer func() { c.metrics.Put(time.Since(startedAt), added, storageType) }() c.modeMtx.RLock() defer c.modeMtx.RUnlock() if c.readOnly() { return common.PutRes{}, writecache.ErrReadOnly } sz := uint64(len(prm.RawData)) if sz > c.maxObjectSize { return common.PutRes{}, writecache.ErrBigObject } oi := objectInfo{ addr: prm.Address, obj: prm.Object, data: prm.RawData, } storageType = writecache.StorageTypeDB err := c.put(oi) if err == nil { added = true } return common.PutRes{}, err } // put persists objects to the write-cache database and // pushes the to the flush workers queue. func (c *cache) put(obj objectInfo) error { cacheSize := c.estimateCacheSize() if c.maxCacheSize < c.incSizeDB(cacheSize) { return writecache.ErrOutOfSpace } wb := c.db.NewWriteBatch() k := addr2key(obj.addr) _ = wb.Set(k[:], obj.data) err := wb.Flush() if err == nil { storagelog.Write(c.log, storagelog.AddressField(obj.addr), storagelog.StorageTypeField(wcStorageType), storagelog.OpField("db PUT"), ) c.objCounters.IncDB() } return err }