From ed7c732676006fbcf129de2957773953f0849656 Mon Sep 17 00:00:00 2001
From: Evgenii Stratonikov <evgeniy@nspcc.ru>
Date: Wed, 19 Jan 2022 15:12:34 +0300
Subject: [PATCH] [#1094] shard: unify collection of expired objects

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
---
 pkg/local_object_storage/shard/gc.go | 77 ++++++++--------------------
 1 file changed, 21 insertions(+), 56 deletions(-)

diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go
index 7222d83074..2285d94ee7 100644
--- a/pkg/local_object_storage/shard/gc.go
+++ b/pkg/local_object_storage/shard/gc.go
@@ -216,39 +216,12 @@ func (s *Shard) removeGarbage() {
 }
 
 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:
+	expired, err := s.getExpiredObjects(ctx, e.(newEpoch).epoch, false)
+	if err != nil || len(expired) == 0 {
+		if err != nil {
+			s.log.Warn("iterator over expired objects failed", zap.String("error", err.Error()))
 		}
-
-		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
@@ -265,44 +238,36 @@ func (s *Shard) collectExpiredObjects(ctx context.Context, e Event) {
 	}
 }
 
-// TODO: can be unified with Shard.collectExpiredObjects.
 func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) {
-	epoch := e.(newEpoch).epoch
+	expired, err := s.getExpiredObjects(ctx, e.(newEpoch).epoch, true)
+	if err != nil || len(expired) == 0 {
+		if err != nil {
+			s.log.Warn("iterator over expired tombstones failes", zap.String("error", err.Error()))
+		}
+		return
+	}
 
+	s.expiredTombstonesCallback(ctx, expired)
+}
+
+func (s *Shard) getExpiredObjects(ctx context.Context, epoch uint64, collectTombstones bool) ([]*object.Address, error) {
 	var expired []*object.Address
 
-	// collect expired tombstone objects
 	err := s.metaBase.IterateExpired(epoch, func(expiredObject *meta.ExpiredObject) error {
 		select {
 		case <-ctx.Done():
 			return meta.ErrInterruptIterator
 		default:
+			if (expiredObject.Type() == object.TypeTombstone) == collectTombstones {
+				expired = append(expired, expiredObject.Address())
+			}
+			return nil
 		}
-
-		if expiredObject.Type() == object.TypeTombstone {
-			expired = append(expired, expiredObject.Address())
-		}
-
-		return nil
 	})
 	if err != nil {
-		s.log.Warn("iterator over expired tombstones failed",
-			zap.String("error", err.Error()),
-		)
-
-		return
-	} else if len(expired) == 0 {
-		return
+		return nil, err
 	}
-
-	// check if context canceled
-	select {
-	case <-ctx.Done():
-		return
-	default:
-	}
-
-	s.expiredTombstonesCallback(ctx, expired)
+	return expired, ctx.Err()
 }
 
 // HandleExpiredTombstones marks to be removed all objects that are