/*******************************************************************************
 * 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
	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) {
			    subMonitor.worked(1);
				return null;
			}
	         catch (StringIndexOutOfBoundsException ex) {
	             System.err.println("ERROR: Found StringIndexOutOfBoundsException fournd. Possible corruption in DB?");
	             subMonitor.worked(1);
	            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);
		}
        // there are times when the build we want to analyze is not the
        // "last build",
        // such as there may have be subsequent builds, already.
        // so, we only compute this "default behavior" of finding last build, 
		// and equating it to "name", only if lastBuildName has not been set yet.
		// For the case where "-current" is passed as an argument, in GenerateResults, we do 
		// "setLastBuildName" to "current". See bug 455656.
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=455656
		String lastBuild = null;
		// Note: we can not call "getLastBuildName()" because it has the side effects we are 
		// trying to avoid.
        if (this.lastBuildName == null) {
            int idx = n - 1;
            lastBuild = this.allBuildNames[idx--];
            while (idx > 0 && lastBuild.startsWith(DB_Results.getDbBaselinePrefix())) {
                lastBuild = this.allBuildNames[idx--];
            }
        } else {
            lastBuild = this.lastBuildName;
            this.name = lastBuild;
        }
        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
	    // Currently, 10/2015, R-4.5-yyyyMMddhhmm
		int index = this.baselineName.lastIndexOf('-');
		if (index > 0) {
			this.baselinePrefix = this.baselineName.substring(0, index);
		} else { 
		    // use hard coded value (currently R-4.5)
		    this.baselinePrefix = DB_Results.getDbBaselinePrefix();
		}
	}
}

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 (DO_NOT_WRITE_DATA) {
        return;
    }
	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();
	}
}

}
