blob: 2da6cc637d462f1db3b3795d949d9e18d9e34aa3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.test.internal.performance.results.db;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.*;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.test.internal.performance.results.utils.Util;
/**
* Root class to handle performance results.
*
* Usually performance results are built for a current build vs. a baseline build.
*
* This class allow to read all data from releng performance database for given
* configurations and scenario pattern.
*
* Then it provides easy and speedy access to all stored results.
*/
public class PerformanceResults extends AbstractResults {
String[] allBuildNames = null;
Map allScenarios;
String lastBuildName; // Name of the last used build
String baselineName; // Name of the baseline build used for comparison
String baselinePrefix;
private String scenarioPattern = "%"; //$NON-NLS-1$
private String[] components;
String[] configNames, sortedConfigNames;
String[] configDescriptions, sortedConfigDescriptions;
private String configPattern;
boolean dbRequired;
boolean needToUpdateLocalFile;
/*
* Local class helping to guess remaining time while reading results from DB
*/
class RemainingTimeGuess {
int all, count;
long start;
double remaining;
RemainingTimeGuess(int all, long start) {
this.all = all;
this.start = start;
}
String display() {
StringBuffer buffer = new StringBuffer(" [elapsed: "); //$NON-NLS-1$
long elapsed = getElapsed();
buffer.append(Util.timeChrono(elapsed));
if (this.count > 0) {
buffer.append(" | left: "); //$NON-NLS-1$
long remainingTime = getRemainingTime(elapsed);
buffer.append(Util.timeChrono(remainingTime));
buffer.append(" | end: "); //$NON-NLS-1$
buffer.append(Util.timeEnd(remainingTime));
}
buffer.append(']');
return buffer.toString();
}
private long getRemainingTime(long elapsed) {
return (long) ((((double)elapsed) / this.count) * (this.all - this.count));
}
private long getElapsed() {
return System.currentTimeMillis() - this.start;
}
}
// Failure threshold
public static final int DEFAULT_FAILURE_THRESHOLD = 10;
int failure_threshold = DEFAULT_FAILURE_THRESHOLD;
public PerformanceResults(PrintStream stream) {
super(null, null);
this.printStream = stream;
this.dbRequired = false;
setDefaults();
}
public PerformanceResults(String name, String baseline, String baselinePrefix, PrintStream stream) {
super(null, name);
this.baselineName = baseline;
this.baselinePrefix = baselinePrefix;
this.printStream = stream;
this.dbRequired = true;
setDefaults();
}
/**
* Returns the list of all builds currently read.
*
* @return The names list of all currently known builds
*/
public String[] getAllBuildNames() {
if (this.allBuildNames == null) {
setAllBuildNames();
}
return this.allBuildNames;
}
/**
* Returns the name of the baseline used for extracted results
*
* @return The build name of the baseline of <code>null</code>
* if no specific baseline is used for the extracted results.
*/
public String getBaselineName() {
return this.baselineName;
}
/*
* Get the baseline prefix (computed from #baselineName).
*/
String getBaselinePrefix() {
return this.baselinePrefix;
}
/*
* Get the build date (see #getBuildDate(String, String)).
*/
public String getBuildDate() {
String buildName = getName();
if (buildName == null) return ""; //$NON-NLS-1$
return Util.getBuildDate(getName(), getBaselinePrefix());
}
/**
* Return the list of components concerned by performance results.
*
* @return The list of the components
*/
public String[] getComponents() {
return this.components;
}
/**
* Get the scenarios of a given component.
*
* @param componentName The component name. Should not be <code>null</code>
* @return A list of {@link ScenarioResults scenario results}
*/
public List getComponentScenarios(String componentName) {
ComponentResults componentResults = (ComponentResults) getResults(componentName);
if (componentResults == null) return null;
return Collections.unmodifiableList(componentResults.children);
}
/**
* Get the scenarios which have a summary for a given component.
*
* @param componentName The component name
* @param config Configuration name
* @return A list of {@link ScenarioResults scenario results} which have a summary
*/
public List getComponentSummaryScenarios(String componentName, String config) {
if (componentName == null) {
int size = size();
List scenarios = new ArrayList();
for (int i=0; i< size; i++) {
ComponentResults componentResults = (ComponentResults) this.children.get(i);
scenarios.addAll(componentResults.getSummaryScenarios(true, config));
}
return scenarios;
}
ComponentResults componentResults = (ComponentResults) getResults(componentName);
return componentResults.getSummaryScenarios(false, config);
}
/**
* Return the configuration boxes considered for this performance results
* sorted or not depending on the given flag.
*
* @param sort Indicates whether the list must be sorted or not.
* The order is defined by the configuration names, not by the box names
* @return The list of configuration boxes sorted by configuration names
*/
public String[] getConfigBoxes(boolean sort) {
return sort ? this.sortedConfigDescriptions : this.configDescriptions;
}
/**
* Return the configuration names considered for this performance results
* sorted or not depending on the given flag.
*
* @param sort Indicates whether the list must be sorted or not
* @return The list of configuration names
*/
public String[] getConfigNames(boolean sort) {
return sort ?this.sortedConfigNames : this.configNames;
}
/*
* Compute a SQL pattern from all stored configuration names.
* For example 'eclipseperflnx1', 'eclipseperflnx2' and 'eclipseperflnx3'
* will return 'eclipseperflnx_'.
*/
String getConfigurationsPattern() {
if (this.configPattern == null) {
int length = this.sortedConfigNames == null ? 0 : this.sortedConfigNames.length;
if (length == 0) return null;
this.configPattern = this.sortedConfigNames[0];
int refLength = this.configPattern.length();
for (int i=1; i<length; i++) {
String config = this.sortedConfigNames[i];
StringBuffer newConfig = null;
if (refLength != config.length()) return null; // strings have not the same length => cannot find a pattern
for (int j=0; j<refLength; j++) {
char c = this.configPattern.charAt(j);
if (config.charAt(j) != c) {
if (newConfig == null) {
newConfig = new StringBuffer(refLength);
if (j == 0) return null; // first char is already different => cannot find a pattern
newConfig.append(this.configPattern.substring(0, j));
}
newConfig.append('_');
} else if (newConfig != null) {
newConfig.append(c);
}
}
if (newConfig != null) {
this.configPattern = newConfig.toString();
}
}
}
return this.configPattern;
}
/**
* Return the name of the last build name except baselines.
*
* @return the name of the last build
*/
public String getLastBuildName() {
return getLastBuildName(1/*all except baselines*/);
}
/**
* Return the name of the last build name
*
* @param kind Decide what kind of build is taken into account
* 0: all kind of build
* 1: all except baseline builds
* 2: all except baseline and nightly builds
* 3: only integration builds
* @return the name of the last build of the selected kind
*/
public String getLastBuildName(int kind) {
if (this.name == null) {
getAllBuildNames(); // init build names if necessary
int idx = this.allBuildNames.length-1;
this.name = this.allBuildNames[idx];
if (kind > 0) {
loop: while (idx-- >= 0) {
switch (this.name.charAt(0)) {
case 'N':
if (kind < 2) break loop;
break;
case 'M':
if (kind < 3) break loop;
break;
case 'I':
if (kind < 4) break loop;
break;
}
this.name = this.allBuildNames[idx];
}
}
}
return this.name;
}
public String getName() {
if (this.name == null) {
setAllBuildNames();
}
return this.name;
}
/*
* (non-Javadoc)
* @see org.eclipse.test.internal.performance.results.AbstractResults#getPerformance()
*/
PerformanceResults getPerformance() {
return this;
}
/**
* Get the results of a given scenario.
*
* @param scenarioName The scenario name
* @return The {@link ScenarioResults scenario results}
*/
public ScenarioResults getScenarioResults(String scenarioName) {
ComponentResults componentResults = (ComponentResults) getResults(DB_Results.getComponentNameFromScenario(scenarioName));
return componentResults == null ? null : (ScenarioResults) componentResults.getResults(scenarioName);
}
/*
* Init configurations from performance results database.
*/
private void initConfigs() {
// create config names
this.configNames = DB_Results.getConfigs();
this.configDescriptions = DB_Results.getConfigDescriptions();
int length = this.configNames.length;
this.sortedConfigNames = new String[length];
for (int i = 0; i < length; i++) {
this.sortedConfigNames[i] = this.configNames[i];
}
// Sort the config names
Arrays.sort(this.sortedConfigNames);
this.sortedConfigDescriptions = new String[length];
for (int i=0; i<length; i++) {
for (int j=0; j<length; j++) {
if (this.sortedConfigNames[i] == this.configNames[j]) { // == is intentional!
this.sortedConfigDescriptions[i] = this.configDescriptions[j];
break;
}
}
}
}
/*
* Read or update data for a build from a directory supposed to have local files.
*/
private String[] read(boolean local, String buildName, String[][] configs, boolean force, File dataDir, String taskName, SubMonitor subMonitor) {
if (local && dataDir == null) {
throw new IllegalArgumentException("Must specify a directory to read local files!"); //$NON-NLS-1$
}
subMonitor.setWorkRemaining(100);
// Update info
long start = System.currentTimeMillis();
int allScenariosSize;
if (DB_Results.DB_CONNECTION) {
try {
// Read all scenarios
allScenariosSize = readScenarios(buildName, subMonitor.newChild(10)) ;
if (allScenariosSize < 0) {
return null;
}
// Read all builds
DB_Results.queryAllVariations(getConfigurationsPattern());
// Refresh configs
if (configs == null) {
initConfigs();
} else {
setConfigInfo(configs);
}
} catch (OperationCanceledException e) {
return null;
}
} else {
if (this.allScenarios == null) return null;
allScenariosSize = this.allScenarios.size();
if (configs != null) {
setConfigInfo(configs);
}
}
// Create corresponding children
int componentsLength = this.components.length;
subMonitor.setWorkRemaining(componentsLength);
RemainingTimeGuess timeGuess = null;
for (int i=0; i<componentsLength; i++) {
String componentName = this.components[i];
List scenarios = this.allScenarios == null ? null : (List) this.allScenarios.get(componentName);
// Manage monitor
int percentage = (int) ((((double)(i+1)) / (componentsLength+1)) * 100);
StringBuffer tnBuffer= taskName==null ? new StringBuffer() : new StringBuffer(taskName);
tnBuffer.append(" ("); //$NON-NLS-1$
if (buildName != null) {
tnBuffer.append(buildName).append(": "); //$NON-NLS-1$
}
tnBuffer.append(percentage).append("%)"); //$NON-NLS-1$
subMonitor.setTaskName(tnBuffer.toString());
StringBuffer subTaskBuffer = new StringBuffer("Component "); //$NON-NLS-1$
subTaskBuffer.append(componentName);
subTaskBuffer.append("..."); //$NON-NLS-1$
subMonitor.subTask(subTaskBuffer.toString());
// Get component results
if (scenarios == null && !local) continue;
ComponentResults componentResults;
if (local || (buildName == null && force)) {
componentResults = new ComponentResults(this, componentName);
addChild(componentResults, true);
} else {
componentResults = (ComponentResults) getResults(componentName);
if (componentResults == null) {
componentResults = new ComponentResults(this, componentName);
addChild(componentResults, true);
}
}
// Read the component results
if (local) {
try {
componentResults.readLocalFile(dataDir, scenarios);
}
catch (FileNotFoundException ex) {
return null;
}
subMonitor.worked(1);
} else {
if (timeGuess == null) {
timeGuess = new RemainingTimeGuess(1+componentsLength+allScenariosSize, start);
}
componentResults.updateBuild(buildName, scenarios, force, dataDir, subMonitor.newChild(1), timeGuess);
}
if (subMonitor.isCanceled()) return null;
}
// Update names
setAllBuildNames();
writeData(dataDir);
// Print time
printGlobalTime(start);
return this.allBuildNames;
}
/**
* Read all data from performance database for the given configurations
* and scenario pattern.
*
* This method is typically called when generated performance results
* from a non-UI application.
*
* @param buildName The name of the build
* @param configs All configurations to extract results. If <code>null</code>,
* then all known configurations ({@link DB_Results#getConfigs()}) are read.
* @param pattern The pattern of the concerned scenarios
* @param dataDir The directory where data will be read/stored locally.
* If <code>null</code>, then database will be read instead and no storage
* will be performed
* @param threshold The failure percentage threshold over which a build result
* value compared to the baseline is considered as failing.
* @param monitor The progress monitor
*
* @return All known build names
*/
public String[] readAll(String buildName, String[][] configs, String pattern, File dataDir, int threshold, IProgressMonitor monitor) {
// Init
this.scenarioPattern = pattern == null ? "%" : pattern; //$NON-NLS-1$
this.failure_threshold = threshold;
SubMonitor subMonitor = SubMonitor.convert(monitor, 1000);
// Set default names
setDefaults();
// Read local data files first
reset(dataDir);
String[] names = read(true, null, configs, true, dataDir, null, subMonitor.newChild(100));
if (names==null) {
// if one local files is missing then force a full DB read!
// TODO moderate this to force the DB read only for the missing file...
return read(false, null, configs, true, dataDir, null, subMonitor.newChild(900));
}
// Search build name in read data
boolean buildMissing = true;
if (buildName != null) {
this.name = buildName;
buildMissing = Arrays.binarySearch(names, buildName, Util.BUILD_DATE_COMPARATOR) < 0;
}
// Look for missing builds
if (buildMissing) {
String[] builds = DB_Results.getBuilds();
Arrays.sort(builds, Util.BUILD_DATE_COMPARATOR);
for (int i=builds.length-1; i>=0; i--) {
if (Arrays.binarySearch(names, builds[i], Util.BUILD_DATE_COMPARATOR) >= 0) {
break;
}
read(false, builds[i], configs, true, dataDir, null, subMonitor.newChild(900));
}
}
return this.allBuildNames;
}
/**
* Read all data from performance database for the given configurations
* and scenario pattern.
*
* Note that calling this method flush all previous read data.
*
* @param dataDir The directory where local files are located
* @param monitor The progress monitor
*/
public void readLocal(File dataDir, IProgressMonitor monitor) {
// Print title
String taskName = "Read local performance results"; //$NON-NLS-1$
println(taskName);
// Create monitor
SubMonitor subMonitor = SubMonitor.convert(monitor, 1000);
subMonitor.setTaskName(taskName);
// Read
reset(dataDir);
read(true, null, null, true, dataDir, taskName, subMonitor);
}
void readLocalFile(File dir) {
if (!dir.exists()) return;
File dataFile = new File(dir, "performances.dat"); //$NON-NLS-1$
if (!dataFile.exists()) return;
DataInputStream stream = null;
try {
// Read local file info
stream = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFile)));
// Read build info
String str = stream.readUTF();
this.needToUpdateLocalFile = this.name == null || Util.getBuildDate(this.name).compareTo(Util.getBuildDate(str)) > 0;
if (this.name != null && Util.getBuildDate(this.name).compareTo(Util.getBuildDate(str)) >= 0) {
return;
}
println(" - read performance results local files info: "); //$NON-NLS-1$
println(" + name : "+str);
this.name = str == "" ? null : str;
str = stream.readUTF();
println(" + baseline : "+str);
if (this.baselineName == null) {
this.baselineName = str == "" ? null : str;
}
str = stream.readUTF();
println(" + baseline prefix: "+str);
this.baselinePrefix = str == "" ? null : str;
// Write configs info
int length = stream.readInt();
println(" + "+length+" configs");
this.configNames = new String[length];
this.sortedConfigNames = new String[length];
this.configDescriptions = new String[length];
this.sortedConfigDescriptions = new String[length];
for (int i = 0; i < length; i++) {
this.configNames[i] = stream.readUTF();
this.sortedConfigNames[i] = this.configNames[i];
this.configDescriptions[i] = stream.readUTF();
this.sortedConfigDescriptions[i] = this.configDescriptions[i];
}
DB_Results.setConfigs(this.configNames);
DB_Results.setConfigDescriptions(this.configDescriptions);
// Write builds info
length = stream.readInt();
println(" + "+length+" builds");
this.allBuildNames = new String[length];
for (int i = 0; i < length; i++) {
this.allBuildNames[i] = stream.readUTF();
}
// Write scenarios info
length = stream.readInt();
println(" + "+length+" components");
this.components = new String[length];
this.allScenarios = new HashMap();
for (int i = 0; i < length; i++) {
this.components[i] = stream.readUTF();
int size = stream.readInt();
List scenarios = new ArrayList(size);
for (int j=0; j<size; j++) {
scenarios.add(new ScenarioResults(stream.readInt(), stream.readUTF(), stream.readUTF()));
}
this.allScenarios.put(this.components[i], scenarios);
}
println(" => read from file "+dataFile); //$NON-NLS-1$
} catch (IOException ioe) {
println(" !!! "+dataFile+" should be deleted as it contained invalid data !!!"); //$NON-NLS-1$ //$NON-NLS-2$
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
// nothing else to do!
}
}
}
private int readScenarios(String buildName, SubMonitor subMonitor) throws OperationCanceledException {
subMonitor.setWorkRemaining(10);
long start = System.currentTimeMillis();
String titleSuffix;
if (buildName == null) {
titleSuffix = "all database scenarios..."; //$NON-NLS-1$
} else {
titleSuffix = "all database scenarios for "+buildName+" build..."; //$NON-NLS-1$ //$NON-NLS-2$
}
print(" + get "+titleSuffix); //$NON-NLS-1$
subMonitor.subTask("Get "+titleSuffix); //$NON-NLS-1$
this.allScenarios = DB_Results.queryAllScenarios(this.scenarioPattern, buildName);
if (this.allScenarios == null) return -1;
int allScenariosSize = 0;
List componentsSet = new ArrayList(this.allScenarios.keySet());
Collections.sort(componentsSet);
int componentsSize = componentsSet.size();
componentsSet.toArray(this.components = new String[componentsSize]);
for (int i=0; i<componentsSize; i++) {
String componentName = this.components[i];
List scenarios = (List) this.allScenarios.get(componentName);
allScenariosSize += scenarios.size();
}
println(" -> "+allScenariosSize+" found in "+(System.currentTimeMillis()-start)+"ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
subMonitor.worked(10);
if (subMonitor.isCanceled()) throw new OperationCanceledException();
return allScenariosSize;
}
void reset(File dataDir) {
this.allBuildNames = null;
this.children = new ArrayList();
// this.name = null;
this.components = null;
this.allScenarios = null;
readLocalFile(dataDir);
}
private void setAllBuildNames() {
SortedSet builds = new TreeSet(Util.BUILD_DATE_COMPARATOR);
int size = size();
if (size == 0) return;
for (int i=0; i<size; i++) {
ComponentResults componentResults = (ComponentResults) this.children.get(i);
Set names = componentResults.getAllBuildNames();
builds.addAll(names);
}
int buildsSize = builds.size();
this.allBuildNames = new String[buildsSize];
if (buildsSize > 0) {
int n = 0;
Iterator buildNames = builds.iterator();
while (buildNames.hasNext()) {
String buildName = (String) buildNames.next();
if (this.lastBuildName == null || Util.getBuildDate(buildName).compareTo(Util.getBuildDate(this.lastBuildName)) <= 0) {
this.allBuildNames[n++] = buildName;
}
}
if (n < buildsSize) {
System.arraycopy(this.allBuildNames, 0, this.allBuildNames = new String[n], 0, n);
}
int idx = n-1;
String lastBuild = this.allBuildNames[idx--];
while (idx > 0 && lastBuild.startsWith(DB_Results.getDbBaselinePrefix())) {
lastBuild = this.allBuildNames[idx--];
}
this.needToUpdateLocalFile = this.name == null || Util.getBuildDate(lastBuild).compareTo(Util.getBuildDate(this.name)) > 0;
this.name = lastBuild;
if (this.baselineName != null) {
String lastBuildDate = Util.getBuildDate(lastBuild);
if (Util.getBuildDate(this.baselineName).compareTo(lastBuildDate) > 0) {
this.baselineName = DB_Results.getLastBaselineBuild(lastBuildDate);
}
}
}
}
private void setConfigInfo(String[][] configs) {
if (configs == null) return;
// Store config information
int length = configs.length;
this.configNames = new String[length];
this.sortedConfigNames = new String[length];
this.configDescriptions = new String[length];
for (int i=0; i<length; i++) {
this.configNames[i] = this.sortedConfigNames[i] = configs[i][0];
this.configDescriptions[i] = configs[i][1];
}
// Sort the config names
Arrays.sort(this.sortedConfigNames);
length = this.sortedConfigNames.length;
this.sortedConfigDescriptions = new String[length];
for (int i=0; i<length; i++) {
for (int j=0; j<length; j++) {
if (this.sortedConfigNames[i] == this.configNames[j]) { // == is intentional!
this.sortedConfigDescriptions[i] = this.configDescriptions[j];
break;
}
}
}
}
/**
* Set the name of the baseline used for extracted results
*
* @param buildName The name of the baseline build
*/
public void setBaselineName(String buildName) {
this.baselineName = buildName;
if (this.baselinePrefix == null || !this.baselineName.startsWith(this.baselinePrefix)) {
// Usually hat baseline name format is *always* x.y_yyyyMMddhhmm_yyyyMMddhhmm
int index = this.baselineName.lastIndexOf('_');
if (index > 0) {
this.baselinePrefix = this.baselineName.substring(0, index);
} else {
// this.baselinePrefix = DB_Results.getDbBaselinePrefix();
this.baselinePrefix = this.baselineName;
}
}
}
private void setDefaults() {
// Set builds if none
if (size() == 0 && DB_Results.DB_CONNECTION) {
this.allBuildNames = DB_Results.getBuilds();
this.components = DB_Results.getComponents();
initConfigs();
}
// Set name if null
if (this.name == null) {
setAllBuildNames();
if (this.name == null) { // does not know any build
this.name = DB_Results.getLastCurrentBuild();
if (this.dbRequired) {
if (this.name == null) {
// throw new RuntimeException("Cannot find any current build!"); //$NON-NLS-1$
this.name = "No current build!";
}
this.allBuildNames = DB_Results.getBuilds();
this.components = DB_Results.getComponents();
initConfigs();
}
if (this.printStream != null) {
this.printStream.println(" + no build specified => use last one: "+this.name); //$NON-NLS-1$
}
}
}
// Init baseline name if not set
if (this.baselineName == null && getName() != null) {
String buildDate = Util.getBuildDate(getName());
this.baselineName = DB_Results.getLastBaselineBuild(buildDate);
if (this.baselineName == null && this.dbRequired) {
throw new RuntimeException("Cannot find any baseline to refer!"); //$NON-NLS-1$
}
if (this.printStream != null) {
this.printStream.println(" + no baseline specified => use last one: "+this.baselineName); //$NON-NLS-1$
}
}
// Init baseline prefix if not set
if (this.baselineName != null) {
if (this.baselinePrefix == null || !this.baselineName.startsWith(this.baselinePrefix)) {
// Usually hat baseline name format is *always* x.y_yyyyMMddhhmm_yyyyMMddhhmm
int index = this.baselineName.lastIndexOf('_');
if (index > 0) {
this.baselinePrefix = this.baselineName.substring(0, index);
} else {
// this.baselinePrefix = DB_Results.getDbBaselinePrefix();
this.baselinePrefix = this.baselineName;
}
}
}
// Set scenario pattern default
if (this.scenarioPattern == null) {
this.scenarioPattern = "%"; //$NON-NLS-1$
}
// Flush print stream
if (this.printStream != null) {
this.printStream.println();
this.printStream.flush();
}
}
public void setLastBuildName(String lastBuildName) {
this.lastBuildName = lastBuildName;
// if (lastBuildName == null) {
// int idx = this.allBuildNames.length-1;
// String lastBuild = this.allBuildNames[idx--];
// while (this.name.startsWith(DB_Results.getDbBaselinePrefix())) {
// lastBuild = this.allBuildNames[idx--];
// }
// this.name = lastBuild;
// } else {
// this.name = lastBuildName;
// }
}
/**
* Update a given build information with database contents.
*
* @param builds The builds to read new data
* @param force Force the update from the database, even if the build is
* already known.
* @param dataDir The directory where data should be stored locally if necessary.
* If <code>null</code>, then information changes won't be persisted.
* @param monitor The progress monitor
* @return All known builds
*/
public String[] updateBuilds(String[] builds, boolean force, File dataDir, IProgressMonitor monitor) {
// Print title
StringBuffer buffer = new StringBuffer("Update data for "); //$NON-NLS-1$
int length = builds == null ? 0 : builds.length;
switch (length) {
case 0:
buffer.append("all builds"); //$NON-NLS-1$
reset(dataDir);
break;
case 1:
buffer.append("one build"); //$NON-NLS-1$
break;
default:
buffer.append("several builds"); //$NON-NLS-1$
break;
}
String taskName = buffer.toString();
println(buffer);
// Create sub-monitor
SubMonitor subMonitor = SubMonitor.convert(monitor, 1000*length);
subMonitor.setTaskName(taskName);
// Read
for (int i=0; i<length; i++) {
if (builds == null) {
throw new RuntimeException("'builds' was unexpected null. Check input data?");
}
read(false, builds[i], null, force, dataDir, taskName, subMonitor.newChild(1000));
}
// Return new builds list
return this.allBuildNames;
}
/**
* Update a given build information with database contents.
*
* @param buildName The build name to read new data
* @param force Force the update from the database, even if the build is
* already known.
* @param dataDir The directory where data should be stored locally if necessary.
* If <code>null</code>, then information changes won't be persisted.
* @param monitor The progress monitor
* @return All known builds
*/
public String[] updateBuild(String buildName, boolean force, File dataDir, IProgressMonitor monitor) {
// Print title
StringBuffer buffer = new StringBuffer("Update data for "); //$NON-NLS-1$
if (buildName == null) {
buffer.append("all builds"); //$NON-NLS-1$
reset(dataDir);
} else {
buffer.append("one build"); //$NON-NLS-1$
}
String taskName = buffer.toString();
println(buffer);
// Create sub-monitor
SubMonitor subMonitor = SubMonitor.convert(monitor, 1000);
subMonitor.setTaskName(taskName);
// Read
read(false, buildName, null, force, dataDir, taskName, subMonitor);
// Refresh name
if (buildName != null && !buildName.startsWith(DB_Results.getDbBaselinePrefix())) {
this.name = buildName;
}
// Return new list all build names
return this.allBuildNames;
}
/*
* Write general information.
*/
void writeData(File dir) {
if (!DB_Results.DB_CONNECTION) {
// Only write new local file if there's a database connection
// otherwise contents may not be complete...
return;
}
if (dir ==null || (!dir.exists() && !dir.mkdirs())) {
System.err.println("can't create directory " + dir); //$NON-NLS-1$
return;
}
File dataFile = new File(dir, "performances.dat"); //$NON-NLS-1$
if (dataFile.exists()) {
if (!this.needToUpdateLocalFile) {
return;
}
dataFile.delete();
}
try {
DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile)));
// Write build info
stream.writeUTF(this.name == null ? DB_Results.getLastCurrentBuild() : this.name);
stream.writeUTF(this.baselineName == null ? DB_Results.getLastBaselineBuild(null) : this.baselineName);
stream.writeUTF(this.baselinePrefix == null ? "" : this.baselinePrefix);
// Write configs info
int length = this.sortedConfigNames.length;
stream.writeInt(length);
for (int i = 0; i < length; i++) {
stream.writeUTF(this.sortedConfigNames[i]);
stream.writeUTF(this.sortedConfigDescriptions[i]);
}
// Write builds info
String[] builds = this.allBuildNames == null ? DB_Results.getBuilds() : this.allBuildNames;
length = builds.length;
stream.writeInt(length);
for (int i = 0; i < length; i++) {
stream.writeUTF(builds[i]);
}
// Write scenarios info
length = this.components.length;
stream.writeInt(length);
for (int i = 0; i < length; i++) {
stream.writeUTF(this.components[i]);
List scenarios = (List) this.allScenarios.get(this.components[i]);
int size = scenarios.size();
stream.writeInt(size);
for (int j=0; j<size; j++) {
final ScenarioResults scenarioResults = (ScenarioResults)scenarios.get(j);
stream.writeInt(scenarioResults.getId());
stream.writeUTF(scenarioResults.getName());
stream.writeUTF(scenarioResults.getLabel());
}
}
// Close
stream.close();
println(" => performance results general data written in file " + dataFile); //$NON-NLS-1$
} catch (FileNotFoundException e) {
System.err.println("can't create output file" + dataFile); //$NON-NLS-1$
} catch (IOException e) {
e.printStackTrace();
}
}
}