• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2000, 2009 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.test.internal.performance.results.ui;
12 
13 import java.io.BufferedOutputStream;
14 import java.io.DataOutputStream;
15 import java.io.File;
16 import java.io.FileNotFoundException;
17 import java.io.FileOutputStream;
18 import java.io.IOException;
19 import java.util.HashSet;
20 import java.util.Iterator;
21 import java.util.Set;
22 
23 import org.eclipse.core.runtime.preferences.InstanceScope;
24 import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
25 import org.eclipse.jface.action.Action;
26 import org.eclipse.jface.action.IAction;
27 import org.eclipse.jface.action.IMenuManager;
28 import org.eclipse.jface.action.Separator;
29 import org.eclipse.jface.dialogs.MessageDialog;
30 import org.eclipse.jface.resource.JFaceResources;
31 import org.eclipse.jface.viewers.AbstractTreeViewer;
32 import org.eclipse.jface.viewers.ISelectionChangedListener;
33 import org.eclipse.jface.viewers.SelectionChangedEvent;
34 import org.eclipse.jface.viewers.StructuredSelection;
35 import org.eclipse.jface.viewers.TreeViewer;
36 import org.eclipse.jface.viewers.Viewer;
37 import org.eclipse.jface.viewers.ViewerFilter;
38 import org.eclipse.jface.viewers.ViewerSorter;
39 import org.eclipse.swt.SWT;
40 import org.eclipse.swt.graphics.Font;
41 import org.eclipse.swt.graphics.FontData;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Display;
44 import org.eclipse.test.internal.performance.results.model.BuildResultsElement;
45 import org.eclipse.test.internal.performance.results.model.ComponentResultsElement;
46 import org.eclipse.test.internal.performance.results.model.ConfigResultsElement;
47 import org.eclipse.test.internal.performance.results.model.ResultsElement;
48 import org.eclipse.test.internal.performance.results.model.ScenarioResultsElement;
49 import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
50 import org.eclipse.test.internal.performance.results.utils.Util;
51 import org.eclipse.ui.IMemento;
52 import org.eclipse.ui.PlatformUI;
53 import org.eclipse.ui.model.WorkbenchContentProvider;
54 import org.eclipse.ui.model.WorkbenchLabelProvider;
55 
56 /**
57  * View to see the performance results of all the components in a hierarchical tree.
58  * <p>
59  * A component defines several performance scenarios which are run on several
60  * machines (aka config). All builds results are stored onto each configuration
61  * and 2 dimensions have been stored for each result: the "Elapsed Process Time"
62  * and the "CPU Time".
63  * </p><p>
64  * There's only one available action from this view: read the local data files. This
65  * populates the hierarchy with the numbers stored in these files.
66  * </p><p>
67  * There's also the possibility to filter the results:
68  * 	<ul>
69  *	<li>Filter for builds:
70  *		<ul>
71  *		<li>Filter baselines:	hide the baselines (starting with R-3.x)</li>
72  *		<li>Filter nightly:	hide the nightly builds (starting with 'N')</li>
73  *		<li>Filter non-important builds:	hide all non-important builds, which means non-milestone builds and those after the last milestone</li>
74  *		</ul>
75  *	</li>
76  *	</li>Filter for scenarios:
77  *		<ul>
78  *		<li>Filter non-fingerprints: hide the scenarios which are not in the fingerprints</li>
79  *		</ul>
80  *	</li>
81  *	</ul>
82  * </p>
83  * @see ComponentResultsView
84  */
85 public class ComponentsView extends PerformancesView {
86 
87 	// Viewer filters
88 	final static ViewerFilter FILTER_ADVANCED_SCENARIOS = new ViewerFilter() {
89 		public boolean select(Viewer v, Object parentElement, Object element) {
90 			if (element instanceof ScenarioResultsElement) {
91 				ScenarioResultsElement scenarioElement = (ScenarioResultsElement) element;
92 				return scenarioElement.hasSummary();
93 			}
94 	        return true;
95         }
96 	};
97 
98 	// Views
99 	PerformancesView buildsView;
100 	ComponentResultsView componentResultsView = null;
101 
102 	// Internal
103 	Set expandedComponents = new HashSet();
104 	File resultsDir = null;
105 
106 	// Actions
107 	Action filterAdvancedScenarios;
108 	Action writeStatus;
109 
110 	// SWT resources
111 	Font boldFont;
112 
113 	// Write Status
114 	static int WRITE_STATUS;
115 
116 /**
117  * Default constructor.
118  */
ComponentsView()119 public ComponentsView() {
120 //	this.onlyFingerprintsImageDescriptor = ImageDescriptor.createFromFile(getClass(), "filter_ps.gif");
121 	super();
122 
123 	// Get preferences
124 	this.preferences = new InstanceScope().getNode(IPerformancesConstants.PLUGIN_ID);
125 
126 	// Init status
127 	WRITE_STATUS = this.preferences.getInt(IPerformancesConstants.PRE_WRITE_STATUS, IPerformancesConstants.DEFAULT_WRITE_STATUS);
128 
129 }
130 
131 /*
132  * (non-Javadoc)
133  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#createPartControl(org.eclipse.swt.widgets.Composite)
134  */
createPartControl(Composite parent)135 public void createPartControl(Composite parent) {
136 	super.createPartControl(parent);
137 
138 	// Create the viewer
139 	this.viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
140 
141 	// Set the content provider: first level is components list
142 	WorkbenchContentProvider contentProvider = new WorkbenchContentProvider() {
143 		public Object[] getElements(Object o) {
144 			return ComponentsView.this.getElements();
145 		}
146 	};
147 	this.viewer.setContentProvider(contentProvider);
148 
149 	// Set the label provider
150 	WorkbenchLabelProvider labelProvider = new WorkbenchLabelProvider() {
151 
152 		protected String decorateText(String input, Object element) {
153 			String text = super.decorateText(input, element);
154 			if (element instanceof BuildResultsElement) {
155 				BuildResultsElement buildElement = (BuildResultsElement) element;
156 				if (buildElement.isMilestone()) {
157 					text = Util.getMilestoneName(buildElement.getName()) + " - "+text;
158 				}
159 			}
160 			return text;
161 		}
162 
163 		// When all scenarios are displayed, then set fingerprints one in bold.
164 		public Font getFont(Object element) {
165 			Font font = super.getFont(element);
166 			if (element instanceof ScenarioResultsElement) {
167 //				Action fingerprints = ComponentsView.this.filterNonFingerprints;
168 //				if (fingerprints != null && !fingerprints.isChecked()) {
169 				boolean fingerprints = ComponentsView.this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
170 				if (!fingerprints) {
171 					ScenarioResultsElement scenarioElement = (ScenarioResultsElement) element;
172 					if (scenarioElement.hasSummary()) {
173 						return getBoldFont(font);
174 					}
175 				}
176 			}
177 			if (element instanceof BuildResultsElement) {
178 				BuildResultsElement buildElement = (BuildResultsElement) element;
179 				if (Util.isMilestone(buildElement.getName())) {
180 					return getBoldFont(font);
181 				}
182 			}
183 			return font;
184 		}
185 	};
186 	this.viewer.setLabelProvider(labelProvider);
187 
188 	// Set the children sorter
189 	ViewerSorter nameSorter = new ViewerSorter() {
190 
191 		// Sort children using specific comparison (see the implementation
192 		// of the #compareTo(Object) in the ResultsElement hierarchy
193 		public int compare(Viewer view, Object e1, Object e2) {
194 			// Config and Build results are sorted in reverse order
195 			if (e1 instanceof BuildResultsElement) {
196 				ResultsElement element = (ResultsElement) e2;
197 				return element.compareTo(e1);
198 			}
199 			if (e1 instanceof ResultsElement) {
200 				ResultsElement element = (ResultsElement) e1;
201 				return element.compareTo(e2);
202 			}
203 			return super.compare(view, e1, e2);
204 		}
205 	};
206 	this.viewer.setSorter(nameSorter);
207 
208 	// Add results view as listener to viewer selection changes
209 	Display.getDefault().asyncExec(new Runnable() {
210 		public void run() {
211 			ISelectionChangedListener listener = getResultsView();
212 			if (listener != null) {
213 				ComponentsView.this.viewer.addSelectionChangedListener(listener);
214 			}
215 		}
216 	});
217 
218 	// Finalize viewer initialization
219 	PlatformUI.getWorkbench().getHelpSystem().setHelp(this.viewer.getControl(), "org.eclipse.test.performance.ui.components");
220 	finalizeViewerCreation();
221 }
222 
223 /*
224  * (non-Javadoc)
225  * @see org.eclipse.ui.part.WorkbenchPart#dispose()
226  */
dispose()227 public void dispose() {
228 	if (this.boldFont != null) {
229 		this.boldFont.dispose();
230 	}
231 //	JFaceResources.getResources().destroyImage(this.onlyFingerprintsImageDescriptor);
232 	super.dispose();
233 }
234 
235 /*
236  * (non-Javadoc)
237  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#fillLocalPullDown(org.eclipse.jface.action.IMenuManager)
238  */
fillFiltersDropDown(IMenuManager manager)239 void fillFiltersDropDown(IMenuManager manager) {
240 	super.fillFiltersDropDown(manager);
241 	manager.add(this.filterOldBuilds);
242 	manager.add(this.filterLastBuilds);
243 	manager.add(new Separator());
244 	manager.add(this.filterAdvancedScenarios);
245 }
246 
fillLocalPullDown(IMenuManager manager)247 void fillLocalPullDown(IMenuManager manager) {
248 	super.fillLocalPullDown(manager);
249 	manager.add(new Separator());
250 	manager.add(this.writeStatus);
251 }
252 
253 /*
254  * Filter non fingerprints scenarios action run.
255  */
filterAdvancedScenarios(boolean fingerprints, boolean updatePreference)256 void filterAdvancedScenarios(boolean fingerprints, boolean updatePreference) {
257 	this.results.setFingerprints(fingerprints);
258 	if (fingerprints) {
259 		this.viewFilters.add(FILTER_ADVANCED_SCENARIOS);
260 	} else {
261 		this.viewFilters.remove(FILTER_ADVANCED_SCENARIOS);
262 	}
263 	this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, fingerprints);
264 	updateFilters();
265 }
266 
267 /*
268  * Returns the bold font.
269  */
getBoldFont(Font font)270 Font getBoldFont(Font font) {
271 	if (this.boldFont == null) {
272 		FontData[] fontData = (font==null ? JFaceResources.getDefaultFont() : font).getFontData();
273 		FontData boldFontData = new FontData(fontData[0].getName(), fontData[0].getHeight(), SWT.BOLD);
274 		this.boldFont = new Font(this.display, boldFontData);
275 	}
276 	return this.boldFont;
277 }
278 
279 /*
280  * Get all the components from the model.
281  */
getElements()282 Object[] getElements() {
283 	if (this.results == null) {
284 		initResults();
285 		if (this.filterAdvancedScenarios != null) {
286 			this.results.setFingerprints(this.filterAdvancedScenarios.isChecked());
287 		}
288 	}
289 	return this.results.getElements();
290 }
291 
292 /*
293  * Return the components results view.
294  */
getResultsView()295 ComponentResultsView getResultsView() {
296 	if (this.componentResultsView == null) {
297 		this.componentResultsView = (ComponentResultsView) getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsResultsView");
298 	}
299 	return this.componentResultsView;
300 }
301 
302 /*
303  * Return the builds view.
304  */
getSiblingView()305 PerformancesView getSiblingView() {
306 	if (this.buildsView == null) {
307 		this.buildsView = (PerformancesView) getWorkbenchView("org.eclipse.test.internal.performance.results.ui.BuildsView");
308 	}
309 	return this.buildsView;
310 }
311 
312 /*
313  * (non-Javadoc)
314  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#makeActions()
315  */
makeActions()316 void makeActions() {
317 
318 	super.makeActions();
319 
320 	// Filter non-fingerprints action
321 	this.filterAdvancedScenarios = new Action("Advanced &Scenarios", IAction.AS_CHECK_BOX) {
322 		public void run() {
323 			filterAdvancedScenarios(isChecked(), true/*update preference*/);
324         }
325 	};
326 	this.filterAdvancedScenarios.setChecked(true);
327 	this.filterAdvancedScenarios.setToolTipText("Filter advanced scenarios (i.e. not fingerprint ones)");
328 
329 	// Write status
330 	this.writeStatus = new Action("Write status") {
331 		public void run() {
332 
333 			// Get write directory
334 			String filter = (ComponentsView.this.resultsDir == null) ? null : ComponentsView.this.resultsDir.getPath();
335 			final File writeDir = changeDir(filter, "Select a directory to write the status");
336 			if (writeDir != null) {
337 				writeStatus(writeDir);
338 			}
339         }
340 	};
341 	this.writeStatus.setEnabled(true);
342 	this.writeStatus.setToolTipText("Write component status to a file");
343 
344 	// Set filters default
345 	this.filterBaselineBuilds.setChecked(true);
346 	this.filterNightlyBuilds.setChecked(false);
347 }
348 
349 /* (non-Javadoc)
350  * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
351  */
preferenceChange(PreferenceChangeEvent event)352 public void preferenceChange(PreferenceChangeEvent event) {
353 	String propertyName = event.getKey();
354 	Object newValue = event.getNewValue();
355 
356 	// Filter non-fingerprints change
357 	if (propertyName.equals(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS)) {
358 		boolean checked = newValue == null ? IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS : "true".equals(newValue);
359 		filterAdvancedScenarios(checked, false/*do not update preference*/);
360 		this.filterAdvancedScenarios.setChecked(checked);
361 	}
362 
363 	// Filter non-milestone change
364 	if (propertyName.equals(IPerformancesConstants.PRE_FILTER_OLD_BUILDS)) {
365 		boolean checked = newValue == null ? IPerformancesConstants.DEFAULT_FILTER_OLD_BUILDS : "true".equals(newValue);
366 		filterOldBuilds(checked, false/*do not update preference*/);
367 		this.filterOldBuilds.setChecked(checked);
368 	}
369 
370 	// Write status
371 	if (propertyName.equals(IPerformancesConstants.PRE_WRITE_STATUS)) {
372 		WRITE_STATUS = newValue == null ? IPerformancesConstants.DEFAULT_WRITE_STATUS : Integer.parseInt((String)newValue);
373 	}
374 
375 	super.preferenceChange(event);
376 }
377 
restoreState()378 void restoreState() {
379 	super.restoreState();
380 
381 	// Filter baselines action default
382 	if (this.viewState == null) {
383 		this.filterBaselineBuilds.setChecked(true);
384 		this.viewFilters.add(FILTER_BASELINE_BUILDS);
385 	} else {
386 		String dir = this.viewState.getString(IPerformancesConstants.PRE_WRITE_RESULTS_DIR);
387 		if (dir != null) {
388 			this.resultsDir = new File(dir);
389 		}
390 	}
391 
392 	// Filter non fingerprints action state
393 	boolean checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
394 	this.filterAdvancedScenarios.setChecked(checked);
395 	if (checked) {
396 		this.viewFilters.add(FILTER_ADVANCED_SCENARIOS);
397 	}
398 }
399 
saveState(IMemento memento)400 public void saveState(IMemento memento) {
401 	if (this.resultsDir != null) {
402 		memento.putString(IPerformancesConstants.PRE_WRITE_RESULTS_DIR, this.resultsDir.getPath());
403 	}
404 	super.saveState(memento);
405 }
406 
407 /**
408  * Select a results element in the tree.
409  */
select(ComponentResultsElement componentResults, String configName, String scenarioName, String buildName)410 public void select(ComponentResultsElement componentResults, String configName, String scenarioName, String buildName) {
411 
412 	// Collapse previous expanded components except the requested one
413 	// TODO (frederic) also collapse expanded components children elements
414 	this.expandedComponents.remove(componentResults);
415 	Iterator iterator = this.expandedComponents.iterator();
416 	while (iterator.hasNext()) {
417 		this.viewer.collapseToLevel(iterator.next(), AbstractTreeViewer.ALL_LEVELS);
418 	}
419 	this.expandedComponents.clear();
420 
421 	// Set the tree selection
422 	ScenarioResultsElement scenarioResultsElement = (ScenarioResultsElement) componentResults.getResultsElement(scenarioName);
423 	if (scenarioResultsElement != null) {
424 		ConfigResultsElement configResultsElement = (ConfigResultsElement) scenarioResultsElement.getResultsElement(configName);
425 		if (configResultsElement != null) {
426 			BuildResultsElement buildResultsElement = (BuildResultsElement) configResultsElement.getResultsElement(buildName);
427 			if (buildResultsElement != null) {
428 				this.viewer.setSelection(new StructuredSelection(buildResultsElement), true);
429 				this.setFocus();
430 			}
431 		}
432 	}
433 }
434 
435 /*
436  * (non-Javadoc)
437  * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
438  */
selectionChanged(SelectionChangedEvent event)439 public void selectionChanged(SelectionChangedEvent event) {
440 	super.selectionChanged(event);
441 	ResultsElement eventResultsElement = (ResultsElement) ((StructuredSelection)event.getSelection()).getFirstElement();
442 	if (eventResultsElement != null) {
443 		ResultsElement eventComponentElement = eventResultsElement;
444 		if (!(eventComponentElement instanceof ComponentResultsElement)) {
445 			while (!(eventComponentElement instanceof ComponentResultsElement)) {
446 				eventComponentElement = (ResultsElement) eventComponentElement.getParent(null);
447 			}
448 			this.expandedComponents.add(eventComponentElement);
449 		}
450 	}
451 }
452 
writeStatus(File writeDir)453 protected void writeStatus(File writeDir) {
454 		this.resultsDir = writeDir;
455 		if (this.filterAdvancedScenarios.isChecked()) {
456 			writeDir = new File(writeDir, "fingerprints");
457 		} else {
458 			writeDir = new File(writeDir, "all");
459 		}
460 		writeDir.mkdir();
461 		if ((WRITE_STATUS & IPerformancesConstants.STATUS_VALUES) != 0) {
462 			writeDir = new File(writeDir, "values");
463 		}
464 		int buildsNumber = WRITE_STATUS & IPerformancesConstants.STATUS_BUILDS_NUMBER_MASK;
465 		if (buildsNumber > 1) {
466 			writeDir = new File(writeDir, Integer.toString(buildsNumber));
467 		}
468 		writeDir.mkdirs();
469 		String prefix = this.results.getName();
470 		File resultsFile = new File(writeDir, prefix+".log");
471 		File exclusionDir = new File(writeDir, "excluded");
472 		exclusionDir.mkdir();
473 		File exclusionFile = new File(exclusionDir, prefix+".log");
474 		if (resultsFile.exists()) {
475 			int i=0;
476 			File saveDir = new File(writeDir, "save");
477 			saveDir.mkdir();
478 			while (true) {
479 				String newFileName = prefix+"_";
480 				if (i<10) newFileName += "0";
481 				newFileName += i;
482 				File renamedFile = new File(saveDir, newFileName+".log");
483 				if (resultsFile.renameTo(renamedFile)) {
484 					File renamedExclusionFile = new File(exclusionDir, newFileName+".log");
485 					exclusionFile.renameTo(renamedExclusionFile);
486 					break;
487 				}
488 				i++;
489 			}
490 		}
491 
492 		// Write status
493 		StringBuffer excluded = this.results.writeStatus(resultsFile, WRITE_STATUS);
494 		if (excluded == null) {
495 			MessageDialog.openWarning(this.shell, getTitleToolTip(), "The component is not read, hence no results can be written!");
496 		}
497 
498 		// Write exclusion file
499 		try {
500 			DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(exclusionFile)));
501 			try {
502 				stream.write(excluded.toString().getBytes());
503 			}
504 			finally {
505 				stream.close();
506 			}
507 		} catch (FileNotFoundException e) {
508 			System.err.println("Can't create exclusion file"+exclusionFile); //$NON-NLS-1$
509 		} catch (IOException e) {
510 			e.printStackTrace();
511 		}
512 }
513 }