From a6c62dd9030c151b98a33f3d81cc4bea94fc5d8d Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Mon, 9 Feb 2026 20:58:29 +0530 Subject: [PATCH 1/4] Heartbeat should not schedule usage job when a job is already running --- .../main/java/com/cloud/usage/UsageManagerImpl.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index 9da64889fc36..79d2cc4fbb88 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -31,6 +31,7 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import com.cloud.network.Network; import com.cloud.usage.dao.UsageNetworksDao; @@ -192,6 +193,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna private final List usageVmDisks = new ArrayList(); private final ScheduledExecutorService _executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-Job")); + private final AtomicBoolean _parseJobRunning = new AtomicBoolean(false); private final ScheduledExecutorService _heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-HB")); private final ScheduledExecutorService _sanityExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-Sanity")); private Future _scheduledFuture = null; @@ -367,7 +369,12 @@ public void run() { (new ManagedContextRunnable() { @Override protected void runInContext() { - runInContextInternal(); + _parseJobRunning.set(true); + try { + runInContextInternal(); + } finally { + _parseJobRunning.set(false); + } } }).run(); } @@ -2269,7 +2276,9 @@ protected void runInContext() { if (timeToJob > (aggregationDurationMillis / 2)) { logger.debug("it's been {} ms since last usage job and {} ms until next job, scheduling an immediate job to catch up (aggregation duration is {} minutes)" , timeSinceLastSuccessJob, timeToJob, _aggregationDuration); - scheduleParse(); + if (!_parseJobRunning.get()) { + scheduleParse(); + } } } From a92e7d4d69fea0f7fa06dad48d70f47e91f2be92 Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:09:38 +0530 Subject: [PATCH 2/4] change variable name --- usage/src/main/java/com/cloud/usage/UsageManagerImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index 79d2cc4fbb88..481a86a4b6db 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -193,7 +193,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna private final List usageVmDisks = new ArrayList(); private final ScheduledExecutorService _executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-Job")); - private final AtomicBoolean _parseJobRunning = new AtomicBoolean(false); + private final AtomicBoolean isParsingJobRunning = new AtomicBoolean(false); private final ScheduledExecutorService _heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-HB")); private final ScheduledExecutorService _sanityExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-Sanity")); private Future _scheduledFuture = null; @@ -369,11 +369,11 @@ public void run() { (new ManagedContextRunnable() { @Override protected void runInContext() { - _parseJobRunning.set(true); + isParsingJobRunning.set(true); try { runInContextInternal(); } finally { - _parseJobRunning.set(false); + isParsingJobRunning.set(false); } } }).run(); @@ -2276,7 +2276,7 @@ protected void runInContext() { if (timeToJob > (aggregationDurationMillis / 2)) { logger.debug("it's been {} ms since last usage job and {} ms until next job, scheduling an immediate job to catch up (aggregation duration is {} minutes)" , timeSinceLastSuccessJob, timeToJob, _aggregationDuration); - if (!_parseJobRunning.get()) { + if (!isParsingJobRunning.get()) { scheduleParse(); } } From 13c127fb26d2bcf5bb8e5cd318ea0a6b9297c027 Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:14:36 +0530 Subject: [PATCH 3/4] added logging --- .../src/main/java/com/cloud/usage/UsageManagerImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index 481a86a4b6db..8425159457f6 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -2274,9 +2274,12 @@ protected void runInContext() { if ((timeSinceLastSuccessJob > 0) && (timeSinceLastSuccessJob > (aggregationDurationMillis - 100))) { if (timeToJob > (aggregationDurationMillis / 2)) { - logger.debug("it's been {} ms since last usage job and {} ms until next job, scheduling an immediate job to catch up (aggregation duration is {} minutes)" - , timeSinceLastSuccessJob, timeToJob, _aggregationDuration); - if (!isParsingJobRunning.get()) { + logger.debug("Hearbeat: it's been {} ms since last finished usage job and {} ms until next job (aggregation duration is {} minutes)", + timeSinceLastSuccessJob, timeToJob, _aggregationDuration); + if (isParsingJobRunning.get()) { + logger.debug("Heartbeat: A parsing job is already running"); + } else { + logger.debug("Heartbeat: Scheduling an immediate job to catch up"); scheduleParse(); } } From df5d18d536eb715c3fd96592ffc96a6733f2938e Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:42:25 +0530 Subject: [PATCH 4/4] fix spelling --- usage/src/main/java/com/cloud/usage/UsageManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index 8425159457f6..2db91ab0e35d 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -2274,7 +2274,7 @@ protected void runInContext() { if ((timeSinceLastSuccessJob > 0) && (timeSinceLastSuccessJob > (aggregationDurationMillis - 100))) { if (timeToJob > (aggregationDurationMillis / 2)) { - logger.debug("Hearbeat: it's been {} ms since last finished usage job and {} ms until next job (aggregation duration is {} minutes)", + logger.debug("Heartbeat: it's been {} ms since last finished usage job and {} ms until next job (aggregation duration is {} minutes)", timeSinceLastSuccessJob, timeToJob, _aggregationDuration); if (isParsingJobRunning.get()) { logger.debug("Heartbeat: A parsing job is already running");