2020-12-11 08:04:04 +00:00
|
|
|
package deletesvc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-02-17 12:30:11 +00:00
|
|
|
"strconv"
|
2020-12-11 08:04:04 +00:00
|
|
|
|
2023-03-07 13:38:26 +00:00
|
|
|
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
2023-04-12 14:35:10 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
2023-03-07 13:38:26 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
2023-06-07 10:04:55 +00:00
|
|
|
apiclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
2023-03-07 13:38:26 +00:00
|
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
2023-07-06 12:36:41 +00:00
|
|
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
2023-03-07 13:38:26 +00:00
|
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
2020-12-11 08:04:04 +00:00
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
type statusError struct {
|
|
|
|
status int
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
|
|
|
type execCtx struct {
|
|
|
|
svc *Service
|
|
|
|
|
|
|
|
prm Prm
|
|
|
|
|
|
|
|
statusError
|
|
|
|
|
|
|
|
log *logger.Logger
|
|
|
|
|
2023-07-06 12:36:41 +00:00
|
|
|
tombstone *objectSDK.Tombstone
|
2020-12-11 08:04:04 +00:00
|
|
|
|
2023-07-06 12:36:41 +00:00
|
|
|
splitInfo *objectSDK.SplitInfo
|
2020-12-11 08:04:04 +00:00
|
|
|
|
2023-07-06 12:36:41 +00:00
|
|
|
tombstoneObj *objectSDK.Object
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
statusUndefined int = iota
|
|
|
|
statusOK
|
|
|
|
)
|
|
|
|
|
|
|
|
func (exec *execCtx) setLogger(l *logger.Logger) {
|
2022-09-28 07:41:01 +00:00
|
|
|
exec.log = &logger.Logger{Logger: l.With(
|
2020-12-11 08:04:04 +00:00
|
|
|
zap.String("request", "DELETE"),
|
|
|
|
zap.Stringer("address", exec.address()),
|
|
|
|
zap.Bool("local", exec.isLocal()),
|
|
|
|
zap.Bool("with session", exec.prm.common.SessionToken() != nil),
|
|
|
|
zap.Bool("with bearer", exec.prm.common.BearerToken() != nil),
|
2022-09-28 07:41:01 +00:00
|
|
|
)}
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (exec execCtx) isLocal() bool {
|
|
|
|
return exec.prm.common.LocalOnly()
|
|
|
|
}
|
|
|
|
|
2022-05-31 17:00:41 +00:00
|
|
|
func (exec *execCtx) address() oid.Address {
|
2021-11-01 08:35:33 +00:00
|
|
|
return exec.prm.addr
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
2022-05-31 17:00:41 +00:00
|
|
|
func (exec *execCtx) containerID() cid.ID {
|
|
|
|
return exec.prm.addr.Container()
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (exec *execCtx) commonParameters() *util.CommonPrm {
|
|
|
|
return exec.prm.common
|
|
|
|
}
|
|
|
|
|
2022-05-31 17:00:41 +00:00
|
|
|
func (exec *execCtx) newAddress(id oid.ID) oid.Address {
|
|
|
|
var a oid.Address
|
|
|
|
a.SetObject(id)
|
|
|
|
a.SetContainer(exec.containerID())
|
2020-12-11 08:04:04 +00:00
|
|
|
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
func (exec *execCtx) formSplitInfo(ctx context.Context) bool {
|
2023-06-07 10:04:55 +00:00
|
|
|
success := false
|
2020-12-11 08:04:04 +00:00
|
|
|
|
2023-06-07 10:04:55 +00:00
|
|
|
var err error
|
2023-04-04 09:45:59 +00:00
|
|
|
exec.splitInfo, err = exec.svc.header.splitInfo(ctx, exec)
|
2020-12-11 08:04:04 +00:00
|
|
|
|
|
|
|
switch {
|
|
|
|
default:
|
|
|
|
exec.status = statusUndefined
|
|
|
|
exec.err = err
|
|
|
|
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteCouldNotComposeSplitInfo,
|
2020-12-11 08:04:04 +00:00
|
|
|
zap.String("error", err.Error()),
|
|
|
|
)
|
2023-06-07 10:04:55 +00:00
|
|
|
case err == nil, apiclient.IsErrObjectAlreadyRemoved(err):
|
|
|
|
// IsErrObjectAlreadyRemoved check is required because splitInfo
|
|
|
|
// implicitly performs Head request that may return ObjectAlreadyRemoved
|
|
|
|
// status that is not specified for Delete
|
|
|
|
|
2020-12-11 08:04:04 +00:00
|
|
|
exec.status = statusOK
|
|
|
|
exec.err = nil
|
2023-06-07 10:04:55 +00:00
|
|
|
success = true
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
2023-06-07 10:04:55 +00:00
|
|
|
return success
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
func (exec *execCtx) collectMembers(ctx context.Context) (ok bool) {
|
2020-12-11 08:04:04 +00:00
|
|
|
if exec.splitInfo == nil {
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteNoSplitInfoObjectIsPHY)
|
2020-12-11 08:04:04 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
if _, withLink := exec.splitInfo.Link(); withLink {
|
2023-04-04 09:45:59 +00:00
|
|
|
ok = exec.collectChildren(ctx)
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
if !ok {
|
|
|
|
if _, withLast := exec.splitInfo.LastPart(); withLast {
|
2023-04-04 09:45:59 +00:00
|
|
|
ok = exec.collectChain(ctx)
|
2022-05-12 16:37:46 +00:00
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
} // may be fail if neither right nor linking ID is set?
|
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
return exec.supplementBySplitID(ctx)
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
func (exec *execCtx) collectChain(ctx context.Context) bool {
|
2022-05-31 17:00:41 +00:00
|
|
|
var chain []oid.ID
|
2020-12-11 08:04:04 +00:00
|
|
|
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteAssemblingChain)
|
2020-12-11 08:04:04 +00:00
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
for prev, withPrev := exec.splitInfo.LastPart(); withPrev; {
|
|
|
|
chain = append(chain, prev)
|
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
p, err := exec.svc.header.previous(ctx, exec, prev)
|
2020-12-11 08:04:04 +00:00
|
|
|
|
|
|
|
switch {
|
|
|
|
default:
|
|
|
|
exec.status = statusUndefined
|
|
|
|
exec.err = err
|
|
|
|
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteCouldNotGetPreviousSplitElement,
|
2020-12-11 08:04:04 +00:00
|
|
|
zap.Stringer("id", prev),
|
|
|
|
zap.String("error", err.Error()),
|
|
|
|
)
|
|
|
|
|
|
|
|
return false
|
|
|
|
case err == nil:
|
|
|
|
exec.status = statusOK
|
|
|
|
exec.err = nil
|
2022-05-12 16:37:46 +00:00
|
|
|
|
2022-05-30 06:41:26 +00:00
|
|
|
withPrev = p != nil
|
|
|
|
if withPrev {
|
|
|
|
prev = *p
|
|
|
|
}
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
exec.addMembers(chain)
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
func (exec *execCtx) collectChildren(ctx context.Context) bool {
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteCollectingChildren)
|
2020-12-11 08:04:04 +00:00
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
children, err := exec.svc.header.children(ctx, exec)
|
2020-12-11 08:04:04 +00:00
|
|
|
|
|
|
|
switch {
|
|
|
|
default:
|
|
|
|
exec.status = statusUndefined
|
|
|
|
exec.err = err
|
|
|
|
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteCouldNotCollectObjectChildren,
|
2020-12-11 08:04:04 +00:00
|
|
|
zap.String("error", err.Error()),
|
|
|
|
)
|
|
|
|
|
|
|
|
return false
|
|
|
|
case err == nil:
|
|
|
|
exec.status = statusOK
|
|
|
|
exec.err = nil
|
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
link, _ := exec.splitInfo.Link()
|
|
|
|
|
|
|
|
exec.addMembers(append(children, link))
|
2020-12-11 08:04:04 +00:00
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
func (exec *execCtx) supplementBySplitID(ctx context.Context) bool {
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteSupplementBySplitID)
|
2020-12-11 08:04:04 +00:00
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
chain, err := exec.svc.searcher.splitMembers(ctx, exec)
|
2020-12-11 08:04:04 +00:00
|
|
|
|
|
|
|
switch {
|
|
|
|
default:
|
|
|
|
exec.status = statusUndefined
|
|
|
|
exec.err = err
|
|
|
|
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteCouldNotSearchForSplitChainMembers,
|
2020-12-11 08:04:04 +00:00
|
|
|
zap.String("error", err.Error()),
|
|
|
|
)
|
|
|
|
|
|
|
|
return false
|
|
|
|
case err == nil:
|
|
|
|
exec.status = statusOK
|
|
|
|
exec.err = nil
|
|
|
|
|
|
|
|
exec.addMembers(chain)
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-31 17:00:41 +00:00
|
|
|
func (exec *execCtx) addMembers(incoming []oid.ID) {
|
2020-12-11 08:04:04 +00:00
|
|
|
members := exec.tombstone.Members()
|
|
|
|
|
|
|
|
for i := range members {
|
|
|
|
for j := 0; j < len(incoming); j++ { // don't use range, slice mutates in body
|
2022-05-12 16:37:46 +00:00
|
|
|
if members[i].Equals(incoming[j]) {
|
2020-12-11 08:04:04 +00:00
|
|
|
incoming = append(incoming[:j], incoming[j+1:]...)
|
|
|
|
j--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
exec.tombstone.SetMembers(append(members, incoming...))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (exec *execCtx) initTombstoneObject() bool {
|
|
|
|
payload, err := exec.tombstone.Marshal()
|
|
|
|
if err != nil {
|
|
|
|
exec.status = statusUndefined
|
|
|
|
exec.err = err
|
|
|
|
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteCouldNotMarshalTombstoneStructure,
|
2020-12-11 08:04:04 +00:00
|
|
|
zap.String("error", err.Error()),
|
|
|
|
)
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-07-06 12:36:41 +00:00
|
|
|
exec.tombstoneObj = objectSDK.New()
|
2022-05-31 17:00:41 +00:00
|
|
|
exec.tombstoneObj.SetContainerID(exec.containerID())
|
2023-07-06 12:36:41 +00:00
|
|
|
exec.tombstoneObj.SetType(objectSDK.TypeTombstone)
|
2020-12-11 08:04:04 +00:00
|
|
|
exec.tombstoneObj.SetPayload(payload)
|
|
|
|
|
2022-05-25 16:09:12 +00:00
|
|
|
tokenSession := exec.commonParameters().SessionToken()
|
|
|
|
if tokenSession != nil {
|
|
|
|
issuer := tokenSession.Issuer()
|
|
|
|
exec.tombstoneObj.SetOwnerID(&issuer)
|
|
|
|
} else {
|
|
|
|
// make local node a tombstone object owner
|
2022-05-31 17:00:41 +00:00
|
|
|
localUser := exec.svc.netInfo.LocalNodeID()
|
|
|
|
exec.tombstoneObj.SetOwnerID(&localUser)
|
2022-05-25 16:09:12 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 12:36:41 +00:00
|
|
|
var a objectSDK.Attribute
|
2021-02-17 12:30:11 +00:00
|
|
|
a.SetKey(objectV2.SysAttributeExpEpoch)
|
|
|
|
a.SetValue(strconv.FormatUint(exec.tombstone.ExpirationEpoch(), 10))
|
|
|
|
|
|
|
|
exec.tombstoneObj.SetAttributes(a)
|
|
|
|
|
2020-12-11 08:04:04 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2023-04-04 09:45:59 +00:00
|
|
|
func (exec *execCtx) saveTombstone(ctx context.Context) bool {
|
|
|
|
id, err := exec.svc.placer.put(ctx, exec)
|
2020-12-11 08:04:04 +00:00
|
|
|
|
|
|
|
switch {
|
|
|
|
default:
|
|
|
|
exec.status = statusUndefined
|
|
|
|
exec.err = err
|
|
|
|
|
2023-04-12 14:35:10 +00:00
|
|
|
exec.log.Debug(logs.DeleteCouldNotSaveTheTombstone,
|
2020-12-11 08:04:04 +00:00
|
|
|
zap.String("error", err.Error()),
|
|
|
|
)
|
|
|
|
|
|
|
|
return false
|
|
|
|
case err == nil:
|
|
|
|
exec.status = statusOK
|
|
|
|
exec.err = nil
|
|
|
|
|
2021-11-01 08:35:33 +00:00
|
|
|
exec.prm.tombAddrWriter.
|
2022-05-31 17:00:41 +00:00
|
|
|
SetAddress(exec.newAddress(*id))
|
2020-12-11 08:04:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|