/* 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.engine;
import com.sun.faban.common.Command;
import com.sun.faban.common.CommandHandle;
import com.sun.faban.harness.ConfigurationException;
import com.sun.faban.harness.ParamRepository;
import com.sun.faban.harness.common.BenchmarkDescription;
import com.sun.faban.harness.common.Config;
import com.sun.faban.harness.common.HostRoles;
import com.sun.faban.harness.common.Run;
import com.sun.faban.harness.services.ServiceManager;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* GenericBenchmark.java
* The Generic Benchmark object is created by the RunDaemon to execute
* a run. It starts up the various Services (CmdService, Servers
* and ToolService), reads the run's Parameters and processes
* the generic parameters.
* It then performs generic system logging of /etc/system, prtdiag
* psrinfo, etc.
* Finally, it creates the actual benchmark object and requests it
* to execute the run.
* When the run completes, it captures more info for system reports
* and exits.
* @author Ramesh Ramachandran
*/
public class GenericBenchmark {
private Run run;
private CmdService cmds = null;
private ToolService tools = null;
private ServiceManager serviceMgr = null;
private boolean needLogs = true;
//private Benchmark bm = null;
private static BenchmarkWrapper bmw = null;
private static Logger logger =
Logger.getLogger(GenericBenchmark.class.getName());
// Flag to detect failed run
private int runStatus = Run.FAILED;
private int stdyState = 0;
/**
* Constructor.
* @param r run
*/
public GenericBenchmark(Run r) {
this.run = r;
}
/**
* Responsible for configuring, starting and stopping services and tools.
* Creates the actual benchmark object and requests it to execute the run.
*/
@SuppressWarnings("static-access")
public void start() {
ParamRepository par = null;
ServerConfig server;
// Read the benchmark description.
BenchmarkDescription benchDesc = run.getBenchDesc();
long startTime; // benchmark start/end time
long endTime;
// Create benchmark object.
logger.fine("Instantiating benchmark class " +
benchDesc.benchmarkClass);
//bm = newInstance(benchDesc);
bmw = BenchmarkWrapper.getInstance(benchDesc);
if (bmw == null)
return;
startTime = System.currentTimeMillis();
// Update the status of the run
try {
run.updateStatus(Run.STARTED);
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to update run status.", e);
return;
}
// Read in user parameters
logger.info("START TIME : " + new java.util.Date());
logger.fine("Reading in user parameters");
try {
try {
par = new ParamRepository(run.getParamFile(), true);
} catch (Exception e) {
logger.log(Level.SEVERE, "Failed to open ParamRepository "
+ run.getParamFile() + '.', e);
return; // can't proceed with benchmark
}
// Create the facade for the benchmark to access.
RunFacade.newInstance(run, par);
try {
bmw.validate();
} catch (Throwable t) {
logger.log(Level.SEVERE, "Benchmark validation failed.", t);
return;
}
try {
// Initialize CmdService
logger.fine("Initializing Command Service");
cmds = new CmdService();
cmds.init();
// We need to place a marker into the Benchmark's META-INF
// directory so if it is shared, download won't happen.
FileWriter runIdFile = new FileWriter(Config.BENCHMARK_DIR +
run.getBenchmarkName() + File.separator +
"META-INF" + File.separator + "RunID");
runIdFile.write(run.getRunId());
runIdFile.close();
// Start CmdAgent on all ENABLED hosts using the JAVA HOME
// Specified JVM options will be used by the Agent when it
// starts java processes
if (!cmds.setup(benchDesc.shortName, par)) {
logger.severe("CmdService setup failed. Exiting");
return;
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Start failed.", e);
return;
}
// Extract host metadata and save it.
HostRoles hr = new HostRoles(par);
cmds.setHostRoles(hr);
try {
hr.write(run.getOutDir() + File.separator + "META-INF" +
File.separator + "hosttypes");
} catch (IOException e) {
logger.log(Level.WARNING, "Error writing hosttypes file!", e);
}
// Reading parameters needed for ToolService
String s = par.getParameter("fa:runControl/fa:rampUp");
if (s != null)
s = s.trim();
if (s == null || s.length() == 0) {
logger.severe("Configuration runControl/rampUp not set.");
return;
}
int delay = 0;
try {
delay = Integer.parseInt(s);
} catch (NumberFormatException e) {
logger.log(Level.SEVERE,
"Parameter rampUp is not a number.", e);
return;
}
if (delay < 0) {
logger.severe("Parameter rampUp is negative");
return;
}
int len = -1;
s = par.getParameter("fa:runControl/fa:steadyState");
if (s != null) {
s = s.trim();
len = s.length();
}
if (len > 0) {
try {
stdyState = Integer.parseInt(s);
} catch (NumberFormatException e) {
logger.log(Level.SEVERE,
"Parameter steadyState is not a number.", e);
return;
}
if (stdyState <= 0) {
logger.severe(
"Parameter steadyState must be more than zero.");
return;
}
}
// Now, process generic server parameters
logger.fine("Processing Generic Parameters");
try {
server = new ServerConfig(run, par);
} catch (ConfigurationException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
return;
}
// Set # of cpus
if (!server.set(cmds)) {
logger.severe("'psradm' Failed! Aborting run.");
return;
}
// Gather /etc/system, prtdiag, psrinfo, uname, ps , vxprint
logger.info("Gathering system configuration");
server.get();
// Configure the benchmark before starting services
try {
bmw.configure();
logger.fine("Configured benchmark " + benchDesc.name);
} catch (Throwable t) {
logger.log(Level.SEVERE, "Run configuration failed!", t);
return;
}
// Deal with the services.
serviceMgr = new ServiceManager(par, run);
logger.fine("Got Service Manager Instance");
// transfer service configuration.
serviceMgr.configure();
logger.fine("Executed services configure method");
// start services
serviceMgr.startup();
serviceMgr.getConfig();
logger.fine("Executed services Startup method");
// Initialize ToolService, call setup with cmds as parameter
logger.fine("Initializing Tool Service");
tools = ToolService.getHandle();
logger.finer("Got Tool Service Handle");
tools.init();
logger.finer("Tool Service Inited");
tools.setup(par, run.getOutDir(), serviceMgr); // If Tools setup fails,
// we ignore it
logger.finer("Tool Service Set Up");
// Calling PreRun to prepare the data, etc.
try {
logger.fine("Calling PreRun for " + benchDesc.name);
bmw.preRun();
} catch (Throwable t) {
logger.log(Level.SEVERE, "PreRun failed!", t);
return;
}
// Now run the benchmark
try {
bmw.start();
logger.fine("Started benchmark " + benchDesc.name);
} catch (Throwable t) {
logger.log(Level.SEVERE, "Run start failed!", t);
return;
}
// Start the tools
try {
if (stdyState > 0) {
tools.start(delay, stdyState);
logger.fine("Started tools with tools." +
"start(delay, stdyState)");
}else{
tools.start(delay);
logger.fine("Started tools with tools.start(delay)");
}
} catch (Exception e) {
logger.log(Level.WARNING, "ToolService not started.", e);
// Keep running. Failing the tools should not fail the
// benchmark.
}
// Wait and end the benchmark
try {
bmw.end();
} catch (Throwable t) {
logger.log(Level.SEVERE, "Run end failed!", t);
return;
}
// s represents the string value of steady state.
// We only call stop here for benchmarks that do not have
// a firm length, i.e. no steady state.
if (s == null || s.length() == 0) {
logger.fine("Stop called for tools");
tools.stop();
logger.fine("Stopped tools");
}
// Even if the run got killed, we can arrive here.
// So we need to check the killed flag first.
if (runStatus != Run.KILLED) {
tools.waitFor();
runStatus = Run.COMPLETED;
}
serviceMgr.getLogs();
needLogs=false;
try {
// Postprocessing may need tools output. So the postRun
// must be called after all tools and services are done.
logger.fine("Calling PostRun for " + benchDesc.name);
bmw.postRun();
} catch (Throwable t) {
logger.log(Level.SEVERE, "PostRun failed!", t);
return;
}
// Benchmark complete, Capture system messages
endTime = System.currentTimeMillis();
logger.info("Benchmark Complete");
server.report(startTime, endTime);
logger.info("END TIME : " + new java.util.Date());
return;
} catch (Throwable t) {
logger.log(Level.SEVERE,
"Unexpected Exception processing benchmark.", t);
} finally { // Ensure we kill the processes in any case.
if (serviceMgr != null){
if(needLogs){
serviceMgr.getLogs();
needLogs=false;
}
serviceMgr.shutdown();
}
postProcess();
_kill();
// We need to place a marker into the Benchmark's META-INF directory
// so if it is shared, download won't happen.
File runIdFile = new File(Config.BENCHMARK_DIR +
run.getBenchmarkName() + File.separator +
"META-INF" + File.separator + "RunID");
if (runIdFile.exists())
runIdFile.delete();
RunFacade.clearInstance();
}
}
/**
* Method : kill
* This method is called externally to abort or terminate
* the current run.
*/
public void kill() {
runStatus = Run.KILLED;
if (serviceMgr != null){
if(needLogs){
serviceMgr.getLogs();
needLogs=false;
}
serviceMgr.shutdown();
}
_kill();
}
/**
* This method is called internally to terminate the current run.
*/
private void _kill() {
try {
run.updateStatus(runStatus);
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to update run status.", e);
}
if(bmw != null) {
logger.info("Killing benchmark");
try {
bmw.kill();
} catch (Throwable t) {
logger.log(Level.WARNING, "Exceptions killing benchmark.", t);
}
}
if (tools != null) {
logger.fine("Calling tools.kill");
tools.kill();
}
if (cmds != null) {
logger.fine("Calling cmds.kill");
cmds.kill();
}
}
/**
* Responsible for doing the postprocessing.
* @return true if successful
*/
private boolean postProcess() {
// Create the dir for storing Xanadu XMLs
String outDir = run.getOutDir();
String postDir = outDir + File.separator + Config.POST_DIR;
if(!(new File(postDir)).mkdirs())
return false;
// Process the text using FenXi.
/** Not required. We generate the graphs dynamically
Command fenxi = new Command ("fenxi", "process", outDir, postDir,
run.getRunId());
fenxi.setWorkingDirectory(Config.FABAN_HOME + "logs");
try {
CommandHandle handle = cmds.execute(fenxi, null);
if (handle.exitValue() != 0)
logger.severe("FenXi process command " + fenxi + " Failed");
} catch(Exception e) {
logger.log(Level.SEVERE, "FenXi process command " + fenxi +
" failed.", e);
return false;
}
*/
return true;
}
}