/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.monitoring.system.api;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Future;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.rcenvironment.core.communication.api.CommunicationService;
import de.rcenvironment.core.communication.common.InstanceNodeSessionId;
import de.rcenvironment.core.monitoring.system.api.model.FullSystemAndProcessDataSnapshot;
import de.rcenvironment.core.monitoring.system.internal.AsyncSystemMonitoringDataFetchTask;
import de.rcenvironment.toolkit.modules.concurrency.api.AsyncTaskService;
/**
* Fetches monitoring data asynchronously.
*
* @author David Scholz
* @author Robert Mischke
*/
public class SystemMonitoringDataPollingManager {
private static final int REFRESH_INTERVAL_MSEC = 5000; // TODO make configurable
private final CommunicationService communicationService;
private final AsyncTaskService asyncTaskService;
private final Map<InstanceNodeSessionId, Future<?>> futureMap = new HashMap<>();
private final Log log = LogFactory.getLog(getClass());
public SystemMonitoringDataPollingManager(CommunicationService communicationService, AsyncTaskService asyncTaskService) {
this.communicationService = communicationService;
this.asyncTaskService = asyncTaskService;
}
/**
* Fetches data of the corresponding {@link FullSystemAndProcessDataSnapshot} from a given node.
*
* @param nodeId The {@link InstanceNodeSessionId} of the node whose data should be fetched.
* @param callbackListener The {@link SystemMonitoringDataSnapshotListener}.
*/
public synchronized void startPollingTask(final InstanceNodeSessionId nodeId,
final SystemMonitoringDataSnapshotListener callbackListener) {
if (nodeId == null) {
throw new IllegalArgumentException("Node id must not be null");
}
final RemotableSystemMonitoringService remoteService =
communicationService.getRemotableService(RemotableSystemMonitoringService.class, nodeId);
final Future<?> existingFuture = futureMap.get(nodeId);
if (existingFuture != null) {
log.debug("Monitoring start requested for node " + nodeId + ", but it already has a monitoring task; ignoring request");
return;
}
final AsyncSystemMonitoringDataFetchTask backgroundTask =
new AsyncSystemMonitoringDataFetchTask(callbackListener, remoteService);
final Future<?> newFuture = asyncTaskService.scheduleAtFixedRate(backgroundTask, REFRESH_INTERVAL_MSEC);
futureMap.put(nodeId, newFuture);
log.debug("Started system monitoring background task for node " + nodeId);
}
/**
*
* Cancels monitoring task of specified {@link InstanceNodeSessionId}.
*
* @param nodeId The {@link InstanceNodeSessionId} of the node.
*/
public synchronized void cancelPollingTask(InstanceNodeSessionId nodeId) {
removeAndCancelTask(nodeId);
}
/**
* Cancels all running {@link AsyncSystemMonitoringDataFetchTask} if rce instance is disposed.
*/
public synchronized void cancelAllPollingTasks() {
for (Entry<InstanceNodeSessionId, Future<?>> entry : futureMap.entrySet()) {
final InstanceNodeSessionId nodeId = entry.getKey();
final Future<?> taskFuture = entry.getValue();
cancelTaskFuture(nodeId, taskFuture);
}
futureMap.clear();
}
/**
* Cancels {@link AsyncSystemMonitoringDataFetchTask}s of multiple nodes.
*
* @param nodes Set of disconnectedNodes.
*/
public synchronized void cancelPollingTasks(final Set<InstanceNodeSessionId> nodes) {
if (nodes != null) {
for (InstanceNodeSessionId nodeId : nodes) {
removeAndCancelTask(nodeId);
}
}
}
private void removeAndCancelTask(InstanceNodeSessionId nodeId) {
if (nodeId == null) {
log.warn("Attempted to cancel a monitoring task with a null node id");
return;
}
Future<?> taskFuture = futureMap.remove(nodeId);
if (taskFuture != null) {
cancelTaskFuture(nodeId, taskFuture);
}
}
private void cancelTaskFuture(InstanceNodeSessionId nodeId, Future<?> future) {
future.cancel(false);
log.debug("Stopped system monitoring background task for node " + nodeId);
}
}