sysperfana/memspyext/com.nokia.s60tools.swmtanalyser/src/com/nokia/s60tools/swmtanalyser/ui/graphs/ChunksGraph.java
/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.s60tools.swmtanalyser.ui.graphs;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Polyline;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Transform;
import org.eclipse.swt.widgets.Display;
import com.nokia.s60tools.swmtanalyser.data.ChunksData;
import com.nokia.s60tools.swmtanalyser.data.CycleData;
import com.nokia.s60tools.swmtanalyser.data.GlobalDataChunks;
import com.nokia.s60tools.swmtanalyser.model.SWMTLogReaderUtils;
import com.nokia.s60tools.util.debug.DbgUtility;
/**
* This class contains all needed logic to paint data related to Global and Non-Heap chunks.
*
*/
public class ChunksGraph extends GenericGraph {
private HashMap<String, ArrayList<GlobalDataChunks>> chunksData = new HashMap<String, ArrayList<GlobalDataChunks>>();
private HashMap<String, ArrayList<ChunksData>> nonHeapChunksData = new HashMap<String, ArrayList<ChunksData>>();
private HashMap<String, Polyline> pointsData = new HashMap<String, Polyline>();
private double visY;
private double multiplier;
/* (non-Javadoc)
* @see com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph#paint(org.eclipse.draw2d.Graphics)
*/
public void paint(Graphics graphics) {
DbgUtility.println(DbgUtility.PRIORITY_OPERATION, this.getClass().getSimpleName() + "/paint START");
ArrayList<String> chunksList = this.getUserSelectedItems();
if(chunksList == null)
return;
// Storing original settings before graphs are painted with case-specific settings
int origLineWidth = graphics.getLineWidth();
Color origColor = graphics.getForegroundColor();
int origLineStyle = graphics.getLineStyle();
// Setting graph drawing specific settings
graphics.setLineWidth(CommonGraphConstants.DEFAULT_GRAPH_LINE_WIDTH);
graphics.setLineStyle(SWT.LINE_SOLID);
int [] listX = this.calculateTimeIntervals();
this.lastSampleTime = listX[listX.length-1];
int k=0;
for(String chnk: chunksList)
{
if(this.getEvent().equals(GenericGraph.EventTypes.GLOBAL_DATA_SIZE))
valuesToBePlotted = getGlobalChnkSizeData(chnk);
else if(this.getEvent().equals(GenericGraph.EventTypes.NON_HEAP_CHUNK_SIZE))
valuesToBePlotted = getNonHeapChnkSizeData(chnk);
int [] points = new int[valuesToBePlotted.length *2];
double visY = visualSizeY - CommonGraphConstants.XLEGENDSPACE;
boolean handleDeleted = false;
List<List<Integer>> ListOfSolidLinePoints = new ArrayList<List<Integer>>();
ArrayList<Integer> solidLinePoints = new ArrayList<Integer>();
for (int i = 0, j = 0; i < valuesToBePlotted.length; i++, j++)
{
if (valuesToBePlotted[i] <= 0){
// Not showing zero values to a user, not meaningful data
DbgUtility.println(DbgUtility.PRIORITY_LOOP, "continued because value <= 0");
continue;
}
int x_point = (int)(listX[i]/getScale());
int y_point =(int) (visY - valuesToBePlotted[i] /multiplier);
points[j] = x_point;
points[++j] = y_point;
if(!handleDeleted){
if(y_point > 0){
solidLinePoints.add(x_point);
solidLinePoints.add(y_point);
DbgUtility.println(DbgUtility.PRIORITY_LOOP, "add 1: x_point: " + x_point + ", y_point: " + y_point);
}
else{
DbgUtility.println(DbgUtility.PRIORITY_LOOP, "skipped because zero value");
}
}
boolean handleStatus = getHandleStatus(i+1, chnk);
if(handleStatus && !handleDeleted){
handleDeleted = true;
if(solidLinePoints.size() > 0)
ListOfSolidLinePoints.add(solidLinePoints);
solidLinePoints = new ArrayList<Integer>();
}
if(handleDeleted && getChunkStatus(i+1, chnk)== CycleData.New )
{
handleDeleted = false;
if(y_point > 0){
// Graphing only positive values
solidLinePoints.add(x_point);
solidLinePoints.add(y_point);
DbgUtility.println(DbgUtility.PRIORITY_LOOP, "add 2:x_point: " + x_point + ", y_point: " + y_point);
}
else{
DbgUtility.println(DbgUtility.PRIORITY_LOOP, "skipped because zero value");
}
}
points[i] = x_point;
points[i+1] = y_point;
}
if(solidLinePoints.size() > 0)
ListOfSolidLinePoints.add(solidLinePoints);
graphics.setForegroundColor(this.getColors().get(k));
graphics.setLineWidth(2);
for(int i=0; i < ListOfSolidLinePoints.size(); i++)
{
int [] solidPts = GraphsUtils.CreateIntArrayFromIntegerList(ListOfSolidLinePoints.get(i));
if(solidPts != null)
{
if(ListOfSolidLinePoints.size() > 1)
{
int instance_id = i+1;
graphics.drawString("(0" + instance_id + ")", solidPts[0]+2, solidPts[1] - 15);
}
graphics.setLineStyle(SWT.LINE_SOLID);
graphics.drawPolyline(solidPts);
// Drawing markers to the data points
GraphsUtils.drawMarkers(graphics, solidPts);
}
}
Polyline line = new Polyline();
line.setPoints(new PointList(points));
pointsData.put(chnk, line);
k++;
}
// Restoring original settings before paint call
graphics.setLineStyle(origLineStyle);
graphics.setForegroundColor(origColor);
graphics.setLineWidth(origLineWidth);
DbgUtility.println(DbgUtility.PRIORITY_OPERATION, this.getClass().getSimpleName() + "/paint END");
}
/* (non-Javadoc)
* @see com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph#paintYAxis(org.eclipse.swt.graphics.GC)
*/
public void paintYAxis(GC gc) {
visY = visualSizeY - CommonGraphConstants.XLEGENDSPACE;
multiplier = GraphsUtils.prettyMaxBytes(maxBytes) / visY;
double yIncrement = visY / 10;
int previousBottom = 0;
for (int k = 10; k >= 0; k--)
{
// location for the value indicator is k * 1/10 the height of the display
int y = (int) (visY - (yIncrement * k));
int bytes = (int)(yIncrement * multiplier) * k;
String legend = "";
if (maxBytes < 10000)
{
legend += bytes + " B"; //$NON-NLS-1$
}
else if (maxBytes <= 500 * 1024)
{
legend += (bytes / 1024) + " KB"; //$NON-NLS-1$
}
else
{
legend += MBformat.format(((float) bytes / (1024 * 1024))) + " MB"; //$NON-NLS-1$
}
Point extent = gc.stringExtent(legend);
gc.drawLine(CommonGraphConstants.YLEGENDSPACE - 3, (int)y + 1, CommonGraphConstants.YLEGENDSPACE, (int)y + 1);
if (y >= previousBottom)
{
gc.drawString(legend, CommonGraphConstants.YLEGENDSPACE - extent.x -2, (int)y);
previousBottom = (int)y + extent.y;
}
}
final Image image = this.getVerticalLabel("Bytes");
gc.setAdvanced(true);
final org.eclipse.swt.graphics.Rectangle rect2 = image.getBounds();
Transform transform = new Transform(Display.getDefault());
transform.translate(rect2.height / 2f, rect2.width / 2f);
transform.rotate(-90);
transform.translate(-rect2.width / 2f, -rect2.height / 2f);
gc.setTransform(transform);
gc.drawImage(image, -(int)visY/3, 1);
transform.dispose();
gc.dispose();
}
private void fetchEntireDataForSelectedChunks()
{
ArrayList<String> selectedChunks = this.getUserSelectedItems();
SWMTLogReaderUtils utils = new SWMTLogReaderUtils();
if(this.getEvent().equals(GenericGraph.EventTypes.GLOBAL_DATA_SIZE))
{
for(String chunk:selectedChunks)
{
ArrayList<GlobalDataChunks> chnkData = utils.getGLOBDataFromAllCycles(chunk, this.getCyclesData());
chunksData.put(chunk, chnkData);
}
}
else if(this.getEvent().equals(GenericGraph.EventTypes.NON_HEAP_CHUNK_SIZE))
{
for(String chunk:selectedChunks)
{
ArrayList<ChunksData> chnkData = utils.getChunkDataFromAllCycles(chunk, this.getCyclesData());
nonHeapChunksData.put(chunk, chnkData);
}
}
}
/* (non-Javadoc)
* @see com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph#prepareData()
*/
public void prepareData() {
fetchEntireDataForSelectedChunks();
for(String chnk:getUserSelectedItems())
{
int [] valuesToBePlotted = null;
switch(this.getEvent())
{
case GLOBAL_DATA_SIZE:
valuesToBePlotted = getGlobalChnkSizeData(chnk);
break;
case NON_HEAP_CHUNK_SIZE:
valuesToBePlotted = getNonHeapChnkSizeData(chnk);
break;
}
if(valuesToBePlotted == null)
continue;
int maxValue = calculateMaxValue(valuesToBePlotted);
if(maxValue > maxBytes)
maxBytes = maxValue;
}
}
private boolean getHandleStatus(int cycleNo, String chunkName)
{
boolean status = false;
if(this.getEvent().equals(GenericGraph.EventTypes.GLOBAL_DATA_SIZE))
{
ArrayList<GlobalDataChunks> glod_data = chunksData.get(chunkName);
status = glod_data.get(cycleNo -1).isKernelHandleDeleted();
}
else if(this.getEvent().equals(GenericGraph.EventTypes.NON_HEAP_CHUNK_SIZE))
{
ArrayList<ChunksData> chunks_data = nonHeapChunksData.get(chunkName);
status = chunks_data.get(cycleNo -1).isKernelHandleDeleted();
}
return status;
}
private int getChunkStatus(int cycleNo, String chunkName)
{
int status = 0;
if(this.getEvent().equals(GenericGraph.EventTypes.GLOBAL_DATA_SIZE))
{
ArrayList<GlobalDataChunks> glod_data = chunksData.get(chunkName);
status = glod_data.get(cycleNo -1).getAttrib();
}
else if(this.getEvent().equals(GenericGraph.EventTypes.NON_HEAP_CHUNK_SIZE))
{
ArrayList<ChunksData> chunks_data = nonHeapChunksData.get(chunkName);
status = chunks_data.get(cycleNo -1).getAttrib();
}
return status;
}
private int [] getGlobalChnkSizeData(String chnkName)
{
ArrayList<GlobalDataChunks> data = chunksData.get(chnkName);
int [] values = new int[data.size()];
for(int i=0; i<data.size(); i++)
{
if(data.get(i).getAttrib() == CycleData.Deleted)
values[i] = 0;
else
values [i] = (int)data.get(i).getSize();
}
return values;
}
private int [] getNonHeapChnkSizeData(String chnkName)
{
ArrayList<ChunksData> data = nonHeapChunksData.get(chnkName);
int [] values = new int[data.size()];
for(int i=0; i<data.size(); i++)
{
if(data.get(i).getAttrib() == CycleData.Deleted)
values[i] = 0;
else
values [i] = (int)data.get(i).getSize();
}
return values;
}
/* (non-Javadoc)
* @see com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph#getToolTipText(int, int)
*/
public String getToolTipText(int x, int y)
{
if(y > (int)visY)
return null;
String text = "";
double xValue = x + timeOffset;
int scaledX = (int)(xValue * getScale());
double valY = visY - y;
double bytes = valY * multiplier;
String scaledY = "";
if (bytes < 10000)
{
scaledY += Bytes_Format.format(bytes) + " B"; //$NON-NLS-1$
}
else if (bytes <= 500 * 1024)
{
scaledY += Bytes_Format.format(bytes / 1024) + " KB"; //$NON-NLS-1$
}
else
{
scaledY += MBformat.format(((float) bytes / (1024 * 1024))) + " MB"; //$NON-NLS-1$
}
text += scaledX + " s, " + scaledY;
for(String chnk: getUserSelectedItems())
{
Polyline line = pointsData.get(chnk);
if(line != null && line.containsPoint(x, y))
text += "\n" + chnk;
}
return text;
}
/**
* Get {@link GlobalDataChunks} for given chunk name
* @param chnkName
* @return List of chunks with given name
*/
public ArrayList<GlobalDataChunks> getGlobalChunkData(String chnkName)
{
return chunksData.get(chnkName);
}
/**
* Get {@link ChunksData} for given chunk name
* @param chnkName
* @return List of data with given name
*/
public ArrayList<ChunksData> getNonHeapChunkData(String chnkName)
{
return nonHeapChunksData.get(chnkName);
}
}