This is an automated email from the ASF dual-hosted git repository.
ChenSammi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 5d4972e025e HDDS-16209. KeyLifecycleService leaks inFlight entry when
a task runs while shouldRun() is false (#11050)
5d4972e025e is described below
commit 5d4972e025e31dec8c991be5caeab4d64d123ee9
Author: Sergey Soldatov <[email protected]>
AuthorDate: Wed Aug 19 01:10:56 2026 -0700
HDDS-16209. KeyLifecycleService leaks inFlight entry when a task runs while
shouldRun() is false (#11050)
---
.../ozone/om/service/KeyLifecycleService.java | 5 +++
.../ozone/om/service/TestKeyLifecycleService.java | 40 ++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
index c36097fd4d3..09289826594 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
@@ -466,6 +466,11 @@ public BackgroundTaskResult call() {
}
onSuccess(bucketKey);
+ } else {
+ // The task was registered in inFlight when scheduled, but the service
got suspended/disabled
+ // or lost leadership before the task ran. Clear the registration,
otherwise this bucket is
+ // skipped as "already running" in every following getTasks() cycle.
+ inFlight.remove(bucketKey);
}
// By design, no one cares about the results of this call back.
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
index 012123680f6..3f2a93c20c5 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
@@ -92,6 +92,8 @@
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList;
import org.apache.hadoop.hdds.server.ServerUtils;
+import org.apache.hadoop.hdds.utils.BackgroundTask;
+import org.apache.hadoop.hdds.utils.BackgroundTaskQueue;
import org.apache.hadoop.hdds.utils.db.DBConfigFromFile;
import org.apache.hadoop.hdds.utils.db.RocksDatabaseException;
import org.apache.hadoop.hdds.utils.db.Table;
@@ -529,6 +531,44 @@ void testBucketScanResume(BucketLayout bucketLayout,
boolean createPrefix) throw
deleteLifecyclePolicy(volumeName, bucketName);
}
+ @Test
+ void testInFlightClearedWhenTaskSkipsRun() throws Exception {
+ final String volumeName = getTestName();
+ final String bucketName = uniqueObjectName("bucket");
+
+ keyLifecycleService.suspend();
+ createVolumeAndBucket(volumeName, bucketName, BucketLayout.OBJECT_STORE,
+ UserGroupInformation.getCurrentUser().getShortUserName());
+ ZonedDateTime date =
ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(EXPIRE_SECONDS);
+ createLifecyclePolicy(volumeName, bucketName, BucketLayout.OBJECT_STORE,
"key", null, date.toString(), true);
+ String bucketKey = metadataManager.getBucketKey(volumeName, bucketName);
+
+ try {
+ // Schedule the task manually. The service's own scheduler may win the
registration and run
+ // the task to completion; in that case getTasks() returns nothing, so
retry until this
+ // thread holds the scheduled task.
+ keyLifecycleService.resume();
+ BackgroundTaskQueue queue = keyLifecycleService.getTasks();
+ for (int i = 0; queue.isEmpty() && i < 200; i++) {
+ Thread.sleep(WAIT_CHECK_INTERVAL);
+ queue = keyLifecycleService.getTasks();
+ }
+ assertFalse(queue.isEmpty());
+
+ // Suspend before the scheduled task executes, then run it: call()
skips the scan because
+ // shouldRun() is false, but must still clear the in-flight
registration, otherwise the
+ // bucket is never scheduled again.
+ keyLifecycleService.suspend();
+ for (BackgroundTask task = queue.poll(); task != null; task =
queue.poll()) {
+ task.call();
+ }
+
assertFalse(keyLifecycleService.status().getRunningBucketsList().contains(bucketKey));
+ } finally {
+ keyLifecycleService.resume();
+ deleteLifecyclePolicy(volumeName, bucketName);
+ }
+ }
+
@ParameterizedTest
@MethodSource("parameters1")
void testBucketScanWithScanEndTime(BucketLayout bucketLayout, boolean
createPrefix) throws IOException,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]