2022-05-24 06:58:33 +00:00
|
|
|
package layer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-06-30 09:03:55 +00:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2022-05-26 13:11:14 +00:00
|
|
|
|
2023-03-07 14:38:08 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
2023-06-30 09:03:55 +00:00
|
|
|
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
2024-09-27 08:13:13 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/tree"
|
2023-08-23 11:07:52 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
2023-03-07 14:38:08 +00:00
|
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
2022-12-09 13:30:51 +00:00
|
|
|
"go.uber.org/zap"
|
2022-05-24 06:58:33 +00:00
|
|
|
)
|
|
|
|
|
2024-06-25 12:57:55 +00:00
|
|
|
func (n *Layer) GetObjectTagging(ctx context.Context, p *data.GetObjectTaggingParams) (string, map[string]string, error) {
|
2022-10-14 14:36:43 +00:00
|
|
|
var err error
|
2023-08-03 12:08:22 +00:00
|
|
|
owner := n.BearerOwner(ctx)
|
2022-06-07 09:12:07 +00:00
|
|
|
|
2022-10-14 14:36:43 +00:00
|
|
|
if len(p.ObjectVersion.VersionID) != 0 && p.ObjectVersion.VersionID != data.UnversionedObjectVersionID {
|
|
|
|
if tags := n.cache.GetTagging(owner, objectTaggingCacheKey(p.ObjectVersion)); tags != nil {
|
|
|
|
return p.ObjectVersion.VersionID, tags, nil
|
2022-08-05 02:19:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-14 14:36:43 +00:00
|
|
|
nodeVersion := p.NodeVersion
|
|
|
|
if nodeVersion == nil {
|
2022-12-20 08:38:58 +00:00
|
|
|
nodeVersion, err = n.getNodeVersionFromCacheOrFrostfs(ctx, p.ObjectVersion)
|
2022-10-14 14:36:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", nil, err
|
|
|
|
}
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
2022-10-14 14:36:43 +00:00
|
|
|
p.ObjectVersion.VersionID = nodeVersion.OID.EncodeToString()
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2022-10-14 14:36:43 +00:00
|
|
|
if tags := n.cache.GetTagging(owner, objectTaggingCacheKey(p.ObjectVersion)); tags != nil {
|
|
|
|
return p.ObjectVersion.VersionID, tags, nil
|
2022-08-03 21:26:14 +00:00
|
|
|
}
|
|
|
|
|
2022-10-14 14:36:43 +00:00
|
|
|
tags, err := n.treeService.GetObjectTagging(ctx, p.ObjectVersion.BktInfo, nodeVersion)
|
2022-05-24 06:58:33 +00:00
|
|
|
if err != nil {
|
2024-09-27 08:13:13 +00:00
|
|
|
if errors.Is(err, tree.ErrNodeNotFound) {
|
2023-06-30 09:03:55 +00:00
|
|
|
return "", nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
2022-06-07 09:12:07 +00:00
|
|
|
return "", nil, err
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2022-10-14 14:36:43 +00:00
|
|
|
n.cache.PutTagging(owner, objectTaggingCacheKey(p.ObjectVersion), tags)
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2022-10-14 14:36:43 +00:00
|
|
|
return p.ObjectVersion.VersionID, tags, nil
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2024-06-25 12:57:55 +00:00
|
|
|
func (n *Layer) PutObjectTagging(ctx context.Context, p *data.PutObjectTaggingParams) (err error) {
|
2024-06-25 12:24:29 +00:00
|
|
|
nodeVersion := p.NodeVersion
|
2022-10-14 14:36:43 +00:00
|
|
|
if nodeVersion == nil {
|
2022-12-20 08:38:58 +00:00
|
|
|
nodeVersion, err = n.getNodeVersionFromCacheOrFrostfs(ctx, p.ObjectVersion)
|
2022-10-14 14:36:43 +00:00
|
|
|
if err != nil {
|
2024-06-25 12:24:29 +00:00
|
|
|
return err
|
2022-10-14 14:36:43 +00:00
|
|
|
}
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
2022-10-14 14:36:43 +00:00
|
|
|
p.ObjectVersion.VersionID = nodeVersion.OID.EncodeToString()
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2022-10-14 14:36:43 +00:00
|
|
|
err = n.treeService.PutObjectTagging(ctx, p.ObjectVersion.BktInfo, nodeVersion, p.TagSet)
|
2022-05-24 06:58:33 +00:00
|
|
|
if err != nil {
|
2024-09-27 08:13:13 +00:00
|
|
|
if errors.Is(err, tree.ErrNodeNotFound) {
|
2024-06-25 12:24:29 +00:00
|
|
|
return fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
2024-06-25 12:24:29 +00:00
|
|
|
return err
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2023-08-03 12:08:22 +00:00
|
|
|
n.cache.PutTagging(n.BearerOwner(ctx), objectTaggingCacheKey(p.ObjectVersion), p.TagSet)
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2024-06-25 12:24:29 +00:00
|
|
|
return nil
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2024-06-25 12:57:55 +00:00
|
|
|
func (n *Layer) DeleteObjectTagging(ctx context.Context, p *data.ObjectVersion) error {
|
2022-05-26 13:11:14 +00:00
|
|
|
version, err := n.getNodeVersion(ctx, p)
|
2022-05-24 06:58:33 +00:00
|
|
|
if err != nil {
|
2024-06-25 12:24:29 +00:00
|
|
|
return err
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2022-09-13 09:44:18 +00:00
|
|
|
err = n.treeService.DeleteObjectTagging(ctx, p.BktInfo, version)
|
2022-05-24 06:58:33 +00:00
|
|
|
if err != nil {
|
2024-09-27 08:13:13 +00:00
|
|
|
if errors.Is(err, tree.ErrNodeNotFound) {
|
2024-06-25 12:24:29 +00:00
|
|
|
return fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
2024-06-25 12:24:29 +00:00
|
|
|
return err
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2022-08-09 00:01:29 +00:00
|
|
|
p.VersionID = version.OID.EncodeToString()
|
|
|
|
|
2022-10-03 14:33:49 +00:00
|
|
|
n.cache.DeleteTagging(objectTaggingCacheKey(p))
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2024-06-25 12:24:29 +00:00
|
|
|
return nil
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2024-06-25 12:57:55 +00:00
|
|
|
func (n *Layer) GetBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) (map[string]string, error) {
|
2023-08-03 12:08:22 +00:00
|
|
|
owner := n.BearerOwner(ctx)
|
2022-05-25 01:58:25 +00:00
|
|
|
|
2022-10-06 08:46:53 +00:00
|
|
|
if tags := n.cache.GetTagging(owner, bucketTaggingCacheKey(bktInfo.CID)); tags != nil {
|
2022-05-25 01:58:25 +00:00
|
|
|
return tags, nil
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2022-10-06 08:46:53 +00:00
|
|
|
tags, err := n.treeService.GetBucketTagging(ctx, bktInfo)
|
2024-09-27 08:13:13 +00:00
|
|
|
if err != nil && !errors.Is(err, tree.ErrNodeNotFound) {
|
2022-05-25 01:58:25 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2022-10-06 08:46:53 +00:00
|
|
|
n.cache.PutTagging(owner, bucketTaggingCacheKey(bktInfo.CID), tags)
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2022-05-25 01:58:25 +00:00
|
|
|
return tags, nil
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2024-06-25 12:57:55 +00:00
|
|
|
func (n *Layer) PutBucketTagging(ctx context.Context, bktInfo *data.BucketInfo, tagSet map[string]string) error {
|
2022-09-13 09:44:18 +00:00
|
|
|
if err := n.treeService.PutBucketTagging(ctx, bktInfo, tagSet); err != nil {
|
2022-05-25 01:58:25 +00:00
|
|
|
return err
|
|
|
|
}
|
2022-10-03 14:33:49 +00:00
|
|
|
|
2023-08-03 12:08:22 +00:00
|
|
|
n.cache.PutTagging(n.BearerOwner(ctx), bucketTaggingCacheKey(bktInfo.CID), tagSet)
|
2022-05-25 01:58:25 +00:00
|
|
|
|
|
|
|
return nil
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2024-06-25 12:57:55 +00:00
|
|
|
func (n *Layer) DeleteBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) error {
|
2022-10-03 14:33:49 +00:00
|
|
|
n.cache.DeleteTagging(bucketTaggingCacheKey(bktInfo.CID))
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2022-09-13 09:44:18 +00:00
|
|
|
return n.treeService.DeleteBucketTagging(ctx, bktInfo)
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2024-04-10 06:41:07 +00:00
|
|
|
func objectTaggingCacheKey(p *data.ObjectVersion) string {
|
2022-05-26 13:11:14 +00:00
|
|
|
return ".tagset." + p.BktInfo.CID.EncodeToString() + "." + p.ObjectName + "." + p.VersionID
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2022-06-27 09:08:26 +00:00
|
|
|
func bucketTaggingCacheKey(cnrID cid.ID) string {
|
2022-05-25 01:58:25 +00:00
|
|
|
return ".tagset." + cnrID.EncodeToString()
|
|
|
|
}
|
|
|
|
|
2024-06-25 12:57:55 +00:00
|
|
|
func (n *Layer) getNodeVersion(ctx context.Context, objVersion *data.ObjectVersion) (*data.NodeVersion, error) {
|
2022-05-26 13:11:14 +00:00
|
|
|
var err error
|
|
|
|
var version *data.NodeVersion
|
2022-05-24 06:58:33 +00:00
|
|
|
|
2022-08-08 22:35:26 +00:00
|
|
|
if objVersion.VersionID == data.UnversionedObjectVersionID {
|
2022-09-13 09:44:18 +00:00
|
|
|
version, err = n.treeService.GetUnversioned(ctx, objVersion.BktInfo, objVersion.ObjectName)
|
2022-05-26 13:11:14 +00:00
|
|
|
} else if len(objVersion.VersionID) == 0 {
|
2022-09-13 09:44:18 +00:00
|
|
|
version, err = n.treeService.GetLatestVersion(ctx, objVersion.BktInfo, objVersion.ObjectName)
|
2022-05-24 06:58:33 +00:00
|
|
|
} else {
|
2022-09-13 09:44:18 +00:00
|
|
|
versions, err2 := n.treeService.GetVersions(ctx, objVersion.BktInfo, objVersion.ObjectName)
|
2022-05-26 13:11:14 +00:00
|
|
|
if err2 != nil {
|
|
|
|
return nil, err2
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
for _, v := range versions {
|
2022-05-26 13:11:14 +00:00
|
|
|
if v.OID.EncodeToString() == objVersion.VersionID {
|
2022-05-24 06:58:33 +00:00
|
|
|
version = v
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2022-05-26 13:11:14 +00:00
|
|
|
if version == nil {
|
2023-06-30 09:03:55 +00:00
|
|
|
err = fmt.Errorf("%w: there isn't tree node with requested version id", s3errors.GetAPIError(s3errors.ErrNoSuchVersion))
|
2022-05-26 13:11:14 +00:00
|
|
|
}
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2024-01-17 14:26:02 +00:00
|
|
|
if err == nil && version.IsDeleteMarker && !objVersion.NoErrorOnDeleteMarker {
|
2023-06-30 09:03:55 +00:00
|
|
|
return nil, fmt.Errorf("%w: found version is delete marker", s3errors.GetAPIError(s3errors.ErrNoSuchKey))
|
2024-09-27 08:13:13 +00:00
|
|
|
} else if errors.Is(err, tree.ErrNodeNotFound) {
|
2023-06-30 09:03:55 +00:00
|
|
|
return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2024-01-17 14:26:02 +00:00
|
|
|
if err == nil && version != nil && !version.IsDeleteMarker {
|
2023-08-23 11:07:52 +00:00
|
|
|
n.reqLogger(ctx).Debug(logs.GetTreeNode,
|
2023-06-09 13:19:23 +00:00
|
|
|
zap.Stringer("cid", objVersion.BktInfo.CID), zap.Stringer("oid", version.OID))
|
2022-12-09 13:30:51 +00:00
|
|
|
}
|
|
|
|
|
2022-05-26 13:11:14 +00:00
|
|
|
return version, err
|
2022-05-24 06:58:33 +00:00
|
|
|
}
|
2022-08-30 12:19:28 +00:00
|
|
|
|
2024-06-25 12:57:55 +00:00
|
|
|
func (n *Layer) getNodeVersionFromCache(owner user.ID, o *data.ObjectVersion) *data.NodeVersion {
|
2022-08-30 12:19:28 +00:00
|
|
|
if len(o.VersionID) == 0 || o.VersionID == data.UnversionedObjectVersionID {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var objID oid.ID
|
|
|
|
if objID.DecodeString(o.VersionID) != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var addr oid.Address
|
|
|
|
addr.SetContainer(o.BktInfo.CID)
|
|
|
|
addr.SetObject(objID)
|
|
|
|
|
2022-10-03 14:33:49 +00:00
|
|
|
extObjectInfo := n.cache.GetObject(owner, addr)
|
2022-08-30 12:19:28 +00:00
|
|
|
if extObjectInfo == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return extObjectInfo.NodeVersion
|
|
|
|
}
|