/* The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * http://www.sun.com/cddl/cddl.html or * install_dir/legal/LICENSE * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at install_dir/legal/LICENSE. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id$ * * Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved */ package com.sun.faban.harness.agent; import com.sun.faban.harness.common.Config; import com.sun.faban.harness.engine.DeployImageClassLoader; import com.sun.faban.harness.tools.CommandLineTool; import com.sun.faban.harness.tools.MasterToolContext; import com.sun.faban.harness.tools.ToolDescription; import com.sun.faban.harness.tools.ToolWrapper; import com.sun.faban.harness.util.XMLReader; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import java.io.File; import java.io.IOException; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.rmi.server.Unreferenced; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; import java.util.logging.Logger; /** * This class implements the ToolAgent interface. * It runs in a seperate VM and is started by the GenericBenchmark. * It configures and manages all tools on a particular machine * and performs the ToolService API functions for this machine. * Each tool is run as a seperate thread. * * @see com.sun.faban.harness.engine.ToolService * @see com.sun.faban.harness.engine.GenericBenchmark * @author Ramesh Ramachandran */ public class ToolAgentImpl extends UnicastRemoteObject implements ToolAgent, Unreferenced { String toolNames[]; ToolWrapper tools []; // handles to the Tool objects int numTools; static String masterMachine = null; // name of master machine static String host; // our current hostname Logger logger; CountDownLatch latch; /** * Constructor for Tool agent implementation. * @throws java.rmi.RemoteException Error constructing ToolAgentImpl */ public ToolAgentImpl() throws RemoteException { super(); logger = Logger.getLogger(this.getClass().getName()); host = CmdAgentImpl.getHost(); masterMachine = CmdAgentImpl.getMaster(); logger.fine("Started processing tools"); } /** * This method configures the tools that must be run on * this machine by calling the configure method on each of * the specified tools. * @param toolList - each element in the array is the * name of a tool and optional arguments, e.g "sar -u -c" * @param osToolSet list of os tools * @param outDir output directory of the run * @throws IOException * */ public void configure(List<MasterToolContext> toolList, Set<String> osToolSet, String outDir) throws IOException { List<MasterToolContext> toollist = new ArrayList<MasterToolContext>(); if(toolList != null) toollist.addAll(toolList); LinkedHashMap<String, List<String>> toolSetsMap = parseOSToolSets(); if (osToolSet != null) { for (String tool : osToolSet) { StringTokenizer tt = new StringTokenizer(tool); String toolId = tt.nextToken(); Set<String> toolsetTools = new LinkedHashSet<String>(); if (toolSetsMap.containsKey(toolId)) { toolsetTools.addAll(toolSetsMap.get(toolId)); for (String t1 : toolsetTools) { MasterToolContext tCtx = new MasterToolContext( t1, null, null); if (tCtx != null) { toollist.add(tCtx); } } } else { MasterToolContext tCtx = new MasterToolContext( tool, null, null); if (tCtx != null) { toollist.add(tCtx); } } } } numTools = toollist.size(); toolNames = new String[numTools]; tools = new ToolWrapper[numTools]; logger.fine("Processing tools"); latch = new CountDownLatch(toollist.size()); for (int i=0; i<toollist.size(); i++) { MasterToolContext ctx = toollist.get(i); String toolId = ctx.getToolId(); toolNames[i] = toolId; //List<String> args = Command.parseArgs(ctx.getToolParams()); String path = null; int nameIdx = toolId.lastIndexOf(File.separator) + 1; if (nameIdx > 0) { path = toolId.substring(0, nameIdx - 1); toolId = toolId.substring(nameIdx); } if (path != null && path.length() == 0) path = null; String toolClass = null; ToolDescription toolDesc = ctx.getToolDescription(); if (toolDesc != null) toolClass = toolDesc.getToolClass(); // Now, create the tool object and call its configure method if (toolClass != null) { try { DeployImageClassLoader loader = DeployImageClassLoader. getInstance(toolDesc.getLocationType(), toolDesc.getLocation(), getClass().getClassLoader()); Class c = loader.loadClass(toolClass); tools[i] = new ToolWrapper(c, ctx); logger.fine("Trying to run tool " + c.getName()); tools[i].configure(toolNames[i], path, outDir, host, CmdAgentImpl.getHandle(), latch); } catch (ClassNotFoundException ce) { logger.log(Level.WARNING, "Class " + toolClass + " not found"); latch.countDown(); } catch (Exception ie) { logger.log(Level.WARNING, "Error in creating tool object " + toolClass, ie); latch.countDown(); // Tool did not get started. } } else if (!"default".equals(ctx.getToolId()) || (ctx.getToolParams() != null && ctx.getToolParams().trim().length() > 0)) { try { tools[i] = new ToolWrapper(CommandLineTool.class, ctx); tools[i].configure(toolNames[i], path, outDir, host, CmdAgentImpl.getHandle(), latch); logger.fine("Trying to run tool " + tools[i] + " using CommandLineTool."); } catch (Exception ex) { logger.log(Level.WARNING, "Cannot start CommandLineTool!", ex); latch.countDown(); } } else { latch.countDown(); } } } /** * This method is responsible for starting all tools. * @param delay - time to delay before starting * @return true if all tools started successfully, else false * @throws RemoteException */ public boolean start(int delay) throws RemoteException { int i; boolean ret = true; for (i = 0; i < tools.length; i++) { if (tools[i] == null || ! tools[i].start(delay)) { ret = false; logger.severe("Could not start tool " + toolNames[i]); } } return(ret); } /** * This method is responsible for starting all tools. * @param delay - time to delay before starting * @param duration after which tools must be stopped * @return true if all tools started successfully, else false * @throws RemoteException */ public boolean start(int delay, int duration) throws RemoteException { int i; boolean ret = true; for (i = 0; i < tools.length; i++) { if (tools[i] == null || ! tools[i].start(delay, duration)) { ret = false; logger.severe("Could not start tool " + toolNames[i]); } } return(ret); } /** * Start only specified tools. * @param delay - time to delay before starting * @param t - specific list of tools to start * @return true if all tools are started successfully, false otherwise * @throws RemoteException A communication error occurred */ public boolean start(int delay, String[] t) throws RemoteException { int i, j; boolean ret = true; for (j = 0; j < t.length; j++) { for (i = 0; i < tools.length; i++) { if (toolNames[i].equals(t[j])) { if ( tools[i] == null || ! tools[i].start(delay)) { ret = false; logger.severe("Could not start tool " + toolNames[i]); } break; } } } return(ret); } /** * Start only specified tools for specific duration. * @param delay - time to delay before starting * @param t - specific list of tools to start * @param duration after which tools must be stopped * @return true if all tools are started successfully, false otherwise * @throws RemoteException A communication error occurred */ public boolean start(int delay, String[] t, int duration) throws RemoteException { int i, j; boolean ret = true; for (j = 0; j < t.length; j++) { for (i = 0; i < tools.length; i++) { if (toolNames[i].equals(t[j])) { if ( tools[i] == null || ! tools[i].start(delay, duration)) { ret = false; logger.severe("Could not start tool " + toolNames[i]); } break; } } } return(ret); } /** * This method is responsible for stopping the tools. */ public void stop() { for (int i = 0; i < tools.length; i++) { if (tools[i] != null){ try { tools[i].stop(); } catch (Exception e) { logger.log(Level.WARNING, "ToolAgent: toolName = " + toolNames[i] + " cannot stop", e); } } } } /** * Stopping specific tools. * @param t The tools to stop. */ public void stop(String t[]) { for (String tool : t) { for (int i = 0; i < tools.length; i++) { if (tools[i] != null && toolNames[i].equals(tool)) { try { tools[i].stop(); } catch (Exception ex) { logger.log(Level.SEVERE, null, ex); } break; } } } } /** * This method is responsible for post processing tools. */ public void postprocess() { for (int i = 0; i < tools.length; i++) { if (tools[i] != null){ try { logger.finer("Postprocessing " + toolNames[i]); tools[i].postprocess(); } catch (Exception e) { logger.log(Level.WARNING, "ToolAgent: toolName = " + toolNames[i] + " cannot stop", e); } } } } /** * Waits for all tools to finish up. */ public void waitFor() { try { latch.await(); } catch (InterruptedException e) { logger.log(Level.WARNING, "Interrupted waiting for tools to finish.", e); } } /** * Kills all the tools. */ public void kill() { logger.info("Killing tools"); for (int i = 0; i < tools.length; i++){ if (tools[i] != null){ try { tools[i].kill(); } catch (Exception e) { logger.log(Level.WARNING, "ToolAgent: toolName = " + toolNames[i] + " cannot kill", e); } } } } /** * When this instance is unreferenced the application must exit. * * @see java.rmi.server.Unreferenced * */ public void unreferenced() { kill(); } /** * Obtains the OS toolsets. * @return LinkedHashMap */ protected LinkedHashMap<String, List<String>> parseOSToolSets() { LinkedHashMap<String, List<String>> toolSetsMap = new LinkedHashMap<String, List<String>>(); File toolsetsXml = new File(Config.CONFIG_DIR + Config.OS_DIR + "toolsets.xml"); try { if(toolsetsXml.exists()){ XMLReader reader = new XMLReader(Config.CONFIG_DIR + Config.OS_DIR + "toolsets.xml"); Element root; if (reader != null) { root = reader.getRootNode(); // First, parse the services. NodeList toolsetsNodes = reader.getNodes("toolset", root); for (int i = 0; i < toolsetsNodes.getLength(); i++) { Node toolsetsNode = toolsetsNodes.item(i); if (toolsetsNode.getNodeType() != Node.ELEMENT_NODE) { continue; } Element tse = (Element) toolsetsNode; ArrayList<String> toolsCmds = new ArrayList<String>(); String name = reader.getValue("name", tse); String base = reader.getValue("base", tse); List<String> toolIncludes = reader.getValues("includes", tse); List<String> toolExcludes = reader.getValues("excludes", tse); if(!"".equals(base)){ toolsCmds.addAll(toolSetsMap.get(base)); } if(toolIncludes != null){ for (String tool : toolIncludes){ StringTokenizer st = new StringTokenizer(tool, ";"); while(st.hasMoreTokens()) toolsCmds.add(st.nextToken().trim()); } } if(toolExcludes != null){ ArrayList<String> td = new ArrayList<String>(); for (String tool : toolExcludes){ StringTokenizer st = new StringTokenizer(tool, ";"); while(st.hasMoreTokens()) td.add(st.nextToken().trim()); } toolsCmds.removeAll(td); } if (!"".equals(name) && (toolIncludes != null || base != null)) { if (toolSetsMap.containsKey(name)) { logger.log(Level.WARNING, "Ignoring duplicate toolset = " + name); } else { toolSetsMap.put(name, toolsCmds); } } } } } } catch (Exception e) { logger.log(Level.WARNING, "Error reading toolsets.xml ", e); } return toolSetsMap; } }