sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTrace.java
changeset 2 b9ab3b238396
child 5 844b047e260d
equal deleted inserted replaced
1:1050670c6980 2:b9ab3b238396
       
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of the License "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description: 
       
    15  *
       
    16  */
       
    17 
       
    18 package com.nokia.carbide.cpp.pi.address;
       
    19 
       
    20 import java.util.Arrays;
       
    21 import java.util.Comparator;
       
    22 import java.util.Enumeration;
       
    23 import java.util.Hashtable;
       
    24 import java.util.Vector;
       
    25 
       
    26 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
       
    27 import com.nokia.carbide.cpp.internal.pi.model.Function;
       
    28 import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
       
    29 import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTraceWithFunctions;
       
    30 import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
       
    31 import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
       
    32 import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
       
    33 import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
       
    34 import com.nokia.carbide.cpp.internal.pi.model.ProfiledThreshold;
       
    35 import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
       
    36 import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
       
    37 import com.nokia.carbide.cpp.pi.util.BinaryColorPalette;
       
    38 import com.nokia.carbide.cpp.pi.util.FunctionColorPalette;
       
    39 import com.nokia.carbide.cpp.pi.util.ThreadColorPalette;
       
    40 
       
    41 
       
    42 public class GppTrace extends GenericSampledTraceWithFunctions
       
    43 {
       
    44 	private static final long serialVersionUID = -658505849351283165L;
       
    45 	
       
    46 	// sample times start at a set interval, monotonically increase by that interval, and end at a
       
    47 	// time equal to (number of elements - 1) times the interval
       
    48 	private boolean complete;
       
    49 	
       
    50 	private transient GppSample[] sortedSamples = null;
       
    51 
       
    52 	// unchanging set of objects in the trace, ordered by total load
       
    53 	private transient Vector<ProfiledGeneric> sortedProfiledThreads;
       
    54 	private transient Vector<ProfiledGeneric> sortedProfiledBinaries;
       
    55 	private transient Vector<ProfiledGeneric> sortedProfiledFunctions;
       
    56 	
       
    57 	// unchanging set of objects in the trace, sorted by index
       
    58 	private transient Vector<ProfiledGeneric> profiledThreads;
       
    59 	private transient Vector<ProfiledGeneric> profiledBinaries;
       
    60 	private transient Vector<ProfiledGeneric> profiledFunctions;
       
    61 	
       
    62 	// selection time based objects in the trace
       
    63 	private transient int startSampleIndex;	// first sample in the selection
       
    64 	private transient int endSampleIndex;		// last sample in the selection
       
    65 
       
    66 	// sample counts for the currently selected area of the graph 
       
    67 	private transient int[] threadSamples;
       
    68 	private transient int[] binarySamples;
       
    69 	private transient int[] functionSamples;
       
    70 
       
    71 	private transient GppTraceGraph[] graphs;
       
    72 	
       
    73 	// tie palette to a trace instead of graph since trace is the data it represents
       
    74 	private transient ThreadColorPalette threadColorPalette = null;
       
    75 	private transient BinaryColorPalette binaryColorPalette = null;
       
    76 	private transient FunctionColorPalette functionColorPalette = null;
       
    77 	
       
    78 	//protected int uid;
       
    79 	
       
    80 	public GppTrace() 
       
    81 	{
       
    82 	}
       
    83 	
       
    84 	// for fast access, created a sorted array of samples
       
    85 	// this will remove duplicate times, find if times are missing, and
       
    86 	// find if times are increasing  
       
    87 	public void sortGppSamples()
       
    88 	{
       
    89 		// check if already sorted
       
    90 		if (this.sortedSamples != null)
       
    91 			return;
       
    92 		
       
    93 		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
       
    94 
       
    95 		complete = this.samples.size()*samplingInterval == this.getLastSampleNumber();
       
    96 		
       
    97 		this.sortedSamples = new GppSample[this.samples.size()];
       
    98 	
       
    99 		// fill the sorted array, assuming each sample time matches its (index+1)*samplingInterval
       
   100 		boolean sorted = true;
       
   101 		int arrayIndex = 0;
       
   102 		long lastTime = -1;
       
   103 		
       
   104 		for (int i = 0, sampleTime = 0; i < this.samples.size(); i++) {
       
   105 			Object o = this.samples.get(i);
       
   106 			if (o instanceof GppSample) {
       
   107 				  GppSample sample = (GppSample)o;
       
   108 
       
   109 				  // don't copy duplicates
       
   110 				  if (sample.sampleSynchTime == lastTime)
       
   111 					  continue;
       
   112 
       
   113 				  this.sortedSamples[arrayIndex++] = sample;
       
   114 				  sampleTime += samplingInterval;
       
   115 				  
       
   116 				  // make sure times are in increasing order
       
   117 				  if (sample.sampleSynchTime < lastTime)
       
   118 					  sorted = false;
       
   119 				  
       
   120 				  lastTime = sample.sampleSynchTime;
       
   121 				  
       
   122 				  if (sample.sampleSynchTime != sampleTime) {
       
   123 					  this.complete = false;
       
   124 					  
       
   125 					  // find the time it does match, in case one is missing
       
   126 					  while (sample.sampleSynchTime > sampleTime)
       
   127 						  sampleTime += samplingInterval;
       
   128 				  }
       
   129 			} else {
       
   130 				// error case
       
   131 				this.sortedSamples = new GppSample[1];
       
   132 				this.sortedSamples[0].sampleSynchTime = -1;
       
   133 				this.complete = false;
       
   134 				return;
       
   135 			}
       
   136 		}
       
   137 		
       
   138 		// if any duplicates, create a shorter array
       
   139 		if (arrayIndex != this.samples.size()) {
       
   140 			GppSample[] sampleObjects1 = new GppSample[this.samples.size()];
       
   141 			for (int i = 0; i < this.sortedSamples.length; i++)
       
   142 				sampleObjects1[i] = this.sortedSamples[i];
       
   143 			this.sortedSamples = sampleObjects1;
       
   144 		}
       
   145 		
       
   146 		if (!sorted) {
       
   147 			// now we have to actually sort
       
   148 			Arrays.sort(this.sortedSamples, new Comparator<Object>() {
       
   149 	
       
   150 				public int compare(Object arg0, Object arg1)
       
   151 				{
       
   152 					return (int) (((GppSample)arg0).sampleSynchTime - ((GppSample)arg1).sampleSynchTime);
       
   153 				}
       
   154 			});
       
   155 
       
   156 			// get rid of any duplicates and check for completeness
       
   157 			for (int i = 0, sampleTime = 0, length = this.sortedSamples.length; i < length; i++) {
       
   158 				GppSample sample = this.sortedSamples[i];
       
   159 
       
   160 				// don't copy duplicates
       
   161 				if (sample.sampleSynchTime == lastTime) {
       
   162 					for (int j = i; j < length - 1; j++) {
       
   163 						this.sortedSamples[j] = this.sortedSamples[j + 1];
       
   164 					}
       
   165 					length--;
       
   166 					this.complete = false;
       
   167 					continue;
       
   168 				}
       
   169 				
       
   170 				sampleTime += samplingInterval;
       
   171 				
       
   172 				if (sample.sampleSynchTime != sampleTime) {
       
   173 					  this.complete = false;
       
   174 						  
       
   175 					  // find the time it does match, in case one is missing
       
   176 					  while (sample.sampleSynchTime > sampleTime)
       
   177 						  sampleTime += samplingInterval;
       
   178 			    }
       
   179 			}
       
   180 		}
       
   181 	}
       
   182 	
       
   183 	public boolean isGppSampleComplete()
       
   184 	{
       
   185 		return this.complete;
       
   186 	}
       
   187 	
       
   188 	public GppSample[] getSortedGppSamples()
       
   189 	{
       
   190 		return this.sortedSamples;
       
   191 	}
       
   192 	
       
   193 	public GppSample getGppSample(int number)
       
   194 	{
       
   195 		return (GppSample)this.samples.elementAt(number);
       
   196 	}
       
   197 	
       
   198 	public GenericTraceGraph getTraceGraph(int graphIndex, int uid)
       
   199 	{	
       
   200 		return getGppGraph(graphIndex,uid);
       
   201 	}
       
   202 	
       
   203 	public GppTraceGraph getGppGraph(int graphIndex, int uid)
       
   204 	{
       
   205 		if (graphs == null) {
       
   206 			graphs = new GppTraceGraph[3];
       
   207 		}
       
   208 			
       
   209 		// note that graphIndex needs not match the index sent to GppTraceGraph
       
   210 		if (   (graphIndex == PIPageEditor.THREADS_PAGE)
       
   211 			|| (graphIndex == PIPageEditor.BINARIES_PAGE)
       
   212 			|| (graphIndex == PIPageEditor.FUNCTIONS_PAGE)) {
       
   213 			if (graphs[graphIndex] == null)
       
   214 				graphs[graphIndex] = new GppTraceGraph(graphIndex, this, uid);
       
   215 			return graphs[graphIndex];
       
   216 		}
       
   217 	
       
   218 		return null;
       
   219 	}
       
   220 	
       
   221 	public GenericTraceGraph getTraceGraph(int graphIndex)
       
   222 	{
       
   223 		int uid = NpiInstanceRepository.getInstance().activeUid();
       
   224 		return getTraceGraph(graphIndex, uid);
       
   225 	}
       
   226 	
       
   227 	public void refineTrace(FunctionResolver resolver)
       
   228 	{
       
   229 		super.refineTrace(resolver);
       
   230 	}
       
   231 
       
   232 	public int getSortedThreadsCount()
       
   233 	{
       
   234 		return this.sortedProfiledThreads.size();
       
   235 	}
       
   236 	
       
   237 	public Enumeration<ProfiledGeneric> getSortedThreadsElements()
       
   238 	{
       
   239 		return this.sortedProfiledThreads.elements();
       
   240 	}
       
   241 
       
   242 	public Vector<ProfiledGeneric> getSortedThreads()
       
   243 	{
       
   244 		if (this.sortedProfiledThreads == null)
       
   245 			this.sortedProfiledThreads = new Vector<ProfiledGeneric>();
       
   246 		return this.sortedProfiledThreads;
       
   247 	}
       
   248 
       
   249 	public Vector<ProfiledGeneric> getIndexedThreads()
       
   250 	{
       
   251 		if (this.profiledThreads == null)
       
   252 			this.profiledThreads = new Vector<ProfiledGeneric>();
       
   253 		return this.profiledThreads;
       
   254 	}
       
   255 
       
   256 	public int getSortedBinariesCount()
       
   257 	{
       
   258 	    return this.sortedProfiledBinaries.size();
       
   259 	}
       
   260 	
       
   261 	public Enumeration<ProfiledGeneric> getSortedBinariesElements()
       
   262 	{
       
   263 	    return this.sortedProfiledBinaries.elements();
       
   264 	}
       
   265 	
       
   266 	public Vector<ProfiledGeneric> getSortedBinaries()
       
   267 	{
       
   268 		if (this.sortedProfiledBinaries == null)
       
   269 			this.sortedProfiledBinaries = new Vector<ProfiledGeneric>();
       
   270 	    return this.sortedProfiledBinaries;
       
   271 	}
       
   272 
       
   273 	public Vector<ProfiledGeneric> getIndexedBinaries()
       
   274 	{
       
   275 		if (this.profiledBinaries == null)
       
   276 			this.profiledBinaries = new Vector<ProfiledGeneric>();
       
   277 	    return this.profiledBinaries;
       
   278 	}
       
   279 
       
   280 	public int getSortedFunctionsCount()
       
   281 	{
       
   282 	    return this.sortedProfiledFunctions.size();
       
   283 	}
       
   284 	
       
   285 	public Enumeration<ProfiledGeneric> getSortedFunctionsElements()
       
   286 	{
       
   287         return this.sortedProfiledFunctions.elements();
       
   288 	}
       
   289 	
       
   290 	public Vector<ProfiledGeneric> getSortedFunctions()
       
   291 	{
       
   292 		if (this.sortedProfiledFunctions == null)
       
   293 			this.sortedProfiledFunctions = new Vector<ProfiledGeneric>();
       
   294 		return this.sortedProfiledFunctions;
       
   295 	}
       
   296 	
       
   297 	public Vector<ProfiledGeneric> getIndexedFunctions()
       
   298 	{
       
   299 		if (this.profiledFunctions == null)
       
   300 			this.profiledFunctions = new Vector<ProfiledGeneric>();
       
   301 		return this.profiledFunctions;
       
   302 	}
       
   303 
       
   304 	/*
       
   305 	 *	Determine the threads, binaries, and functions associated with a time period
       
   306 	 *  from the start time up to and including the end time. If the times are equal,
       
   307 	 *  do not include any samples.
       
   308 	 */
       
   309 	public void setSelectedArea() {
       
   310 		// create empty arrays to hold sample counts
       
   311 		this.threadSamples   = new int[this.profiledThreads.size()];
       
   312 		this.binarySamples   = new int[this.profiledBinaries.size()];
       
   313 		this.functionSamples = new int[this.profiledFunctions.size()];
       
   314 
       
   315 		double doubleStartTime = PIPageEditor.currentPageEditor().getStartTime();
       
   316 		double doubleEndTime   = PIPageEditor.currentPageEditor().getEndTime();
       
   317 
       
   318 		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
       
   319 
       
   320 		GppSample[] sortedGppSamples = this.getSortedGppSamples();
       
   321 
       
   322 		// get the sample start time in integer multiples of milliseconds
       
   323 		startSampleIndex = ((int) ((doubleStartTime + 0.0005f)* 1000.0f))/samplingInterval;
       
   324 		if (startSampleIndex*samplingInterval < this.getFirstSampleNumber()) {
       
   325 			startSampleIndex = 0;
       
   326 		} else if (startSampleIndex > sortedGppSamples.length) {
       
   327 			startSampleIndex = sortedGppSamples.length - 1;
       
   328 		}
       
   329 			
       
   330 		// get the sample end time in integer multiples of milliseconds
       
   331 		// NOTE: endSampleIndex is one past the last allowed index, so that when no time
       
   332 		// is selected startSampleIndex will equal end sample index
       
   333 		endSampleIndex = ((int) ((doubleEndTime + 0.0005f) * 1000.0f))/samplingInterval;
       
   334 		if (endSampleIndex*samplingInterval < this.getFirstSampleNumber()) {
       
   335 			endSampleIndex = 0;
       
   336 		} else if (endSampleIndex > sortedGppSamples.length) {
       
   337 			endSampleIndex = sortedGppSamples.length - 1;
       
   338 		}
       
   339 
       
   340 		if (this.isGppSampleComplete()) {
       
   341 			// find the sample counts in each category
       
   342 			// just use the start and end times as indices
       
   343 			for (int i = startSampleIndex; i < endSampleIndex; i++) {
       
   344 				threadSamples[sortedGppSamples[i].threadIndex]++;
       
   345 				binarySamples[sortedGppSamples[i].binaryIndex]++;
       
   346 				functionSamples[sortedGppSamples[i].functionIndex]++;
       
   347 			}
       
   348 		} else {
       
   349 			// use a binary search to find the first sample
       
   350 			int startIndex = 0;
       
   351 			GppSample sample = null;
       
   352 			int lowerBound = 0;
       
   353 			int upperBound = sortedGppSamples.length;
       
   354 		    while (lowerBound <= upperBound) {
       
   355 		    	startIndex = (lowerBound + upperBound)/2;
       
   356 				sample = sortedGppSamples[startIndex];
       
   357 				if (startSampleIndex*samplingInterval == sample.sampleSynchTime) {
       
   358 		            break;
       
   359 				} else if (sample.sampleSynchTime > startSampleIndex*samplingInterval)
       
   360 		            upperBound = startIndex - 1;
       
   361 		        else
       
   362 		        	lowerBound = startIndex + 1;
       
   363 		    }
       
   364 		    
       
   365 		    // if there is no match, it's okay if the sample's time is larger than the
       
   366 		    // startTime, but not if the startTime is less
       
   367 		    if (sample.sampleSynchTime < startSampleIndex*samplingInterval)
       
   368 		    	startIndex++;
       
   369 	    	endSampleIndex = startIndex;
       
   370 		    
       
   371 			// find the sample counts in each category
       
   372 	    	// use comparisons to find the end sample
       
   373 		    if (startIndex < this.samples.size()) {
       
   374 				while (sample.sampleSynchTime < endSampleIndex*samplingInterval) {
       
   375 					threadSamples[sample.threadIndex]++;
       
   376 					binarySamples[sample.binaryIndex]++;
       
   377 					functionSamples[sample.functionIndex]++;
       
   378 	
       
   379 					endSampleIndex++;
       
   380 					if (endSampleIndex == sortedGppSamples.length)
       
   381 						break;
       
   382 	
       
   383 					sample = sortedGppSamples[endSampleIndex];
       
   384 				}
       
   385 				
       
   386 				if (   (endSampleIndex == this.samples.size())
       
   387 					|| (sample.sampleSynchTime > endSampleIndex*samplingInterval))
       
   388 					endSampleIndex--;
       
   389 		    }
       
   390 		    endSampleIndex++;
       
   391 		}
       
   392 		
       
   393 		// set the sample counts and loads for all the trace-related graphs
       
   394 		// set the % load strings only for a tab's base table
       
   395 		// To optimise this, we could just set the main sample count and load per graph (e.g., thread stuff for page 0)
       
   396 		// To ptimise this, we could check drawMode and ignore sample counts when tables don't show them
       
   397 		// requires sample counts, a
       
   398 		double percentPerSample;
       
   399 		if (startSampleIndex == endSampleIndex)
       
   400 			percentPerSample = 0.0;
       
   401 		else
       
   402 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   403 
       
   404 		// NOTE: For slightly better performance, might have other functions rely on this one zeroing out sample counts
       
   405 		for (int i = 0; i < this.profiledThreads.size(); i++) {
       
   406 			ProfiledGeneric pThread = this.profiledThreads.elementAt(i);
       
   407 			pThread.setSampleCount(PIPageEditor.THREADS_PAGE, this.threadSamples[i]);
       
   408 			pThread.setLoadAndString(PIPageEditor.THREADS_PAGE, (float)(this.threadSamples[i] * percentPerSample));
       
   409 		}
       
   410 
       
   411 		for (int i = 0; i < this.profiledBinaries.size(); i++) {
       
   412 			ProfiledGeneric pBinary = this.profiledBinaries.elementAt(i);
       
   413 			pBinary.setSampleCount(PIPageEditor.BINARIES_PAGE, this.binarySamples[i]);
       
   414 			pBinary.setLoadAndString(PIPageEditor.BINARIES_PAGE, (float)(this.binarySamples[i] * percentPerSample));
       
   415 		}
       
   416 
       
   417 		for (int i = 0; i < this.profiledFunctions.size(); i++) {
       
   418 			ProfiledGeneric pFunction = this.profiledFunctions.elementAt(i);
       
   419 			pFunction.setSampleCount(PIPageEditor.FUNCTIONS_PAGE, this.functionSamples[i]);
       
   420 			pFunction.setLoadAndString(PIPageEditor.FUNCTIONS_PAGE, (float)(this.functionSamples[i] * percentPerSample));
       
   421 		}		
       
   422 	}
       
   423 
       
   424 	/*
       
   425 	 * Based on a graph's set of enabled threads, produce a set of binaries, and
       
   426 	 * disable all other binaries for that graph
       
   427 	 */
       
   428 	public Vector<ProfiledGeneric> setThreadBinary(int graphIndex)
       
   429 	{
       
   430 		Vector<ProfiledGeneric>  graphBinaries = new Vector<ProfiledGeneric>();
       
   431 		Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
       
   432 		
       
   433 		// disable all binaries for the given graph
       
   434 		for (int i = 0; i < this.profiledBinaries.size(); i++) {
       
   435 			ProfiledGeneric pBinary = this.profiledBinaries.elementAt(i);
       
   436 			pBinary.setEnabled(graphIndex, false);
       
   437 		}
       
   438 
       
   439 		// set up in case we find binaries below the threshold
       
   440 		boolean lowBinary;
       
   441 		ProfiledThreshold thresholdBinary = this.graphs[graphIndex].getThresholdBinary();
       
   442 		thresholdBinary.init(graphIndex);
       
   443 
       
   444 		// for each binary in the selected sample range, if its thread is enabled, add the binary
       
   445 		int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
       
   446 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   447 			GppSample sample = this.sortedSamples[i];
       
   448 			ProfiledThread pThread = (ProfiledThread)
       
   449 							this.profiledThreads.elementAt(sample.threadIndex);
       
   450 
       
   451 			if (pThread.isEnabled(graphIndex)) {
       
   452 				ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
       
   453 				String binaryName = pBinary.getNameString();
       
   454 
       
   455 				lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
       
   456 
       
   457 				if (!foundBinaries.containsKey(binaryName)) {
       
   458 					pBinary.setEnabled(graphIndex, true);
       
   459 					foundBinaries.put(binaryName, binaryName);
       
   460 					if (lowBinary) {
       
   461 						thresholdBinary.addItem(graphIndex, pBinary, 1);
       
   462 					} else {
       
   463 						pBinary.setSampleCount(graphIndex, 1);
       
   464 						graphBinaries.add(pBinary);
       
   465 					}
       
   466 				} else {
       
   467 					if (lowBinary)
       
   468 						thresholdBinary.incSampleCount(graphIndex);
       
   469 					else
       
   470 						pBinary.incSampleCount(graphIndex);
       
   471 				}
       
   472 			}
       
   473 		}
       
   474 		
       
   475 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
   476 		double percentPerSample;
       
   477 		if (startSampleIndex == endSampleIndex)
       
   478 			percentPerSample = 0.0;
       
   479 		else
       
   480 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   481 
       
   482 		for (int i = 0; i < graphBinaries.size(); i++) {
       
   483 			ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
       
   484 			pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex) * percentPerSample));
       
   485 		}
       
   486 
       
   487 		return graphBinaries;
       
   488 	}
       
   489 
       
   490 	/*
       
   491 	 * Based on a graph's set of enabled threads and binaries, produce a set of functions, and
       
   492 	 * disable all other functions for that graph
       
   493 	 */
       
   494 	public Vector<ProfiledGeneric> setThreadBinaryFunction(int graphIndex)
       
   495 	{
       
   496 		Vector<ProfiledGeneric>  graphFunctions = new Vector<ProfiledGeneric>();
       
   497 		Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
       
   498 		
       
   499 		// disable all functions for the given graph
       
   500 		for (int i = 0; i < this.profiledFunctions.size(); i++) {
       
   501 			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(i);
       
   502 			pFunction.setEnabled(graphIndex, false);
       
   503 		}
       
   504 
       
   505 		// set up in case we find functions below the threshold
       
   506 		boolean lowFunction;
       
   507 		ProfiledThreshold thresholdFunction = this.graphs[graphIndex].getThresholdFunction();
       
   508 		thresholdFunction.init(graphIndex);
       
   509 
       
   510 		// for each function in the selected sample range, if its thread and binary are enabled,
       
   511 		// add the function
       
   512 		int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
       
   513 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   514 			GppSample sample = this.sortedSamples[i];
       
   515 			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
       
   516 			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
       
   517 
       
   518 			if (pThread.isEnabled(graphIndex) && pBinary.isEnabled(graphIndex)) {
       
   519 				ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
       
   520 				String functionName = pFunction.getNameString();
       
   521 
       
   522 				lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
       
   523 
       
   524 				if (!foundFunctions.containsKey(functionName)) {
       
   525 					pFunction.setEnabled(graphIndex, true);
       
   526 					foundFunctions.put(functionName, functionName);
       
   527 					if (lowFunction) {
       
   528 						thresholdFunction.addItem(graphIndex, pFunction, 1);
       
   529 					} else {
       
   530 						pFunction.setSampleCount(graphIndex, 1);
       
   531 						graphFunctions.add(pFunction);
       
   532 					}
       
   533 				} else {
       
   534 					if (lowFunction)
       
   535 						thresholdFunction.incSampleCount(graphIndex);
       
   536 					else
       
   537 						pFunction.incSampleCount(graphIndex);
       
   538 				}
       
   539 			}
       
   540 		}
       
   541 		
       
   542 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
   543 		double percentPerSample;
       
   544 		if (startSampleIndex == endSampleIndex)
       
   545 			percentPerSample = 0.0;
       
   546 		else
       
   547 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   548 
       
   549 		for (int i = 0; i < graphFunctions.size(); i++) {
       
   550 			ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
       
   551 			pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)* percentPerSample));
       
   552 		}		
       
   553 
       
   554 		return graphFunctions;
       
   555 	}
       
   556 
       
   557 	public Vector<ProfiledGeneric> setBinaryThreadFunction(int graphIndex)
       
   558 	{
       
   559 		return setThreadBinaryFunction(graphIndex);
       
   560 	}
       
   561 	
       
   562 	/*
       
   563 	 * Based on a graph's set of enabled threads, produce a set of functions, and
       
   564 	 * disable all other functions for that graph
       
   565 	 */
       
   566 	public Vector<ProfiledGeneric> setThreadFunction(int graphIndex)
       
   567 	{
       
   568 		Vector<ProfiledGeneric>  graphFunctions = new Vector<ProfiledGeneric>();
       
   569 		Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
       
   570 		
       
   571 		// disable all functions for the given graph
       
   572 		for (int i = 0; i < this.profiledFunctions.size(); i++) {
       
   573 			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(i);
       
   574 			pFunction.setEnabled(graphIndex, false);
       
   575 		}
       
   576 
       
   577 		// set up in case we find functions below the threshold
       
   578 		boolean lowFunction;
       
   579 		ProfiledThreshold thresholdFunction = this.graphs[graphIndex].getThresholdFunction();
       
   580 		thresholdFunction.init(graphIndex);
       
   581 
       
   582 		// for each function in the selected sample range, if its thread is enabled, add the function
       
   583 		int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
       
   584 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   585 			GppSample sample = this.sortedSamples[i];
       
   586 			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
       
   587 
       
   588 			if (pThread.isEnabled(graphIndex)) {
       
   589 				ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
       
   590 				String functionName = pFunction.getNameString();
       
   591 
       
   592 				lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
       
   593 
       
   594 				if (!foundFunctions.containsKey(functionName)) {
       
   595 					pFunction.setEnabled(graphIndex, true);
       
   596 					foundFunctions.put(functionName, functionName);
       
   597 					if (lowFunction) {
       
   598 						thresholdFunction.addItem(graphIndex, pFunction, 1);
       
   599 					} else {
       
   600 						pFunction.setSampleCount(graphIndex, 1);
       
   601 						graphFunctions.add(pFunction);
       
   602 					}
       
   603 				} else {
       
   604 					if (lowFunction)
       
   605 						thresholdFunction.incSampleCount(graphIndex);
       
   606 					else
       
   607 						pFunction.incSampleCount(graphIndex);
       
   608 				}
       
   609 			}
       
   610 		}
       
   611 		
       
   612 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
   613 		double percentPerSample;
       
   614 		if (startSampleIndex == endSampleIndex)
       
   615 			percentPerSample = 0.0;
       
   616 		else
       
   617 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   618 
       
   619 		for (int i = 0; i < graphFunctions.size(); i++) {
       
   620 			ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
       
   621 			pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex) * percentPerSample));
       
   622 		}		
       
   623 		
       
   624 		return graphFunctions;
       
   625 	}
       
   626 
       
   627 	/*
       
   628 	 * Based on a graph's set of enabled threads and functions, produce a set of binaries, and
       
   629 	 * disable all other binaries for that graph
       
   630 	 */
       
   631 	public Vector<ProfiledGeneric> setThreadFunctionBinary(int graphIndex)
       
   632 	{
       
   633 		Vector<ProfiledGeneric>  graphBinaries = new Vector<ProfiledGeneric>();
       
   634 		Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
       
   635 		
       
   636 		// disable all binaries for the given graph
       
   637 		for (int i = 0; i < this.profiledBinaries.size(); i++) {
       
   638 			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(i);
       
   639 			pBinary.setEnabled(graphIndex, false);
       
   640 		}
       
   641 
       
   642 		// set up in case we find binaries below the threshold
       
   643 		boolean lowBinary;
       
   644 		ProfiledThreshold thresholdBinary = this.graphs[graphIndex].getThresholdBinary();
       
   645 		thresholdBinary.init(graphIndex);
       
   646 
       
   647 		// for each binary in the selected sample range, if its thread and function are enabled,
       
   648 		// add the binary
       
   649 		int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
       
   650 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   651 			GppSample sample = this.sortedSamples[i];
       
   652 			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
       
   653 			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
       
   654 
       
   655 			if (pThread.isEnabled(graphIndex) && pFunction.isEnabled(graphIndex)) {
       
   656 				ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
       
   657 				String binaryName = pBinary.getNameString();
       
   658 
       
   659 				lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
       
   660 
       
   661 				if (!foundBinaries.containsKey(binaryName)) {
       
   662 					pBinary.setEnabled(graphIndex, true);
       
   663 					foundBinaries.put(binaryName, binaryName);
       
   664 					if (lowBinary) {
       
   665 						thresholdBinary.addItem(graphIndex, pBinary, 1);
       
   666 					} else {
       
   667 						pBinary.setSampleCount(graphIndex, 1);
       
   668 						graphBinaries.add(pBinary);
       
   669 					}
       
   670 				} else {
       
   671 					if (lowBinary)
       
   672 						thresholdBinary.incSampleCount(graphIndex);
       
   673 					else
       
   674 						pBinary.incSampleCount(graphIndex);
       
   675 				}
       
   676 			}
       
   677 		}
       
   678 		
       
   679 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
   680 		double percentPerSample;
       
   681 		if (startSampleIndex == endSampleIndex)
       
   682 			percentPerSample = 0.0;
       
   683 		else
       
   684 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   685 
       
   686 		for (int i = 0; i < graphBinaries.size(); i++) {
       
   687 			ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
       
   688 			pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex) * percentPerSample));
       
   689 		}
       
   690 		
       
   691 		return graphBinaries;
       
   692 	}
       
   693 
       
   694 	public Vector<ProfiledGeneric> setFunctionThreadBinary(int graphIndex)
       
   695 	{
       
   696 		return setThreadFunctionBinary(graphIndex);
       
   697 	}
       
   698 
       
   699 	/*
       
   700 	 * Based on a graph's set of enabled binaries, produce a set of threads, and
       
   701 	 * disable all other threads for that graph
       
   702 	 */
       
   703 	public Vector<ProfiledGeneric> setBinaryThread(int graphIndex)
       
   704 	{
       
   705 		Vector<ProfiledGeneric>  graphThreads = new Vector<ProfiledGeneric>();
       
   706 		Hashtable<String,String> foundThreads = new Hashtable<String,String>();
       
   707 		
       
   708 		// disable all threads for the given graph
       
   709 		for (int i = 0; i < this.profiledThreads.size(); i++) {
       
   710 			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(i);
       
   711 			pThread.setEnabled(graphIndex, false);
       
   712 		}
       
   713 
       
   714 		// set up in case we find threads below the threshold
       
   715 		boolean lowThread;
       
   716 		ProfiledThreshold thresholdThread = this.graphs[graphIndex].getThresholdThread();
       
   717 		thresholdThread.init(graphIndex);
       
   718 
       
   719 		// for each thread in the selected sample range, if its binary is enabled, add the thread
       
   720 		int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
       
   721 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   722 			GppSample sample = this.sortedSamples[i];
       
   723 			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
       
   724 
       
   725 			if (pBinary.isEnabled(graphIndex)) {
       
   726 				ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
       
   727 				String threadName = pThread.getNameString();
       
   728 
       
   729 				lowThread = pThread.getTotalSampleCount() < threadThreshold;
       
   730 
       
   731 				if (!foundThreads.containsKey(threadName)) {
       
   732 					pThread.setEnabled(graphIndex, true);
       
   733 					foundThreads.put(threadName, threadName);
       
   734 					if (lowThread) {
       
   735 						thresholdThread.addItem(graphIndex, pThread, 1);
       
   736 					} else {
       
   737 						pThread.setSampleCount(graphIndex, 1);
       
   738 						graphThreads.add(pThread);
       
   739 					}
       
   740 				} else {
       
   741 					if (lowThread)
       
   742 						thresholdThread.incSampleCount(graphIndex);
       
   743 					else
       
   744 						pThread.incSampleCount(graphIndex);
       
   745 				}
       
   746 			}
       
   747 		}
       
   748 		
       
   749 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
   750 		double percentPerSample;
       
   751 		if (startSampleIndex == endSampleIndex)
       
   752 			percentPerSample = 0.0;
       
   753 		else
       
   754 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   755 
       
   756 		for (int i = 0; i < graphThreads.size(); i++) {
       
   757 			ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
       
   758 			pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex) * percentPerSample));
       
   759 		}
       
   760 		
       
   761 		return graphThreads;
       
   762 	}
       
   763 
       
   764 	/*
       
   765 	 * Based on a graph's set of enabled functions, produce a set of threads, and
       
   766 	 * disable all other threads for that graph
       
   767 	 */
       
   768 	public Vector<ProfiledGeneric> setFunctionThread(int graphIndex)
       
   769 	{
       
   770 		Vector<ProfiledGeneric>  graphThreads = new Vector<ProfiledGeneric>();
       
   771 		Hashtable<String,String> foundThreads = new Hashtable<String,String>();
       
   772 		
       
   773 		// disable all threads for the given graph
       
   774 		for (int i = 0; i < this.profiledThreads.size(); i++) {
       
   775 			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(i);
       
   776 			pThread.setEnabled(graphIndex, false);
       
   777 		}
       
   778 
       
   779 		// set up in case we find threads below the threshold
       
   780 		boolean lowThread;
       
   781 		ProfiledThreshold thresholdThread = this.graphs[graphIndex].getThresholdThread();
       
   782 		thresholdThread.init(graphIndex);
       
   783 
       
   784 		// for each thread in the selected sample range, if its function is enabled, add the thread
       
   785 		int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
       
   786 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   787 			GppSample sample = this.sortedSamples[i];
       
   788 			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
       
   789 
       
   790 			if (pFunction.isEnabled(graphIndex)) {
       
   791 				ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
       
   792 				String threadName = pThread.getNameString();
       
   793 
       
   794 				lowThread = pThread.getTotalSampleCount() < threadThreshold;
       
   795 
       
   796 				if (!foundThreads.containsKey(threadName)) {
       
   797 					pThread.setEnabled(graphIndex, true);
       
   798 					foundThreads.put(threadName, threadName);
       
   799 					if (lowThread) {
       
   800 						thresholdThread.addItem(graphIndex, pThread, 1);
       
   801 					} else {
       
   802 						pThread.setSampleCount(graphIndex, 1);
       
   803 						graphThreads.add(pThread);
       
   804 					}
       
   805 				} else {
       
   806 					if (lowThread)
       
   807 						thresholdThread.incSampleCount(graphIndex);
       
   808 					else
       
   809 						pThread.incSampleCount(graphIndex);
       
   810 				}
       
   811 			}
       
   812 		}
       
   813 		
       
   814 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
   815 		double percentPerSample;
       
   816 		if (startSampleIndex == endSampleIndex)
       
   817 			percentPerSample = 0.0;
       
   818 		else
       
   819 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   820 
       
   821 		for (int i = 0; i < graphThreads.size(); i++) {
       
   822 			ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
       
   823 			pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex) * percentPerSample));
       
   824 		}
       
   825 		
       
   826 		return graphThreads;
       
   827 	}
       
   828 
       
   829 	/*
       
   830 	 * Based on a graph's set of enabled binaries and functions, produce a set of threads, and
       
   831 	 * disable all other threads for that graph
       
   832 	 */
       
   833 	public Vector<ProfiledGeneric> setBinaryFunctionThread(int graphIndex)
       
   834 	{
       
   835 		Vector<ProfiledGeneric>  graphThreads = new Vector<ProfiledGeneric>();
       
   836 		Hashtable<String,String> foundThreads = new Hashtable<String,String>();
       
   837 		
       
   838 		// disable all threads for the given graph
       
   839 		for (int i = 0; i < this.profiledThreads.size(); i++) {
       
   840 			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(i);
       
   841 			pThread.setEnabled(graphIndex, false);
       
   842 		}
       
   843 
       
   844 		// set up in case we find threads below the threshold
       
   845 		boolean lowThread;
       
   846 		ProfiledThreshold thresholdThread = this.graphs[graphIndex].getThresholdThread();
       
   847 		thresholdThread.init(graphIndex);
       
   848 
       
   849 		// for each thread in the selected sample range, if its binary and function are enabled,
       
   850 		// add the thread
       
   851 		int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
       
   852 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   853 			GppSample sample = this.sortedSamples[i];
       
   854 			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
       
   855 			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
       
   856 
       
   857 			if (pBinary.isEnabled(graphIndex)
       
   858 	 		    && (pFunction.isEnabled(graphIndex))) {
       
   859 				ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
       
   860 				String threadName = pThread.getNameString();
       
   861 
       
   862 				lowThread = pThread.getTotalSampleCount() < threadThreshold;
       
   863 
       
   864 				if (!foundThreads.containsKey(threadName)) {
       
   865 					pThread.setEnabled(graphIndex, true);
       
   866 					foundThreads.put(threadName, threadName);
       
   867 					if (lowThread) {
       
   868 						thresholdThread.addItem(graphIndex, pThread, 1);
       
   869 					} else {
       
   870 						pThread.setSampleCount(graphIndex, 1);
       
   871 						graphThreads.add(pThread);
       
   872 					}
       
   873 				} else {
       
   874 					if (lowThread)
       
   875 						thresholdThread.incSampleCount(graphIndex);
       
   876 					else
       
   877 						pThread.incSampleCount(graphIndex);
       
   878 				}
       
   879 			}
       
   880 		}
       
   881 		
       
   882 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
   883 		double percentPerSample;
       
   884 		if (startSampleIndex == endSampleIndex)
       
   885 			percentPerSample = 0.0;
       
   886 		else
       
   887 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   888 
       
   889 		for (int i = 0; i < graphThreads.size(); i++) {
       
   890 			ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
       
   891 			pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex) * percentPerSample));
       
   892 		}
       
   893 		
       
   894 		return graphThreads;
       
   895 	}
       
   896 
       
   897 	public Vector<ProfiledGeneric> setFunctionBinaryThread(int graphIndex)
       
   898 	{
       
   899 		return setBinaryFunctionThread(graphIndex);
       
   900 	}
       
   901 
       
   902 	/*
       
   903 	 * Based on a graph's set of enabled functions, produce a set of binaries, and
       
   904 	 * disable all other binaries for that graph
       
   905 	 */
       
   906 	public Vector<ProfiledGeneric> setFunctionBinary(int graphIndex)
       
   907 	{
       
   908 		Vector<ProfiledGeneric>  graphBinaries = new Vector<ProfiledGeneric>();
       
   909 		Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
       
   910 		
       
   911 		// disable all binaries for the given graph
       
   912 		for (int i = 0; i < this.profiledBinaries.size(); i++) {
       
   913 			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(i);
       
   914 			pBinary.setEnabled(graphIndex, false);
       
   915 		}
       
   916 
       
   917 		// set up in case we find binaries below the threshold
       
   918 		boolean lowBinary;
       
   919 		ProfiledThreshold thresholdBinary = this.graphs[graphIndex].getThresholdBinary();
       
   920 		thresholdBinary.init(graphIndex);
       
   921 
       
   922 		// for each binary in the selected sample range, if its function is enabled, add the binary
       
   923 		int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
       
   924 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   925 			GppSample sample = this.sortedSamples[i];
       
   926 			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
       
   927 
       
   928 			if (pFunction.isEnabled(graphIndex)) {
       
   929 				ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
       
   930 				String binaryName = pBinary.getNameString();
       
   931 
       
   932 				lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
       
   933 
       
   934 				if (!foundBinaries.containsKey(binaryName)) {
       
   935 					pBinary.setEnabled(graphIndex, true);
       
   936 					foundBinaries.put(binaryName, binaryName);
       
   937 					if (lowBinary) {
       
   938 						thresholdBinary.addItem(graphIndex, pBinary, 1);
       
   939 					} else {
       
   940 						pBinary.setSampleCount(graphIndex, 1);
       
   941 						graphBinaries.add(pBinary);
       
   942 					}
       
   943 				} else {
       
   944 					if (lowBinary)
       
   945 						thresholdBinary.incSampleCount(graphIndex);
       
   946 					else
       
   947 						pBinary.incSampleCount(graphIndex);
       
   948 				}
       
   949 			}
       
   950 		}
       
   951 		
       
   952 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
   953 		double percentPerSample;
       
   954 		if (startSampleIndex == endSampleIndex)
       
   955 			percentPerSample = 0.0;
       
   956 		else
       
   957 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
   958 
       
   959 		for (int i = 0; i < graphBinaries.size(); i++) {
       
   960 			ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
       
   961 			pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex) * percentPerSample));
       
   962 		}
       
   963 		
       
   964 		return graphBinaries;
       
   965 	}
       
   966 
       
   967 	/*
       
   968 	 * Based on a graph's set of enabled binaries, produce a set of functions, and
       
   969 	 * disable all other functions for that graph
       
   970 	 */
       
   971 	public Vector<ProfiledGeneric> setBinaryFunction(int graphIndex)
       
   972 	{
       
   973 		Vector<ProfiledGeneric>  graphFunctions = new Vector<ProfiledGeneric>();
       
   974 		Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
       
   975 		
       
   976 		// disable all functions for the given graph
       
   977 		for (int i = 0; i < this.profiledFunctions.size(); i++) {
       
   978 			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(i);
       
   979 			pFunction.setEnabled(graphIndex, false);
       
   980 		}
       
   981 
       
   982 		// set up in case we find functions below the threshold
       
   983 		boolean lowFunction;
       
   984 		ProfiledThreshold thresholdFunction = this.graphs[graphIndex].getThresholdFunction();
       
   985 		thresholdFunction.init(graphIndex);
       
   986 
       
   987 		// for each function in the selected sample range, if its binary is enabled, add the function
       
   988 		int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
       
   989 		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
       
   990 			GppSample sample = this.sortedSamples[i];
       
   991 			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
       
   992 
       
   993 			if (pBinary.isEnabled(graphIndex)) {
       
   994 				ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
       
   995 				String functionName = pFunction.getNameString();
       
   996 
       
   997 				lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
       
   998 
       
   999 				if (!foundFunctions.containsKey(functionName)) {
       
  1000 					pFunction.setEnabled(graphIndex, true);
       
  1001 					foundFunctions.put(functionName, functionName);
       
  1002 					if (lowFunction) {
       
  1003 						thresholdFunction.addItem(graphIndex, pFunction, 1);
       
  1004 					} else {
       
  1005 						pFunction.setSampleCount(graphIndex, 1);
       
  1006 						graphFunctions.add(pFunction);
       
  1007 					}
       
  1008 				} else {
       
  1009 					if (lowFunction)
       
  1010 						thresholdFunction.incSampleCount(graphIndex);
       
  1011 					else
       
  1012 						pFunction.incSampleCount(graphIndex);
       
  1013 				}
       
  1014 			}
       
  1015 		}
       
  1016 		
       
  1017 		// since we are not converting float % load to string % load inside the table viewers, do it here
       
  1018 		double percentPerSample;
       
  1019 		if (startSampleIndex == endSampleIndex)
       
  1020 			percentPerSample = 0.0;
       
  1021 		else
       
  1022 			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
       
  1023 
       
  1024 		for (int i = 0; i < graphFunctions.size(); i++) {
       
  1025 			ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
       
  1026 			pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex) * percentPerSample));
       
  1027 		}		
       
  1028 		
       
  1029 		return graphFunctions;
       
  1030 	}
       
  1031 	
       
  1032 	public int getStartSampleIndex()
       
  1033 	{
       
  1034 		return this.startSampleIndex;
       
  1035 	}
       
  1036 	
       
  1037 	public int getEndSampleIndex()
       
  1038 	{
       
  1039 		return this.endSampleIndex;
       
  1040 	}
       
  1041 	
       
  1042 	public int[] getThreadSampleCounts()
       
  1043 	{
       
  1044 		return this.threadSamples;
       
  1045 	}
       
  1046 	
       
  1047 	public int[] getBinarySampleCounts()
       
  1048 	{
       
  1049 		return this.binarySamples;
       
  1050 	}
       
  1051 	
       
  1052 	public int[] getFunctionSampleCounts()
       
  1053 	{
       
  1054 		return this.functionSamples;
       
  1055 	}
       
  1056 
       
  1057 	public void setThreadSampleCounts(int[] sampleCounts)
       
  1058 	{
       
  1059 		this.threadSamples = sampleCounts;
       
  1060 	}
       
  1061 	
       
  1062 	public void setBinarySampleCounts(int[] sampleCounts)
       
  1063 	{
       
  1064 		this.binarySamples = sampleCounts;
       
  1065 	}
       
  1066 	
       
  1067 	public void setFunctionSampleCounts(int[] sampleCounts)
       
  1068 	{
       
  1069 		this.functionSamples = sampleCounts;
       
  1070 	}
       
  1071 	
       
  1072 	public void setThreadColorPalette(ThreadColorPalette tableColorPalette) {
       
  1073 		this.threadColorPalette = tableColorPalette;
       
  1074 	}
       
  1075 
       
  1076 	public ThreadColorPalette getThreadColorPalette() {
       
  1077 		if (this.threadColorPalette == null) {
       
  1078 			this.threadColorPalette = new ThreadColorPalette();
       
  1079 		}
       
  1080 		return this.threadColorPalette;
       
  1081 	}
       
  1082 
       
  1083 	public void setBinaryColorPalette(BinaryColorPalette tableColorPalette) {
       
  1084 		this.binaryColorPalette = tableColorPalette;
       
  1085 	}
       
  1086 
       
  1087 	public BinaryColorPalette getBinaryColorPalette() {
       
  1088 		if (this.binaryColorPalette == null) {
       
  1089 			this.binaryColorPalette = new BinaryColorPalette();
       
  1090 		}
       
  1091 		return this.binaryColorPalette;
       
  1092 	}
       
  1093 
       
  1094 	public void setFunctionColorPalette(FunctionColorPalette tableColorPalette) {
       
  1095 		this.functionColorPalette = tableColorPalette;
       
  1096 	}
       
  1097 
       
  1098 	public FunctionColorPalette getFunctionColorPalette() {
       
  1099 		if (this.functionColorPalette == null) {
       
  1100 			this.functionColorPalette = new FunctionColorPalette();
       
  1101 		}
       
  1102 		return this.functionColorPalette;
       
  1103 	}
       
  1104 
       
  1105 	@Override
       
  1106 	public void finalizeTrace() {
       
  1107 		samples.trimToSize();
       
  1108 		for (int i = 0; i < samples.size(); i++) {
       
  1109 			GppSample sample = (GppSample) samples.get(i);
       
  1110 			
       
  1111 			if (sample.currentFunctionItt == null && sample.currentFunctionSym == null) {
       
  1112 				sample.currentFunctionItt = new Function(Messages.getString("GppTrace.functionNotFound1") + Long.toHexString(sample.programCounter) + Messages.getString("GppTrace.functionNotFound2"), //$NON-NLS-1$ //$NON-NLS-2$
       
  1113 						new Long(sample.programCounter),
       
  1114 						Messages.getString("GppTrace.binaryNotFound1") +  Long.toHexString(sample.programCounter) + Messages.getString("GppTrace.binarynotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
       
  1115 			}
       
  1116 		}
       
  1117 	}
       
  1118 }