/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.management;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.StandardMBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.opengamma.DataNotFoundException;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.engine.exec.stats.TotallingGraphStatisticsGathererProvider;
import com.opengamma.engine.view.ViewDefinition;
import com.opengamma.engine.view.ViewProcess;
import com.opengamma.engine.view.client.ViewClient;
import com.opengamma.engine.view.event.ViewProcessorEventListener;
import com.opengamma.engine.view.impl.ViewProcessInternal;
import com.opengamma.engine.view.impl.ViewProcessorImpl;
import com.opengamma.id.UniqueId;
import com.opengamma.util.ArgumentChecker;
/**
* Creates exposed MBeans and register with MBeanServer.
*/
public final class ManagementService implements ViewProcessorEventListener {
/** Logger. */
private static final Logger s_logger = LoggerFactory.getLogger(ManagementService.class);
/**
* The underlying view processor.
*/
private final ViewProcessorImpl _viewProcessor;
/**
* The MBean server.
*/
private final MBeanServer _mBeanServer;
/**
* The statistics gatherer.
*/
private final TotallingGraphStatisticsGathererProvider _statisticsProvider;
/**
* The config.
*/
private final ConcurrentHashMap<UniqueId, Set<String>> _calcConfigByViewProcessId = new ConcurrentHashMap<>();
/**
* Should beans be categorized by view processor or not. If only one view processor is expected then setting this to false means the MBean hierarchy is simpler to navigate.
*/
private final boolean _splitByViewProcessor;
/**
* Have the MBeans already been initialized for the view processor. Used to avoid trying to register on the notifyViewProcessorStarted method if registration has already happened through the
* constructor.
*/
private boolean _isInitialized;
//-------------------------------------------------------------------------
/**
* A convenience static method which creates a ManagementService and initializes it with the supplied parameters.
*
* @param viewProcessor the view processor, not null
* @param statisticsProvider the statistics provider, not null
* @param mBeanServer the MBeanServer to register MBeans to, not null
* @deprecated add section containing JmxManagementServiceFactory to ini file instead
*/
@Deprecated
public static void registerMBeans(ViewProcessorImpl viewProcessor, TotallingGraphStatisticsGathererProvider statisticsProvider, MBeanServer mBeanServer) {
ManagementService registry = new ManagementService(viewProcessor, statisticsProvider, mBeanServer, false);
registry.init();
}
//-------------------------------------------------------------------------
/**
* A constructor for a management service for a range of possible MBeans.
*
* @param viewProcessor the view processor, not null
* @param statisticsProvider the statistics provider, not null
* @param mBeanServer the MBeanServer to register MBeans to, not null
* @param splitByViewProcessor if true, then classify registered beans by their view processor. Only required if more than one view processor will be running.
*/
public ManagementService(ViewProcessorImpl viewProcessor, TotallingGraphStatisticsGathererProvider statisticsProvider, MBeanServer mBeanServer, boolean splitByViewProcessor) {
ArgumentChecker.notNull(viewProcessor, "View Processor");
ArgumentChecker.notNull(mBeanServer, "MBeanServer");
ArgumentChecker.notNull(statisticsProvider, "TotallingGraphStatisticsGathererProvider");
_viewProcessor = viewProcessor;
_mBeanServer = mBeanServer;
_statisticsProvider = statisticsProvider;
_splitByViewProcessor = splitByViewProcessor;
}
//-------------------------------------------------------------------------
/**
* Call to register the mbeans in the mbean server and start and do any other required initialization.
*
* @throws net.sf.ehcache.CacheException - all exceptions are wrapped in CacheException
*/
public void init() {
try {
initializeAndRegisterMBeans();
_viewProcessor.getViewProcessorEventListenerRegistry().registerListener(this);
} catch (Exception e) {
throw new OpenGammaRuntimeException("MBean registration error", e);
}
}
/**
* @throws Exception
* @throws InstanceAlreadyExistsException
* @throws MBeanRegistrationException
* @throws NotCompliantMBeanException
*/
private void initializeAndRegisterMBeans() throws Exception {
if (!_isInitialized) {
initializeViewProcessor();
initializeViewProcesses();
initializeViewClients();
initializeGraphExecutionStatistics();
_isInitialized = true;
}
}
private void initializeGraphExecutionStatistics() throws Exception {
for (ViewProcess viewProcess : _viewProcessor.getViewProcesses()) {
Set<String> configurationNames = viewProcess.getLatestViewDefinition().getAllCalculationConfigurationNames();
_calcConfigByViewProcessId.putIfAbsent(viewProcess.getUniqueId(), configurationNames);
for (String calcConfigName : configurationNames) {
GraphExecutionStatisticsMBeanImpl graphStatistics = new GraphExecutionStatisticsMBeanImpl(viewProcess, _statisticsProvider, _viewProcessor.getName(), calcConfigName);
registerGraphStatistics(graphStatistics);
}
}
}
private void initializeViewProcessor() throws Exception {
ViewProcessorMBeanImpl viewProcessor = new ViewProcessorMBeanImpl(_viewProcessor, _splitByViewProcessor);
registerViewProcessor(viewProcessor);
}
private void initializeViewProcesses() throws Exception {
for (ViewProcessInternal viewProcess : _viewProcessor.getViewProcesses()) {
ViewProcessMXBeanImpl viewProcessBean = new ViewProcessMXBeanImpl(viewProcess, _viewProcessor, _splitByViewProcessor);
registerViewProcess(viewProcessBean);
}
}
private void initializeViewClients() throws Exception {
for (ViewClient viewClient : _viewProcessor.getViewClients()) {
ViewClientMBeanImpl viewClientBean = new ViewClientMBeanImpl(viewClient, _splitByViewProcessor);
registerViewClient(viewClientBean);
}
}
//-------------------------------------------------------------------------
private void registerGraphStatistics(GraphExecutionStatisticsMBeanImpl graphStatistics) throws Exception {
ObjectName objectName = graphStatistics.getObjectName();
StandardMBean mbean = new StandardMBean(graphStatistics, GraphExecutionStatisticsMBean.class);
try {
_mBeanServer.registerMBean(mbean, objectName);
} catch (InstanceAlreadyExistsException e) {
_mBeanServer.unregisterMBean(objectName);
_mBeanServer.registerMBean(mbean, objectName);
}
}
private void registerViewProcessor(ViewProcessorMBeanImpl viewProcessor) throws Exception {
ObjectName objectName = viewProcessor.getObjectName();
StandardMBean mBean = new StandardMBean(viewProcessor, ViewProcessorMBean.class);
try {
_mBeanServer.registerMBean(mBean, objectName);
} catch (InstanceAlreadyExistsException e) {
_mBeanServer.unregisterMBean(objectName);
_mBeanServer.registerMBean(mBean, objectName);
}
}
private void registerViewProcess(ViewProcessMXBeanImpl viewProcessBean) throws Exception {
registerViewProcess(viewProcessBean, viewProcessBean.getObjectName());
}
private void registerViewProcess(ViewProcessMXBeanImpl viewProcessBean, ObjectName objectName) throws Exception {
try {
_mBeanServer.registerMBean(viewProcessBean, objectName);
} catch (InstanceAlreadyExistsException e) {
_mBeanServer.unregisterMBean(objectName);
_mBeanServer.registerMBean(viewProcessBean, viewProcessBean.getObjectName());
}
}
private void registerViewClient(ViewClientMBeanImpl viewClient) throws Exception {
ObjectName objectName = viewClient.getObjectName();
StandardMBean mBean = new StandardMBean(viewClient, ViewClientMBean.class);
try {
_mBeanServer.registerMBean(mBean, objectName);
} catch (InstanceAlreadyExistsException e) {
_mBeanServer.unregisterMBean(objectName);
_mBeanServer.registerMBean(mBean, objectName);
}
}
//-------------------------------------------------------------------------
@Override
public void notifyViewProcessAdded(UniqueId viewProcessId) {
ViewProcessInternal view = _viewProcessor.getViewProcess(viewProcessId);
if (view == null) {
return;
}
ViewProcessMXBeanImpl viewManagement = new ViewProcessMXBeanImpl(view, _viewProcessor, _splitByViewProcessor);
try {
registerViewProcess(viewManagement);
} catch (Exception e) {
s_logger.warn("Error registering view for management for " + viewManagement.getObjectName() + " . Error was " + e.getMessage(), e);
}
ViewDefinition definition;
try {
definition = view.getLatestViewDefinition();
} catch (DataNotFoundException e) {
definition = null;
s_logger.error("View process {} does not have a valid view definition", viewProcessId);
}
Set<String> configurationNames = Collections.emptySet();
if (definition != null) {
configurationNames = definition.getAllCalculationConfigurationNames();
}
_calcConfigByViewProcessId.putIfAbsent(viewProcessId, configurationNames);
for (String calcConfigName : configurationNames) {
GraphExecutionStatisticsMBeanImpl graphStatistics = new GraphExecutionStatisticsMBeanImpl(view, _statisticsProvider, _viewProcessor.getName(), calcConfigName);
try {
registerGraphStatistics(graphStatistics);
} catch (Exception e) {
s_logger.warn("Error registering GraphExecutionStatistics for management for " + graphStatistics.getObjectName() + " . Error was " + e.getMessage(), e);
}
}
}
@Override
public void notifyViewAutomaticallyStarted(UniqueId viewProcessId, String autoStartName) {
ViewProcessInternal view = _viewProcessor.getViewProcess(viewProcessId);
if (view == null) {
return;
}
ViewProcessMXBeanImpl viewManagement = new ViewProcessMXBeanImpl(view, _viewProcessor, _splitByViewProcessor);
try {
String beanNamePrefix = _splitByViewProcessor ? "com.opengamma:type=ViewProcessors,ViewProcessor=ViewProcessor " + _viewProcessor.getName() : "com.opengamma:type=ViewProcessor";
String beanName = beanNamePrefix + ",AutoStartViews=AutoStartViews,name=AutoStart [" + autoStartName + "]";
registerViewProcess(viewManagement, new ObjectName(beanName));
} catch (Exception e) {
s_logger.warn("Error registering view for management for " + viewManagement.getObjectName() + " . Error was " + e.getMessage(), e);
}
}
@Override
public void notifyViewProcessRemoved(UniqueId viewProcessId) {
ObjectName objectName = null;
try {
objectName = ViewProcessMXBeanImpl.createObjectName(_viewProcessor.getName(), viewProcessId, _splitByViewProcessor);
_mBeanServer.unregisterMBean(objectName);
} catch (Exception e) {
s_logger.warn("Error unregistering view for management for " + objectName + " . Error was " + e.getMessage(), e);
}
Set<String> configurationNames = _calcConfigByViewProcessId.get(viewProcessId);
if (configurationNames != null) {
//String viewDefinitionName = _viewProcessor.getViewProcess(viewProcessId).getDefinitionName();
for (String configName : configurationNames) {
objectName = GraphExecutionStatisticsMBeanImpl.createObjectName(_viewProcessor.getName(), viewProcessId, configName);
try {
_mBeanServer.unregisterMBean(objectName);
} catch (Exception e) {
s_logger.warn("Error unregistering view for GraphExecutionStatistics for " + objectName + " . Error was " + e.getMessage(), e);
}
}
}
_calcConfigByViewProcessId.remove(viewProcessId);
}
@Override
public void notifyViewClientAdded(UniqueId viewClientId) {
ViewClient viewClient = _viewProcessor.getViewClient(viewClientId);
ViewClientMBeanImpl viewClientBean = new ViewClientMBeanImpl(viewClient, _splitByViewProcessor);
try {
registerViewClient(viewClientBean);
} catch (Exception e) {
s_logger.warn("Error registering view client for management for " + viewClientBean.getObjectName() + ". Error was " + e.getMessage(), e);
}
}
@Override
public void notifyViewClientRemoved(UniqueId viewClientId) {
ObjectName objectName = null;
try {
objectName = ViewClientMBeanImpl.createObjectName(_viewProcessor.getName(), viewClientId, _splitByViewProcessor);
_mBeanServer.unregisterMBean(objectName);
} catch (Exception e) {
s_logger.warn("Error unregistering view client for management for " + objectName + ". Error was " + e.getMessage(), e);
}
}
@Override
public void notifyViewProcessorStarted() {
try {
initializeAndRegisterMBeans();
} catch (Exception e) {
throw new OpenGammaRuntimeException("MBean registration error", e);
}
}
@Override
public void notifyViewProcessorStopped() {
Set<ObjectName> registeredObjectNames = null;
try {
// ViewProcessor MBean
registeredObjectNames = _mBeanServer.queryNames(ViewProcessorMBeanImpl.createObjectName(_viewProcessor, _splitByViewProcessor), null);
// Other MBeans for this ViewProcessor
registeredObjectNames.addAll(_mBeanServer.queryNames(new ObjectName("com.opengamma:*,ViewProcessor=" + _viewProcessor.toString()), null));
} catch (MalformedObjectNameException e) {
// this should not happen
s_logger.warn("Error querying MBeanServer. Error was " + e.getMessage(), e);
}
for (ObjectName objectName : registeredObjectNames) {
try {
_mBeanServer.unregisterMBean(objectName);
} catch (Exception e) {
s_logger.warn("Error unregistering object instance " + objectName + " . Error was " + e.getMessage(), e);
}
}
_isInitialized = false;
}
}