package blobstor import ( "context" "fmt" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) // ErrNoPlaceFound is returned when object can't be saved to any sub-storage component // because of the policy. var ErrNoPlaceFound = logicerr.New("couldn't find a place to store an object") // Put saves the object in BLOB storage. // // If object is "big", BlobStor saves the object in shallow dir. // Otherwise, BlobStor saves the object in blobonicza. In this // case the identifier of blobovnicza is returned. // // Returns any error encountered that // did not allow to completely save the object. func (b *BlobStor) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, error) { var ( startedAt = time.Now() success = false size = 0 ) defer func() { b.metrics.Put(time.Since(startedAt), size, success) }() ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Put", trace.WithAttributes( attribute.String("address", prm.Address.EncodeToString()), attribute.Bool("dont_compress", prm.DontCompress), )) defer span.End() b.modeMtx.RLock() defer b.modeMtx.RUnlock() if prm.Object != nil { prm.Address = object.AddressOf(prm.Object) } if prm.RawData == nil { // marshal object data, err := prm.Object.Marshal() if err != nil { return common.PutRes{}, fmt.Errorf("could not marshal the object: %w", err) } prm.RawData = data } size = len(prm.RawData) for i := range b.storage { if b.storage[i].Policy == nil || b.storage[i].Policy(prm.Object, prm.RawData) { res, err := b.storage[i].Storage.Put(ctx, prm) if err == nil { success = true logOp(b.log, putOp, prm.Address, b.storage[i].Storage.Type(), res.StorageID) } return res, err } } return common.PutRes{}, ErrNoPlaceFound }