Skip to content

Commit 9f61383

Browse files
committed
server: use managedcontext for concurrent capacity calculation
Fixes #12207 Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent 243f566 commit 9f61383

File tree

1 file changed

+40
-22
lines changed

1 file changed

+40
-22
lines changed

server/src/main/java/com/cloud/alert/AlertManagerImpl.java

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Set;
2929
import java.util.Timer;
3030
import java.util.concurrent.ConcurrentHashMap;
31+
import java.util.concurrent.CountDownLatch;
3132
import java.util.concurrent.ExecutionException;
3233
import java.util.concurrent.ExecutorService;
3334
import java.util.concurrent.Executors;
@@ -37,13 +38,11 @@
3738
import javax.mail.MessagingException;
3839
import javax.naming.ConfigurationException;
3940

40-
import com.cloud.dc.DataCenter;
41-
import com.cloud.dc.Pod;
42-
import com.cloud.org.Cluster;
4341
import org.apache.cloudstack.framework.config.ConfigDepot;
4442
import org.apache.cloudstack.framework.config.ConfigKey;
4543
import org.apache.cloudstack.framework.config.Configurable;
4644
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
45+
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
4746
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
4847
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
4948
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
@@ -52,8 +51,9 @@
5251
import org.apache.cloudstack.utils.mailing.SMTPMailSender;
5352
import org.apache.commons.lang3.ArrayUtils;
5453
import org.apache.commons.lang3.math.NumberUtils;
55-
import org.apache.logging.log4j.Logger;
5654
import org.apache.logging.log4j.LogManager;
55+
import org.apache.logging.log4j.Logger;
56+
import org.jetbrains.annotations.Nullable;
5757

5858
import com.cloud.alert.dao.AlertDao;
5959
import com.cloud.api.ApiDBUtils;
@@ -66,9 +66,11 @@
6666
import com.cloud.configuration.Config;
6767
import com.cloud.configuration.ConfigurationManager;
6868
import com.cloud.dc.ClusterVO;
69+
import com.cloud.dc.DataCenter;
6970
import com.cloud.dc.DataCenter.NetworkType;
7071
import com.cloud.dc.DataCenterVO;
7172
import com.cloud.dc.HostPodVO;
73+
import com.cloud.dc.Pod;
7274
import com.cloud.dc.Vlan.VlanType;
7375
import com.cloud.dc.dao.ClusterDao;
7476
import com.cloud.dc.dao.DataCenterDao;
@@ -82,6 +84,7 @@
8284
import com.cloud.host.dao.HostDao;
8385
import com.cloud.network.Ipv6Service;
8486
import com.cloud.network.dao.IPAddressDao;
87+
import com.cloud.org.Cluster;
8588
import com.cloud.org.Grouping.AllocationState;
8689
import com.cloud.resource.ResourceManager;
8790
import com.cloud.storage.StorageManager;
@@ -93,8 +96,6 @@
9396
import com.cloud.utils.db.TransactionCallbackNoReturn;
9497
import com.cloud.utils.db.TransactionStatus;
9598

96-
import org.jetbrains.annotations.Nullable;
97-
9899
public class AlertManagerImpl extends ManagerBase implements AlertManager, Configurable {
99100
protected Logger logger = LogManager.getLogger(AlertManagerImpl.class.getName());
100101

@@ -289,30 +290,47 @@ protected void recalculateHostCapacities() {
289290
if (hostIds.isEmpty()) {
290291
return;
291292
}
292-
ConcurrentHashMap<Long, Future<Void>> futures = new ConcurrentHashMap<>();
293293
ExecutorService executorService = Executors.newFixedThreadPool(Math.max(1,
294294
Math.min(CapacityManager.CapacityCalculateWorkers.value(), hostIds.size())));
295-
for (Long hostId : hostIds) {
296-
futures.put(hostId, executorService.submit(() -> {
297-
Transaction.execute(new TransactionCallbackNoReturn() {
295+
final CountDownLatch latch = new CountDownLatch(hostIds.size());
296+
final ConcurrentHashMap<Long, Throwable> failures = new ConcurrentHashMap<>();
297+
298+
try {
299+
for (final Long hostId : hostIds) {
300+
executorService.execute(new ManagedContextRunnable() {
298301
@Override
299-
public void doInTransactionWithoutResult(TransactionStatus status) {
300-
final HostVO host = hostDao.findById(hostId);
301-
_capacityMgr.updateCapacityForHost(host);
302+
protected void runInContext() {
303+
try {
304+
final HostVO host = hostDao.findById(hostId);
305+
if (host == null) {
306+
logger.error("Host with ID: {} no longer exists, skipping capacity calculation", hostId);
307+
return;
308+
}
309+
_capacityMgr.updateCapacityForHost(host);
310+
} catch (Throwable t) {
311+
failures.put(hostId, t);
312+
logger.error("Error during host capacity calculation for ID: {}", hostId, t);
313+
} finally {
314+
latch.countDown();
315+
}
302316
}
303317
});
304-
return null;
305-
}));
306-
}
307-
for (Map.Entry<Long, Future<Void>> entry: futures.entrySet()) {
318+
}
319+
308320
try {
309-
entry.getValue().get();
310-
} catch (InterruptedException | ExecutionException e) {
311-
logger.error(String.format("Error during capacity calculation for host: %d due to : %s",
312-
entry.getKey(), e.getMessage()), e);
321+
latch.await();
322+
} catch (InterruptedException ie) {
323+
Thread.currentThread().interrupt();
324+
logger.warn("Interrupted while waiting for host capacity calculation tasks");
313325
}
326+
327+
if (!failures.isEmpty()) {
328+
logger.warn("Host capacity calculation finished with {} failures out of {} hosts",
329+
failures.size(), hostIds.size());
330+
}
331+
} finally {
332+
executorService.shutdown();
314333
}
315-
executorService.shutdown();
316334
}
317335

318336
protected void recalculateStorageCapacities() {

0 commit comments

Comments
 (0)