/*
* Copyright (c) 2010 Ecole des Mines de Nantes.
*
* This file is part of Entropy.
*
* Entropy is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Entropy is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Entropy. If not, see <http://www.gnu.org/licenses/>.
*/
package entropy.monitoring;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import entropy.PropertiesHelper;
import entropy.PropertiesHelperException;
import entropy.monitoring.sampler.CPUBurningVMsSampler;
import entropy.monitoring.sampler.CPUSampler;
import entropy.monitoring.sampler.ConfigurationAdapterBuilder;
import entropy.monitoring.sampler.MemorySampler;
/**
* A Factory to create Monitor instances by reading some properties.
* <p/>
* TODO: Describes the properties
*
* @author Fabien Hermenier
*/
public class MonitorFactory {
public static final String ROOT_PROPERTY = "monitoring";
public static final String ADAPTER = ROOT_PROPERTY + ".adapter";
/**
* The property that define the implementation to use.
*/
public static final String ADAPTER_IMPL_PROPERTY = ADAPTER + ".impl";
//Stuff related to black and white lists
/**
* The property that define the path of the nodes black list.
*/
public static final String NODES_BL_PROPERTY = ADAPTER + ".nodesBlacklist";
/**
* The property that define the path of the nodes black list.
*/
public static final String NODES_WL_PROPERTY = ADAPTER + ".nodesWhitelist";
//Stuff related to the samplers
public static final String SAMPLER = ROOT_PROPERTY + ".simplify";
public static final String USE_SAMPLERS = SAMPLER + ".activate";
//memory sampler
public static final String MEM_SAMPLER = SAMPLER + ".mem";
public static final String MEM_SAMPLER_IMPL = MEM_SAMPLER + ".impl";
public static final String MEM_SAMPLER_SAMPLER_IMPL = "sampler";
public static final String MEM_SAMPLER_SAMPLER_IMPL_SIZE = MEM_SAMPLER + "." + MEM_SAMPLER_SAMPLER_IMPL + ".size";
//CPU samplers
public static final String CPU_SAMPLER = SAMPLER + ".cpu";
public static final String CPU_SAMPLER_IMPL = CPU_SAMPLER + ".impl";
public static final String CPU_SAMPLER_SAMPLER_IMPL = "sampler";
public static final String CPU_SAMPLER_SAMPLER_IMPL_SIZE = CPU_SAMPLER + "." + CPU_SAMPLER_SAMPLER_IMPL + ".size";
public static final String CPU_SAMPLER_BURNING_IMPL = "CPUBurning";
public static final String CPU_SAMPLER_BURNING_IMPL_SIZE = CPU_SAMPLER + "." + CPU_SAMPLER_BURNING_IMPL + ".threshold";
/**
* The properties to use.
*/
private PropertiesHelper properties;
/**
* Create a new factory using specific properties.
*
* @param props the properties to use
*/
public MonitorFactory(PropertiesHelper props) {
this.properties = props;
}
/**
* Create a new monitor instance.
*
* @return the initialized instance
* @throws entropy.PropertiesHelperException
* if an error occurred while configuring the adapter
* @throws MonitorFactoryException If an error occurred during the instantiation
*/
public Monitor createMonitor() throws PropertiesHelperException, MonitorFactoryException {
Monitor m = new Monitor(createConfAdapter());
try {
attachNodeLists(m);
} catch (IOException e) {
throw new MonitorFactoryException("Error while reading the nodes file", e);
}
attachSamplers(m);
return m;
}
/**
* Create the ConfigurationAdapter.
*
* @return an initialized adapter.
* @throws entropy.PropertiesHelperException
* if an error occurred while configuring the adapter
* @throws MonitorFactoryException If an error occurred during the instantiation
*/
private ConfigurationAdapter createConfAdapter() throws PropertiesHelperException, MonitorFactoryException {
String impl = this.properties.getRequiredProperty(ADAPTER_IMPL_PROPERTY);
try {
Class cl = getClass().getClassLoader().loadClass(impl);
ConfigurationAdapterBuilder b = (ConfigurationAdapterBuilder) cl.newInstance();
return b.build(b.getDistributionConfigurationFile());
} catch (ClassNotFoundException e) {
throw new MonitorFactoryException("Unable to locate implementation '" + impl + "'" + e.getMessage(), e);
} catch (InstantiationException e) {
throw new MonitorFactoryException("Unable to instantiate '" + impl + "'" + e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new MonitorFactoryException("Error while accessing to '" + impl + "':" + e.getMessage(), e);
}
}
/**
* Attach the white or the black node list to a ConfigurationAdapter
*
* @param mon the monitor
* @throws entropy.PropertiesHelperException
* if an error occurred while configuring the driver
* @throws MonitorFactoryException If an error occurred during the instantiation
* @throws IOException if an error occurred while reading the nodes file
*/
private void attachNodeLists(Monitor mon) throws IOException, PropertiesHelperException, MonitorFactoryException {
if (properties.isDefined(NODES_BL_PROPERTY)
&& properties.isDefined(NODES_WL_PROPERTY)) {
throw new MonitorFactoryException("Having a blacklist and a whitelist is not supported");
}
if (properties.isDefined(NODES_BL_PROPERTY)) {
mon.getConfigurationAdapter().setNodesBlackList(readNodes(properties.getRequiredProperty(NODES_BL_PROPERTY)));
} else if (properties.isDefined(NODES_WL_PROPERTY)) {
mon.getConfigurationAdapter().setNodesWhiteList(readNodes(properties.getRequiredProperty(NODES_WL_PROPERTY)));
}
}
/**
* Read a file line by lines.
*
* @param file the file to read
* @return a list of lines, may be empty
* @throws MonitorFactoryException If an error occurred during the instantiation
* @throws IOException if an error occurred while reading the nodes file
*/
private List<String> readNodes(String file) throws IOException, MonitorFactoryException {
LinkedList<String> bl;
BufferedReader reader = null;
try {
FileReader r = new FileReader(file);
reader = new BufferedReader(r);
String line = reader.readLine();
bl = new LinkedList<String>();
while (line != null) {
bl.add(line);
line = reader.readLine();
}
} catch (IOException e) {
throw new MonitorFactoryException("Error while reading '" + file + "'", e);
} finally {
if (reader != null) {
reader.close();
}
}
return bl;
}
/**
* Attach a set of samplers to a monitor.
*
* @param mon the monitor to alter
* @throws MonitorFactoryException If an error occurred during the instantiation
* @throws entropy.PropertiesHelperException
* if an error occurred while configuring the driver
*/
private void attachSamplers(Monitor mon) throws PropertiesHelperException, MonitorFactoryException {
if (this.properties.isDefined(MEM_SAMPLER_IMPL)) {
String impl = this.properties.getRequiredProperty(MEM_SAMPLER_IMPL);
if (impl.equals(MEM_SAMPLER_SAMPLER_IMPL)) {
mon.attach(new MemorySampler(this.properties.getRequiredPropertyAsInt(MEM_SAMPLER_SAMPLER_IMPL_SIZE)));
} else {
throw new MonitorFactoryException("Unknown implementation '" + impl + "' for property '" + MEM_SAMPLER_IMPL + "'");
}
}
if (this.properties.isDefined(CPU_SAMPLER_IMPL)) {
String impl = this.properties.getRequiredProperty(CPU_SAMPLER_IMPL);
if (impl.equals(CPU_SAMPLER_SAMPLER_IMPL)) {
mon.attach(new CPUSampler(this.properties.getRequiredPropertyAsInt(CPU_SAMPLER_SAMPLER_IMPL_SIZE)));
} else if (impl.equals(CPU_SAMPLER_BURNING_IMPL)) {
mon.attach(new CPUBurningVMsSampler(this.properties.getRequiredPropertyAsInt(CPU_SAMPLER_BURNING_IMPL_SIZE)));
} else {
throw new MonitorFactoryException("Unknown implementation '" + impl + "' for property '" + CPU_SAMPLER_IMPL + "'");
}
}
}
}