/*
* Copyright (c) 2010-2012 Grid Dynamics Consulting Services, Inc, All Rights Reserved
* http://www.griddynamics.com
*
* This library is free software; you can redistribute it and/or modify it under the terms of
* the Apache License; either
* version 2.0 of the License, or any later version.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.griddynamics.jagger.monitoring;
import com.google.common.collect.*;
import com.griddynamics.jagger.coordinator.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.*;
public class MonitoringController {
private Logger log = LoggerFactory.getLogger(MonitoringController.class);
private final String sessionId;
private final String taskId;
private final Multimap<NodeType, NodeId> availableNodes;
private final Coordinator coordinator;
private Multimap<NodeId, String> activeProcesses = HashMultimap.<NodeId, String>create();
private Map<String, NodeId> agentMapping = Maps.newHashMap();
private final Collection<NodeId> capableNodes;
private final long ttl;
public MonitoringController(String sessionId, String taskId, Multimap<NodeType, NodeId> availableNodes,
Coordinator coordinator, Collection<NodeId> capableNodes, long ttl) {
this.sessionId = sessionId;
this.taskId = taskId;
this.availableNodes = availableNodes;
this.coordinator = coordinator;
this.capableNodes = capableNodes;
this.ttl = ttl;
}
public void startMonitoring() {
log.debug("Start of monitoring requested. Task id {}", taskId);
// todo use nodes on start
Collection<NodeId> agents = availableNodes.get(NodeType.AGENT);
log.debug("Available agents {}", agents);
Iterator<NodeId> iterator = capableNodes.iterator();
for (NodeId agent : agents) {
if (!iterator.hasNext()) {
iterator = capableNodes.iterator();
}
NodeId kernel = iterator.next();
RemoteExecutor remote = coordinator.getExecutor(kernel);
log.info("Agent {} will be monitored by kernel {}", agent, kernel);
log.debug("Start monitoring command is sending");
String processId = remote.runSyncWithTimeout(StartMonitoring.create(sessionId, agent, taskId),
Coordination.<StartMonitoring>doNothing(), ttl * 2);
log.debug("Start monitoring command is sent. Process with id {} started", processId);
activeProcesses.put(kernel, processId);
agentMapping.put(processId, agent);
}
}
public Map<NodeId, MonitoringStatus> getStatus() {
Map<NodeId, MonitoringStatus> result = Maps.newHashMap();
for (NodeId nodeId : capableNodes) {
RemoteExecutor remote = coordinator.getExecutor(nodeId);
Collection<String> processes = activeProcesses.get(nodeId);
for (String processId : processes) {
remote.runSyncWithTimeout(PollMonitoringStatus.create(sessionId, processId),
Coordination.<Command>doNothing(), ttl * 2);
}
}
return result;
}
public void stopMonitoring() {
log.info("Stop monitoring requested");
ExecutorService threadsStopper = Executors.newCachedThreadPool();
Collection<Callable<Void>> stopList = Sets.newLinkedHashSet();
for (final NodeId kernel : activeProcesses.keySet()) {
Collection<String> processes = activeProcesses.get(kernel);
for (final String processId : processes) {
stopList.add(
new Callable<Void>() {
@Override
public Void call() throws Exception {
try {
RemoteExecutor remote = coordinator.getExecutor(kernel);
log.info("Going to send stop monitoring command to kernel {}", kernel);
remote.runSyncWithTimeout(StopMonitoring.create(sessionId, processId),
Coordination.doNothing(), 2*ttl);
log.info("Command stop monitoring successfully sent");
NodeId agent = agentMapping.get(processId);
log.info("Agent {} monitoring is stopped on kernel {}", agent, kernel);
} catch (Throwable e) {
log.error("Stop monitoring failed for kernel {}, process {}", kernel.getIdentifier(),
processId);
return null;
}
return null;
}
});
}
}
try {
threadsStopper.invokeAll(stopList);
threadsStopper.shutdown();
} catch (InterruptedException e) {
log.error("Stop monitoring processes pool failed");
}
for (NodeId kernel : Sets.newHashSet(activeProcesses.keySet())) {
Collection<String> processes = activeProcesses.get(kernel);
for (String processId : processes) {
agentMapping.remove(processId);
}
activeProcesses.removeAll(kernel);
}
log.info("All monitoring processes were stopped successful");
}
}