sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/engine/statistic/ProcessInfo.java
author Matti Laitinen <matti.t.laitinen@nokia.com>
Tue, 24 Aug 2010 12:16:27 +0300
changeset 15 0367d2db2c06
parent 6 f65f740e69f9
permissions -rw-r--r--
AnalyzeTool Carbide extension 1.10.0

/*
 * Copyright (c) 2008-2010 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:  Definitions for the class ProcessInfo
 *
 */

package com.nokia.s60tools.analyzetool.engine.statistic;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IStatus;

import com.nokia.s60tools.analyzetool.Activator;

/**
 * Contains information of process
 * 
 * @author kihe
 * 
 */
public class ProcessInfo {

	/** List of allocations and frees sorted as they arrive in time */
	private AbstractList<BaseInfo> allocsFrees;

	/** List of DLL loads */
	private List<DllLoad> dllLoads;

	/** Process id */
	private int processID;

	/** Process Name */
	private String processName;

	/** Log time */
	private long logTime;

	/** Process start time */
	private Long startTime;

	/** Process end time */
	private Long endTime;

	/** Trace data format version number */
	private int traceDataVersion = 0;

	/** Active allocations account */
	private int allocCount = 0;

	/** Total memory consumed by this process at each event */
	private int totalMemory = 0;

	/** Highest memory consumed by this process */
	private int highestMemory = 0;

	/** Map of potential leaks; to track allocations not yet freed */
	private Map<Long, List<AllocInfo>> potentialLeaksMap;

	/**
	 * Constructor
	 */
	public ProcessInfo() {
		dllLoads = new ArrayList<DllLoad>();
		allocsFrees = new ArrayList<BaseInfo>();
		allocCount = 0;
		potentialLeaksMap = new HashMap<Long, List<AllocInfo>>();
	}

	/**
	 * Adds one memory allocation to the list.
	 * 
	 * @param oneInfo
	 *            One memory allocation
	 */
	public void addOneAlloc(AllocInfo oneInfo) {
		allocCount++;
		totalMemory = totalMemory + oneInfo.getSizeInt();
		oneInfo.setTotalMem(totalMemory);
		if (totalMemory > highestMemory) {
			highestMemory = totalMemory;
		}
		allocsFrees.add(oneInfo);
		// add this alloc to the potential leaks map
		Long addr = oneInfo.getMemoryAddress();
		List<AllocInfo> allocsSameAddr = potentialLeaksMap.get(addr);
		if (allocsSameAddr == null) {
			allocsSameAddr = new ArrayList<AllocInfo>();
			potentialLeaksMap.put(addr, allocsSameAddr);
		}
		allocsSameAddr.add(oneInfo);
	}

	/**
	 * Adds one DLL load to the list.
	 * 
	 * @param dllLoad
	 *            One DLL load
	 */
	public void addOneDllLoad(DllLoad dllLoad) {
		// make sure there is no DLL with the same details already loaded
		for (DllLoad dll : dllLoads) {
			if (dll.getName().equalsIgnoreCase(dllLoad.getName())
					&& dll.getProcessID() == dllLoad.getProcessID()
					&& dll.getUnloadTime() > dllLoad.getLoadTime()) {
				return;
			}
		}

		dllLoads.add(dllLoad);
	}

	/**
	 * Updates memory leaks list by given free information
	 * 
	 * @param info
	 *            Which memory allocation to be deallocated.
	 */
	public void free(FreeInfo info) {

		int freeSize = 0;

		// remove allocs with the same address from the potential leaks map
		Long freeAddr = info.getMemoryAddress();
		List<AllocInfo> allocsSameAddr = potentialLeaksMap.remove(freeAddr);
		if (allocsSameAddr != null && allocsSameAddr.size() > 0) {
			for (AllocInfo allocInfo : allocsSameAddr) {
				allocInfo.setFreedBy(info);
				allocCount--;
				int thisFreedSize = allocInfo.getSizeInt();
				freeSize = freeSize + thisFreedSize;
				totalMemory = totalMemory - thisFreedSize;
			}
			info.setFreedAllocs(new HashSet<AllocInfo>(allocsSameAddr));
		}

		info.setSizeInt(freeSize);
		info.setTotalMem(totalMemory);

		if (info.getTime() == 0) {
			// support old format
			// set time as last operation time or start time.
			Long time = getPreviousTime();
			if (time == null || time == -1L) {
				Activator
						.getDefault()
						.log(
								IStatus.WARNING,
								String
										.format(
												"AnalyzeTool encountered a process = %s, which starts with FREE.",
												processID), null);
				time = startTime == null ? 0 : startTime;
			}
			info.setTime(time);
		}
		allocsFrees.add(info);
	}

	/**
	 * Returns the time stamp of the last memory operation
	 * 
	 * @return the time stamp of the last memory operation, or -1 if there are
	 *         no memory operations
	 */
	private Long getPreviousTime() {
		Long time = -1L;
		if (!allocsFrees.isEmpty()) {
			time = (allocsFrees.get(allocsFrees.size() - 1)).getTime();
		}
		return time;
	}

	/**
	 * Returns list of allocations
	 * 
	 * @return List of allocations
	 */
	public AbstractList<AllocInfo> getAllocs() {
		AbstractList<AllocInfo> allocs = new ArrayList<AllocInfo>();
		for (BaseInfo alloc : allocsFrees) {
			if (alloc instanceof AllocInfo) {
				allocs.add((AllocInfo) alloc);
			}
		}
		return allocs;
	}

