2022-04-19 17:59:13 +00:00
|
|
|
package tombstone
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"strconv"
|
|
|
|
|
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/util/logger"
|
2024-11-07 14:32:10 +00:00
|
|
|
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
|
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"
|
2022-12-30 09:54:48 +00:00
|
|
|
lru "github.com/hashicorp/golang-lru/v2"
|
2022-04-19 17:59:13 +00:00
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Source is a tombstone source interface.
|
|
|
|
type Source interface {
|
|
|
|
// Tombstone must return tombstone from the source it was
|
|
|
|
// configured to fetch from and any error that appeared during
|
|
|
|
// fetching process.
|
|
|
|
//
|
|
|
|
// Tombstone MUST return (nil, nil) if requested tombstone is
|
|
|
|
// missing in the storage for the provided epoch.
|
2023-07-06 12:36:41 +00:00
|
|
|
Tombstone(ctx context.Context, a oid.Address, epoch uint64) (*objectSDK.Object, error)
|
2022-04-19 17:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ExpirationChecker is a tombstone source wrapper.
|
|
|
|
// It checks tombstones presence via tombstone
|
|
|
|
// source, caches it checks its expiration.
|
|
|
|
//
|
|
|
|
// Must be created via NewChecker function. `var` and
|
|
|
|
// `ExpirationChecker{}` declarations leads to undefined behaviour
|
|
|
|
// and may lead to panics.
|
|
|
|
type ExpirationChecker struct {
|
2022-12-30 09:54:48 +00:00
|
|
|
cache *lru.Cache[string, uint64]
|
2022-04-19 17:59:13 +00:00
|
|
|
|
2022-09-28 07:41:01 +00:00
|
|
|
log *logger.Logger
|
2022-04-19 17:59:13 +00:00
|
|
|
|
|
|
|
tsSource Source
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsTombstoneAvailable checks the tombstone presence in the system in the
|
|
|
|
// following order:
|
2022-08-15 16:20:20 +00:00
|
|
|
// - 1. Local LRU cache;
|
|
|
|
// - 2. Tombstone source.
|
2022-04-19 17:59:13 +00:00
|
|
|
//
|
|
|
|
// If a tombstone was successfully fetched (regardless of its expiration)
|
|
|
|
// it is cached in the LRU cache.
|
2022-05-31 17:00:41 +00:00
|
|
|
func (g *ExpirationChecker) IsTombstoneAvailable(ctx context.Context, a oid.Address, epoch uint64) bool {
|
|
|
|
addrStr := a.EncodeToString()
|
2022-04-19 17:59:13 +00:00
|
|
|
log := g.log.With(zap.String("address", addrStr))
|
|
|
|
|
|
|
|
expEpoch, ok := g.cache.Get(addrStr)
|
|
|
|
if ok {
|
2022-12-30 09:54:48 +00:00
|
|
|
return expEpoch > epoch
|
2022-04-19 17:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ts, err := g.tsSource.Tombstone(ctx, a, epoch)
|
|
|
|
if err != nil {
|
2024-10-21 07:22:54 +00:00
|
|
|
log.Warn(ctx,
|
2023-04-12 14:35:10 +00:00
|
|
|
logs.TombstoneCouldNotGetTheTombstoneTheSource,
|
2022-04-19 17:59:13 +00:00
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
if ts != nil {
|
2024-10-21 13:27:28 +00:00
|
|
|
return g.handleTS(ctx, addrStr, ts, epoch)
|
2022-04-19 17:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// requested tombstone not
|
2023-02-05 15:59:38 +00:00
|
|
|
// found in the FrostFS network
|
2022-04-19 17:59:13 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2024-10-21 13:27:28 +00:00
|
|
|
func (g *ExpirationChecker) handleTS(ctx context.Context, addr string, ts *objectSDK.Object, reqEpoch uint64) bool {
|
2022-04-19 17:59:13 +00:00
|
|
|
for _, atr := range ts.Attributes() {
|
2024-09-20 07:58:22 +00:00
|
|
|
if atr.Key() == objectV2.SysAttributeExpEpoch {
|
2022-04-19 17:59:13 +00:00
|
|
|
epoch, err := strconv.ParseUint(atr.Value(), 10, 64)
|
|
|
|
if err != nil {
|
2024-10-21 13:27:28 +00:00
|
|
|
g.log.Warn(ctx,
|
2023-08-09 12:53:13 +00:00
|
|
|
logs.TombstoneExpirationParseFailure,
|
2022-04-19 17:59:13 +00:00
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
g.cache.Add(addr, epoch)
|
2022-09-05 05:48:42 +00:00
|
|
|
return epoch >= reqEpoch
|
2022-04-19 17:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// unexpected tombstone without expiration epoch
|
|
|
|
return false
|
|
|
|
}
|