[#653] Support removal old combined objects

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2025-03-26 09:55:46 +03:00
parent 4a430257a4
commit 396c89f7bc
8 changed files with 88 additions and 28 deletions

View file

@ -72,7 +72,7 @@ type (
removalParams struct {
Auth frostfs.PrmAuth
BktInfo *data.BucketInfo
OIDs []oid.ID
OIDsInfo []data.OIDInfo
RequestID string
TraceID string
}
@ -733,8 +733,17 @@ func (n *Layer) removalRoutine(ctx context.Context) {
}
reqCtx, cancel := context.WithTimeout(ctx, n.features.RemoveOnReplaceTimeout())
for _, objID := range prm.OIDs {
if err := n.objectDeleteBase(reqCtx, prm.BktInfo, objID, prm.Auth); err != nil {
for _, oidInfo := range prm.OIDsInfo {
if oidInfo.IsCombined {
networkInfo, err := n.GetNetworkInfo(ctx)
if err == nil {
err = n.removeCombinedObject(reqCtx, prm.BktInfo, oidInfo.ID, networkInfo, prm.Auth)
}
if err != nil {
n.log.Warn(logs.FailedToRemoveOldUnversionedCombinedObject, zap.String("request_id", prm.RequestID),
zap.String("trace_id", prm.TraceID), zap.Error(err), logs.TagField(logs.TagExternalStorage))
}
} else if err := n.objectDeleteBase(reqCtx, prm.BktInfo, oidInfo.ID, prm.Auth); err != nil {
n.log.Warn(logs.FailedToRemoveOldUnversionedObject, zap.String("request_id", prm.RequestID),
zap.String("trace_id", prm.TraceID), zap.Error(err), logs.TagField(logs.TagExternalStorage))
}
@ -744,7 +753,7 @@ func (n *Layer) removalRoutine(ctx context.Context) {
}
}
func (n *Layer) tryRemove(ctx context.Context, bktInfo *data.BucketInfo, OIDs []oid.ID) {
func (n *Layer) tryRemove(ctx context.Context, bktInfo *data.BucketInfo, OIDsInfo []data.OIDInfo) {
if !n.features.RemoveOnReplace() {
return
}
@ -753,7 +762,7 @@ func (n *Layer) tryRemove(ctx context.Context, bktInfo *data.BucketInfo, OIDs []
prm := removalParams{
Auth: frostfs.PrmAuth{},
BktInfo: bktInfo,
OIDs: OIDs,
OIDsInfo: OIDsInfo,
RequestID: reqInfo.RequestID,
TraceID: reqInfo.TraceID,
}
@ -763,9 +772,9 @@ func (n *Layer) tryRemove(ctx context.Context, bktInfo *data.BucketInfo, OIDs []
select {
case n.removalChan <- prm:
default:
oidsStr := make([]string, len(OIDs))
for i, d := range OIDs {
oidsStr[i] = d.EncodeToString()
oidsStr := make([]string, len(OIDsInfo))
for i, d := range OIDsInfo {
oidsStr[i] = d.ID.EncodeToString()
}
n.reqLogger(ctx).Debug(logs.FailedToQueueOldUnversionedObjectToDelete,
@ -876,16 +885,16 @@ func (n *Layer) removeOldVersion(ctx context.Context, bkt *data.BucketInfo, node
}
if nodeVersion.IsCombined {
return "", n.removeCombinedObject(ctx, bkt, nodeVersion, networkInfo)
return "", n.removeCombinedObject(ctx, bkt, nodeVersion.OID, networkInfo, frostfs.PrmAuth{})
}
return "", n.objectDelete(ctx, bkt, nodeVersion.OID)
}
func (n *Layer) removeCombinedObject(ctx context.Context, bkt *data.BucketInfo, nodeVersion *data.NodeVersion, networkInfo netmap.NetworkInfo) error {
combinedObj, err := n.objectGet(ctx, bkt, nodeVersion.OID)
func (n *Layer) removeCombinedObject(ctx context.Context, bkt *data.BucketInfo, objID oid.ID, networkInfo netmap.NetworkInfo, prmAuth frostfs.PrmAuth) error {
combinedObj, err := n.objectGetBase(ctx, bkt, objID, prmAuth)
if err != nil {
return fmt.Errorf("get combined object '%s': %w", nodeVersion.OID.EncodeToString(), err)
return fmt.Errorf("get combined object '%s': %w", objID.EncodeToString(), err)
}
var parts []*data.PartInfo
@ -893,7 +902,7 @@ func (n *Layer) removeCombinedObject(ctx context.Context, bkt *data.BucketInfo,
return fmt.Errorf("unmarshal combined object parts: %w", err)
}
tokens := prepareTokensParameter(ctx, bkt.Owner)
tokens := prepareTokensParameterBase(ctx, bkt.Owner, prmAuth)
members := make([]oid.ID, 0)
// First gateway tries to delete all object parts.
// In case of errors, abort multipart removal.
@ -905,18 +914,18 @@ func (n *Layer) removeCombinedObject(ctx context.Context, bkt *data.BucketInfo,
members = append(members, oids...)
}
if err = n.putTombstones(ctx, bkt, networkInfo, members); err != nil {
if err = n.putTombstonesBase(ctx, bkt, networkInfo, members, prmAuth); err != nil {
return fmt.Errorf("put tombstones with parts: %w", err)
}
// If all parts were removed successfully, remove multipart linking object.
// Do not delete this object first, because gateway won't be able to find parts.
members, err = n.getMembers(ctx, bkt.CID, nodeVersion.OID, tokens)
members, err = n.getMembers(ctx, bkt.CID, objID, tokens)
if err != nil {
return err
}
return n.putTombstones(ctx, bkt, networkInfo, members)
return n.putTombstonesBase(ctx, bkt, networkInfo, members, prmAuth)
}
// DeleteObjects from the storage.