| /******************************************************************************* |
| * Copyright (c) 2000, 2009 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 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 updateLocalFileNeed; |
| |
| /* |
| * 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 |
| if (configs == null) { |
| if (this.configNames == null) { |
| initConfigs(); |
| } |
| } else { |
| setConfigInfo(configs); |
| } |
| long start = System.currentTimeMillis(); |
| int allScenariosSize; |
| if (DB_Results.DB_CONNECTION) { |
| try { |
| allScenariosSize = readScenarios(buildName, subMonitor.newChild(10)) ; |
| if (allScenariosSize < 0) { |
| return null; |
| } |
| } catch (OperationCanceledException e) { |
| return null; |
| } |
| } else { |
| if (this.allScenarios == null) return null; |
| allScenariosSize = this.allScenarios.size(); |
| } |
| |
| // 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) { |
| if (buildName == null) { |
| // Read all missing builds |
| String[] builds = DB_Results.getBuilds(); |
| Arrays.sort(builds, Util.BUILD_DATE_COMPARATOR); |
| int lengthDB = builds.length; |
| int lengthLocal = names.length; |
| if (lengthLocal < lengthDB) { |
| int length= lengthDB-lengthLocal; |
| String[] addedBuilds = new String[length]; |
| int idx = length-1; |
| int idxDB = lengthDB-1; |
| while (!this.allBuildNames[lengthLocal-1].equals(builds[idxDB])) { |
| addedBuilds[idx] = builds[idxDB]; |
| idxDB--; |
| idx--; |
| } |
| for (int i=idx+1; i<length; i++) { |
| read(false, addedBuilds[i], configs, true, dataDir, null, subMonitor.newChild(900)); |
| } |
| } |
| } else { |
| // Read the missing build |
| read(false, buildName, 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))); |
| println(" - read performance results local files info: "); //$NON-NLS-1$ |
| |
| // Read build info |
| String str = stream.readUTF(); |
| this.updateLocalFileNeed = this.name == null || !this.name.equals(str); |
| println(" + name : "+str); |
| this.name = str == "" ? null : str; |
| str = stream.readUTF(); |
| println(" + baseline : "+str); |
| 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 { |
| 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) { |
| builds.toArray(this.allBuildNames); |
| int idx = this.allBuildNames.length-1; |
| this.name = this.allBuildNames[idx--]; |
| while (this.name.startsWith(DB_Results.getDbBaselinePrefix())) { |
| this.name = this.allBuildNames[idx--]; |
| } |
| } |
| } |
| |
| 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; |
| } |
| |
| private void setDefaults() { |
| |
| // 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.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.baselinePrefix == null && this.baselineName != null) { |
| // Assume that 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(); |
| } |
| } |
| |
| // 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(); |
| } |
| } |
| |
| /** |
| * 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++) { |
| 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 (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.updateLocalFileNeed) { |
| dataFile.delete(); |
| } else { |
| return; |
| } |
| } else if (!DB_Results.DB_CONNECTION) { |
| // Only write new local file if there's a database connection |
| // otherwise contents may not be complete... |
| return; |
| } |
| 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(); |
| } |
| } |
| |
| } |