	/**
	 * Returns list of DLL loads
	 * 
	 * @return List of DLL loads
	 */
	public List<DllLoad> getDllLoads() {
		return dllLoads;
	}

	/**
	 * Returns list of memory leak from this process.
	 * 
	 * @return List of memory leaks.
	 */
	public AbstractList<AllocInfo> getMemLeaks() {
		AbstractList<AllocInfo> leaks = new ArrayList<AllocInfo>();
		for (List<AllocInfo> potLeaks : potentialLeaksMap.values()) {
			leaks.addAll(potLeaks);
		}
		return leaks;
	}

	/**
	 * Returns the number of memory leaks of this process.
	 * 
	 * @return number of memory leaks.
	 */
	public int getMemLeaksNumber() {
		int count = 0;
		for (List<AllocInfo> potLeaks : potentialLeaksMap.values()) {
			count += potLeaks.size();
		}
		return count;
	}

	/**
	 * get list of frees
	 * 
	 * @return List of FreeInfo
	 */
	public AbstractList<FreeInfo> getFrees() {
		AbstractList<FreeInfo> frees = new ArrayList<FreeInfo>();
		for (BaseInfo alloc : allocsFrees) {
			if (alloc instanceof FreeInfo) {
				frees.add((FreeInfo) alloc);
			}
		}
		return frees;
	}

	/**
	 * Returns process id
	 * 
	 * @return Process id
	 */
	public int getProcessID() {
		return processID;
	}

	/**
	 * Returns process start time
	 * 
	 * @return Process start time
	 */
	public Long getStartTime() {
		return startTime;
	}

	/**
	 * Returns trace data version number
	 * 
	 * @return Trace data version number
	 */
	public int getTraceDataVersion() {
		return traceDataVersion;
	}

	/**
	 * Sets process id
	 * 
	 * @param newProcessID
	 *            Process id
	 */
	public void setProcessID(int newProcessID) {
		this.processID = newProcessID;
	}

	/**
	 * Sets process start time
	 * 
	 * @param newTime
	 *            process start time
	 */
	public void setStartTime(String newTime) {
		long lValue = Long.parseLong(newTime, 16);
		this.startTime = lValue;
	}

	/**
	 * Sets log time
	 * 
	 * @param logTime
	 *            log time of one trace message in microseconds
	 */
	public void setLogTime(long logTime) {
		this.logTime = logTime;
	}

	/**
	 * Gets log time
	 * 
	 * @return log time of one trace message in microseconds
	 */
	public long getLogTime() {
		return logTime;
	}

	/**
	 * Updates trace version number
	 * 
	 * @param newTraceDataVersion
	 *            New trace data version number
	 */
	public void setTraceDataVersion(String newTraceDataVersion) {
		try {
			traceDataVersion = Integer.parseInt(newTraceDataVersion, 16);
		} catch (NumberFormatException nfe) {
			traceDataVersion = 0;
		}
	}

	/**
	 * Marks given dll as unloaded
	 * 
	 * @param dllName
	 *            Dll name
	 * @param startAddr
	 *            memory start address for DLL
	 * @param endAddr
	 *            memory end address for DLL
	 * @param dllUnloadTime
	 *            time when DLL is unloaded
	 * @return the dll marked as unloaded, or null if no match found
	 */
	public DllLoad unloadOneDll(String dllName, long startAddr, long endAddr,
			long dllUnloadTime) {
		DllLoad ret = null;
		for (DllLoad dll : dllLoads) {
			if (dll.getName().equals(dllName)
					&& dll.getStartAddress().longValue() == startAddr
					&& dll.getEndAddress().longValue() == endAddr) {
				dll.setUnloadTime(dllUnloadTime);
				ret = dll;
			}
		}
		return ret;
	}

	/**
	 * set end time of the process
	 * 
	 * @param endTime
	 */
	public void setEndTime(long endTime) {
		this.endTime = endTime;
	}

	// /**
	// * set end time of the process
	// *
	// * @param aTime
	// */
	// public void setEndTime(String aTime) {
	// Long lValue = Long.parseLong(aTime, 16);
	// endTime = lValue;
	// }

	/**
	 * set process name
	 * 
	 * @param aProcessName
	 */
	public void setProcessName(String aProcessName) {
		processName = aProcessName;
	}

	/**
	 * @return the process name
	 */
	public String getProcessName() {
		return processName;
	}

	/**
	 * get all events
	 * 
	 * @return list of BaseInfo
	 */
	public AbstractList<BaseInfo> getAllocsFrees() {
		return allocsFrees;
	}

	/**
	 * Get end time of the process
	 * 
	 * @return End time
	 */
	public Long getEndTime() {
		return endTime;
	}

	/**
	 * get list of allocations freed by a FreeInfo
	 * 
	 * @param free
	 * @return AbstractList<AllocInfo> list of allocations freed by the provided
	 *         FreeInfo
	 */
	public AbstractList<AllocInfo> getAllocsFreedBy(FreeInfo free) {
		AbstractList<AllocInfo> allocs = new ArrayList<AllocInfo>();
		for (BaseInfo alloc : allocsFrees) {
			if (alloc instanceof AllocInfo
					&& ((AllocInfo) alloc).getFreedBy() == free) {
				allocs.add((AllocInfo) alloc);
			}
		}
		return allocs;
	}

	/**
	 * Getter for highest memory allocation for the current process
	 * 
	 * @return int containing highest memory usage
	 */
	public int getHighestCumulatedMemoryAlloc() {
		return highestMemory;
	}
}