diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index a842ef4c..b1d79747 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -40,9 +40,16 @@ func (s *Shard) Init() error { } gc := &gc{ - gcCfg: s.gcCfg, - remover: s.removeGarbage, - mEventHandler: map[eventType]*eventHandlers{}, + gcCfg: s.gcCfg, + remover: s.removeGarbage, + mEventHandler: map[eventType]*eventHandlers{ + eventNewEpoch: { + cancelFunc: func() {}, + handlers: []eventHandler{ + s.collectExpiredObjects, + }, + }, + }, } gc.init() diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index dc5cc31e..16396759 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -186,3 +186,53 @@ func (s *Shard) removeGarbage() { return } } + +func (s *Shard) collectExpiredObjects(ctx context.Context, e Event) { + epoch := e.(newEpoch).epoch + + var expired []*object.Address + + // collect expired non-tombstone object + err := s.metaBase.IterateExpired(epoch, func(expiredObject *meta.ExpiredObject) error { + select { + case <-ctx.Done(): + return meta.ErrInterruptIterator + default: + } + + if expiredObject.Type() != object.TypeTombstone { + expired = append(expired, expiredObject.Address()) + } + + return nil + }) + if err != nil { + s.log.Warn("iterator over expired objects failed", + zap.String("error", err.Error()), + ) + + return + } else if len(expired) == 0 { + return + } + + // check if context canceled + select { + case <-ctx.Done(): + return + default: + } + + // inhume the collected objects + _, err = s.metaBase.Inhume(new(meta.InhumePrm). + WithAddresses(expired...). + WithGCMark(), + ) + if err != nil { + s.log.Warn("could not inhume the objects", + zap.String("error", err.Error()), + ) + + return + } +}