/******************************************************************************* * Copyright 2006 - 2012 Vienna University of Technology, * Department of Software Technology and Interactive Systems, IFS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package at.tuwien.minimee.registry; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import org.apache.commons.configuration.Configuration; import org.apache.commons.digester3.Digester; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.tuwien.minimee.migration.engines.IMigrationEngine; import at.tuwien.minimee.migration.engines.MultipleMonitoringMigrationEngine; import at.tuwien.minimee.migration.evaluators.IMinimeeEvaluator; import at.tuwien.minimee.model.ExperienceBase; import at.tuwien.minimee.model.Machine; import at.tuwien.minimee.model.Tool; import at.tuwien.minimee.model.ToolConfig; import at.tuwien.minimee.registry.xml.EngineFactory; import at.tuwien.minimee.registry.xml.EvaluatorFactory; import at.tuwien.minimee.util.StrictErrorHandler; import eu.scape_project.planning.model.measurement.Measure; import eu.scape_project.planning.model.measurement.MeasureConstants; import eu.scape_project.planning.model.measurement.Measurement; import eu.scape_project.planning.model.measurement.ToolExperience; import eu.scape_project.planning.model.values.INumericValue; import eu.scape_project.planning.utils.ConfigurationLoader; /** * This is the internal side of MiniMEE - it contains all tools and * configurations that are exposed as services through {@link MiniMeeRegistry} * * @author cbu * */ public class ToolRegistry { private static Logger log = LoggerFactory.getLogger(ToolRegistry.class); private static final String MINIMEE_HOME = "minimee.home"; private static final String TOOL_CONFIG = "tool-config.xml"; private HashMap<String, ToolConfig> allToolConfigs = new HashMap<String, ToolConfig>(); private HashMap<String, IMigrationEngine> allEngines = new HashMap<String, IMigrationEngine>(); private HashMap<String, Machine> allMachines = new HashMap<String, Machine>(); private HashMap<String, IMinimeeEvaluator> allEvaluators = new HashMap<String, IMinimeeEvaluator>(); private HashMap<String, ToolConfig> benchmarkConfigs = new HashMap<String, ToolConfig>(); private List<Long> timepads = new LinkedList<Long>(); private ExperienceBase eb = new ExperienceBase(); private double benchmarkScore = 1.0; private List<Tool> tools = new ArrayList<Tool>(); private static ToolRegistry me; private ToolRegistry() { } public static ToolRegistry getInstance() { // me = null; if (me == null) { me = new ToolRegistry(); me.reload(); } return me; } private void init() { for (Tool t : tools) { for (ToolConfig c : t.getConfigs()) { allToolConfigs.put(c.getUrl(), c); if (c.isBenchmark()) { benchmarkConfigs.put(c.getUrl(), c); } } } for (IMigrationEngine e : allEngines.values()) { if (e instanceof MultipleMonitoringMigrationEngine) { ((MultipleMonitoringMigrationEngine) e).initEngines(); } } List<Measure> props = me.getMeasures(); log.info("MINIMEE: loaded tools, configs, engines, machines, measurableProperties: " + tools.size() + " tools, " + allToolConfigs.size() + " configs, " + benchmarkConfigs.size() + " of which are used for the benchmark, " + allEngines.size() + " engines, " + allMachines.size() + " machines, " + props.size() + " properties."); log.debug("Listing measurable properties..."); for (Measure p : props) { log.info(p.getName() + " - " + p.getUri()); } } public void addTool(Tool t) { tools.add(t); } public void reload() { clear(); ConfigurationLoader configurationLoader = new ConfigurationLoader(); Configuration configuration = configurationLoader.load(); if (configuration == null) { log.error("An error occurred while reading the properties file."); return; } String home = configuration.getString(MINIMEE_HOME); if (StringUtils.isEmpty(home)) { log.error("minimee.home is not defined. cannot initialize ToolRegistry."); return; } File configFile = new File(home + File.separator + TOOL_CONFIG); if (!configFile.exists()) { log.error("Could not find " + configFile.getAbsolutePath() + ". Cannot initialize ToolRegistry."); } else { try { parseConfig(new FileInputStream(configFile)); init(); } catch (Exception e) { log.error("Failed to reload minimee-config.", e); } } } private void parseConfig(InputStream config) throws IllegalArgumentException { Digester digester = new Digester(); digester.setValidating(true); digester.setErrorHandler(new StrictErrorHandler()); digester.push(this); digester.addObjectCreate("*/tool", Tool.class); digester.addSetProperties("*/tool"); digester.addObjectCreate("*/config", ToolConfig.class); digester.addSetProperties("*/config"); digester.addBeanPropertySetter("*/config/name", "name"); digester.addBeanPropertySetter("*/config/executablePath", "executablePath"); digester.addBeanPropertySetter("*/config/engineName", "engine"); digester.addBeanPropertySetter("*/config/params", "params"); digester.addBeanPropertySetter("*/config/inEnding", "inEnding"); digester.addBeanPropertySetter("*/config/outEnding", "outEnding"); digester.addBeanPropertySetter("*/config/noOutFile", "noOutFile"); digester.addBeanPropertySetter("*/config/initialisationDir", "initialisationDir"); digester.addCallMethod("*/config/evaluators/evaluator", "addEvaluator", 0); digester.addSetNext("*/config", "addConfig"); digester.addSetNext("*/tool", "addTool"); digester.addFactoryCreate("*/evaluators/evaluator", EvaluatorFactory.class); digester.addSetProperties("*/evaluators/evaluator"); digester.addSetNext("*/evaluators/evaluator", "addEvaluator"); digester.addFactoryCreate("*/engine", EngineFactory.class); digester.addSetProperties("*/engine"); digester.addObjectCreate("*/measure", Measure.class); digester.addSetProperties("*/measure", "ID", "uri"); digester.addSetProperties("*/measure", "name", "name"); digester.addSetNext("*/measure", "addMeasure"); digester.addCallMethod("*/includedEngine", "addEngineName", 0); digester.addCallMethod("*/nextEngine", "setNextEngineName", 0); digester.addSetNext("*/engine", "addEngine"); digester.addObjectCreate("*/machine", Machine.class); digester.addSetProperties("*/machine"); digester.addSetNext("*/machine", "addMachine"); try { digester.setUseContextClassLoader(true); digester.setValidating(false); digester.parse(config); // config = // Thread.currentThread().getContextClassLoader().getResourceAsStream(configFile); // engineDigester.setValidating(false); // engineDigester.setUseContextClassLoader(true); // engineDigester.parse(config); } catch (Exception e) { log.error("Error in config file! ", e); } } public List<Tool> getTools() { return tools; } public List<IMigrationEngine> getMigrationEngines() { return null; } public void addMachine(Machine m) { allMachines.put(m.getId(), m); } public void addEngine(IMigrationEngine e) { allEngines.put(e.getName(), e); } public void addEvaluator(IMinimeeEvaluator e) { allEvaluators.put(e.getName(), e); } public HashMap<String, IMigrationEngine> getAllEngines() { return allEngines; } public void setAllEngines(HashMap<String, IMigrationEngine> allEngines) { this.allEngines = allEngines; } public HashMap<String, ToolConfig> getAllToolConfigs() { return allToolConfigs; } public void setAllToolConfigs(HashMap<String, ToolConfig> allTools) { this.allToolConfigs = allTools; } public ToolConfig getToolConfig(String id) { return allToolConfigs.get(id); } public IMigrationEngine getEngine(String name) { return allEngines.get(name); } public Machine getMachine(String name) { return allMachines.get(name); } public IMinimeeEvaluator getEvaluator(String name) { return allEvaluators.get(name); } public List<Measure> getMeasures() { List<Measure> l = new ArrayList<Measure>(); for (IMigrationEngine e : allEngines.values()) { for (Measure p : e.getMeasures()) { if (!l.contains(p)) { l.add(p); } } } return l; } public void setTools(List<Tool> tools) { this.tools = tools; } public double getBenchmarkScore() { return benchmarkScore; } public void setBenchmarkScore(double benchmarkScore) { this.benchmarkScore = benchmarkScore; } public ExperienceBase getEb() { return eb; } public void addTimePad(long time) { timepads.add(time); } /** * @param toolID * @return */ public static String getToolKey(String toolID) { String key = "minimee/"; String toolIdentifier = toolID.substring(toolID.indexOf(key) + key.length()); return toolIdentifier; } /** * checks the timepad for being valid - if so, the measurement is added to * the experience base. Currently not exposed as a web service since minimee * has been integrated with Plato. */ public synchronized boolean addExperience(long otp, String toolID, Measurement m) { if (!timepads.contains(otp)) { return false; } else { addExperience(toolID, m); } return true; } public Measurement addExperience(String config, Measurement m) { eb.addExperience(config, m); return eb.getAverage(config, m); } public double calculateBenchmarkScore() { if (benchmarkConfigs.size() == 0) return 1.0; double score = 0.0; for (String config : benchmarkConfigs.keySet()) { ToolExperience ex = eb.getToolExperience(config); Measurement m = ex.getAverage(MeasureConstants.ELAPSED_TIME_PER_MB); if (m != null) { INumericValue v = (INumericValue) m.getValue(); score += v.value(); } } return score / benchmarkConfigs.size() / 4000; } private void clear(){ allToolConfigs.clear(); allEngines.clear(); allMachines.clear(); allEvaluators.clear(); benchmarkConfigs.clear(); timepads.clear(); tools.clear(); eb = new ExperienceBase(); } }