From 3dbaa0c63e9c6bd5a875a6502064a1e708fb4fdc Mon Sep 17 00:00:00 2001 From: woojin Date: Fri, 30 May 2014 11:08:13 +0900 Subject: [PATCH] Function Profiling : save callstack information to DB in runtime, enable binary setting's profiling 1. save callstackdata, callstackunit to DB in runtime, remove unnecessary callstackdata from memory 2. enable function profiling / callstack for libraries set in binary setting. Change-Id: I1805563f02089356985b0f6e94d618284301c7c6 Signed-off-by: woojin --- .../dynamicanalyzer/common/AnalyzerConstants.java | 5 + .../dynamicanalyzer/common/AnalyzerManager.java | 2 +- .../dynamicanalyzer/handlers/OpenTraceHandler.java | 5 +- .../org/tizen/dynamicanalyzer/sql/SqlManager.java | 7 +- .../swap/callstack/BaseCallstackManager.java | 192 +++++++++++++++++++-- .../swap/callstack/SWAPCallStackManager.java | 91 ++++------ .../swap/logparser/SWAPLogParser.java | 122 ++++++------- .../ui/info/callstack/CallStackInserter.java | 184 ++++++++++++++++++++ .../ui/info/callstack/CallStackManager.java | 9 +- .../ui/info/callstack/CallstackTable.java | 43 ++++- .../dynamicanalyzer/ui/range/RangeDataManager.java | 22 +-- .../summary/profiling/FunctionUsageProfiler.java | 50 +++++- .../ui/summary/profiling/ProfileDataMaker.java | 180 +++---------------- .../ui/summary/profiling/ProfilingTable.java | 16 +- .../ui/toolbar/StopLogProcessor.java | 6 +- .../ConfigurationDialogDataManager.java | 20 +-- .../ConfigurationDialogFeaturesTable.java | 12 +- 17 files changed, 605 insertions(+), 361 deletions(-) create mode 100644 org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallStackInserter.java diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerConstants.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerConstants.java index 5e0f54a..185433f 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerConstants.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerConstants.java @@ -316,6 +316,11 @@ public class AnalyzerConstants { public final static int MSG_SWAP_INST_REMOVE_ACK = 0x1009; public final static int MSG_WAIT_ACK = 0x1010; + // function entry/exit + public final static int FUNCTION_TYPE_APPINST = 0x0001; + public final static int FUNCTION_TYPE_SYSCALL = 0x0003; + public final static int FUNCTION_TYPE_FILE = 0x0004; + public final static int TYPE_TABLE_CALLSTACK = 0x0001; public final static int TYPE_TABLE_FAILED = 0x0002; public final static int TYPE_TABLE_LEAK = 0x0004; diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerManager.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerManager.java index 12ecdc1..fc7a819 100755 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerManager.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerManager.java @@ -79,7 +79,7 @@ public class AnalyzerManager { private static FailedChecker calledChecker = new FailedChecker(); private static WarningChecker warningChecker = new WarningChecker(); private static CallStackManager callstackManager = new CallStackManager(); - private static SWAPCallStackManager swapCallstackManager = new SWAPCallStackManager(); + private static SWAPCallStackManager swapCallstackManager = new SWAPCallStackManager(false); private static Timer screenshotTimer = null; diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/handlers/OpenTraceHandler.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/handlers/OpenTraceHandler.java index f2263be..f9e411a 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/handlers/OpenTraceHandler.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/handlers/OpenTraceHandler.java @@ -121,8 +121,9 @@ public class OpenTraceHandler extends AbstractHandler { } int percent = OpenTraceProgressManager.getInstance().getPercent(); - if (loadInfos() && loadCallStackData() && loadCallStackApis() + if (loadInfos() && loadCallStackApis() && loadProfilingData() && loadProfilingChildData() && + // loadCallStackData() && // loadLeakData() && // loadFailedData() && loadImageSet()) { @@ -492,4 +493,4 @@ public class OpenTraceHandler extends AbstractHandler { } }); } -} +} \ No newline at end of file diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/sql/SqlManager.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/sql/SqlManager.java index 1cb10f8..92c2534 100755 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/sql/SqlManager.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/sql/SqlManager.java @@ -38,13 +38,12 @@ import java.sql.SQLWarning; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; +import java.util.Map; import org.tizen.dynamicanalyzer.common.AnalyzerConstants; import org.tizen.dynamicanalyzer.common.AnalyzerManager; import org.tizen.dynamicanalyzer.common.GlobalInformation; -import org.tizen.dynamicanalyzer.communicator.DACommunicator; import org.tizen.dynamicanalyzer.constant.CommonConstants; import org.tizen.dynamicanalyzer.logparser.LogCenterConstants; import org.tizen.dynamicanalyzer.project.Project; @@ -801,7 +800,7 @@ public class SqlManager { for (int i = 0; i < pids.size(); i++) { ProfileDataMaker profiler = FunctionUsageProfiler.getInstance() .getProfileDataMakerByPid(pids.get(i)); - HashMap profilingDataMap = profiler + Map profilingDataMap = profiler .getProfilingDataMap(); List pDataList = new ArrayList(); pDataList.addAll(profilingDataMap.values()); @@ -836,7 +835,7 @@ public class SqlManager { for (int i = 0; i < pids.size(); i++) { ProfileDataMaker profiler = FunctionUsageProfiler.getInstance() .getProfileDataMakerByPid(pids.get(i)); - HashMap profilingDataMap = profiler + Map profilingDataMap = profiler .getChildListMap(); List pDataList = new ArrayList(); pDataList.addAll(profilingDataMap.values()); diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/callstack/BaseCallstackManager.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/callstack/BaseCallstackManager.java index 65cdf9a..7805286 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/callstack/BaseCallstackManager.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/callstack/BaseCallstackManager.java @@ -4,6 +4,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * WooJin Jung * Jooyoul Lee * Juyoung Kim * @@ -28,21 +29,31 @@ package org.tizen.dynamicanalyzer.swap.callstack; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.TreeMap; +import java.util.Map; +import java.util.NavigableMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; import org.tizen.dynamicanalyzer.common.AnalyzerConstants; import org.tizen.dynamicanalyzer.common.AnalyzerManager; import org.tizen.dynamicanalyzer.common.GlobalInformation; -import org.tizen.dynamicanalyzer.communicator.DACommunicator; +import org.tizen.dynamicanalyzer.common.SymbolManager; import org.tizen.dynamicanalyzer.logparser.LogCenterConstants; +import org.tizen.dynamicanalyzer.nl.InformationViewLabels; import org.tizen.dynamicanalyzer.project.AppInfo; +import org.tizen.dynamicanalyzer.swap.channel.control.BinaryInfo; +import org.tizen.dynamicanalyzer.swap.channel.data.LibraryObject; import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfo; import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfoPackage; import org.tizen.dynamicanalyzer.swap.model.data.LogData; +import org.tizen.dynamicanalyzer.swap.platform.BinarySettingManager; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackData; +import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackInserter; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackUnit; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackItem; import org.tizen.dynamicanalyzer.ui.summary.profiling.ProfileDataMaker; +import org.tizen.dynamicanalyzer.util.DALogger; +import org.tizen.dynamicanalyzer.utils.AnalyzerUtil; public abstract class BaseCallstackManager { protected class DuplicateUserCall { @@ -71,12 +82,16 @@ public abstract class BaseCallstackManager { } } - protected HashMap> callstackApiAddrByPidMap = new HashMap>(); - protected HashMap callstackDataBySeqMap = new HashMap(); + protected ConcurrentHashMap> callstackApiAddrByPidMap = new ConcurrentHashMap>(); + protected ConcurrentHashMap callstackDataBySeqMap = new ConcurrentHashMap(); protected String userFunctionBin = null; protected HashMap> userCallstackByTidMap = new HashMap>(); protected HashMap dupUserCallByTidMap = new HashMap(); - protected HashMap> seqTimeByTidMap = new HashMap>(); + protected HashMap> seqTimeByTidMap = new HashMap>(); + + protected CallStackInserter callstackInserter = null; + + protected static final DALogger DA_LOG = DALogger.getInstance(); abstract public void makeUserCallstack(LogData log, ProfileDataMaker profiler); @@ -85,6 +100,22 @@ public abstract class BaseCallstackManager { abstract public boolean isIrregularUserCall(LogData input); + public void offerCallStackUnit(CallStackUnit csu) { + if (callstackInserter != null) { + callstackInserter.startInserterThread(); + callstackInserter.offerCallstackUnit(csu); + } + return; + } + + public void offerCallStackData(CallStackData csd) { + if (callstackInserter != null) { + callstackInserter.startInserterThread(); + callstackInserter.offerCallstackData(csd); + } + return; + } + public List getPidsOfCallstackApiAddrMap() { ArrayList pids = new ArrayList(); pids.addAll(callstackApiAddrByPidMap.keySet()); @@ -92,21 +123,21 @@ public abstract class BaseCallstackManager { return pids; } - public HashMap getCallStackApiAddrByPidMap(int pid) { + public Map getCallStackApiAddrByPidMap(int pid) { if (null == callstackApiAddrByPidMap) { - callstackApiAddrByPidMap = new HashMap>(); + callstackApiAddrByPidMap = new ConcurrentHashMap>(); } - HashMap callstackApiByAddrMap = callstackApiAddrByPidMap.get(pid); + ConcurrentHashMap callstackApiByAddrMap = callstackApiAddrByPidMap.get(pid); if(null == callstackApiByAddrMap) { - callstackApiByAddrMap = new HashMap(); + callstackApiByAddrMap = new ConcurrentHashMap(); callstackApiAddrByPidMap.put(pid, callstackApiByAddrMap); } return callstackApiByAddrMap; } - public HashMap getCallStackDataBySeqMap() { + public Map getCallStackDataBySeqMap() { if (null == callstackDataBySeqMap) { - callstackDataBySeqMap = new HashMap(); + callstackDataBySeqMap = new ConcurrentHashMap(); } return callstackDataBySeqMap; } @@ -118,13 +149,13 @@ public abstract class BaseCallstackManager { return dupUserCallByTidMap; } - public TreeMap getSeqTimeByTidMap(int tid) { + public NavigableMap getSeqTimeByTidMap(int tid) { if (null == seqTimeByTidMap) { - seqTimeByTidMap = new HashMap>(); + seqTimeByTidMap = new HashMap>(); } - TreeMap seqByTimeMap = seqTimeByTidMap.get(tid); + ConcurrentSkipListMap seqByTimeMap = seqTimeByTidMap.get(tid); if(null == seqByTimeMap) { - seqByTimeMap = new TreeMap(); + seqByTimeMap = new ConcurrentSkipListMap(); seqTimeByTidMap.put(tid, seqByTimeMap); } return seqByTimeMap; @@ -184,7 +215,7 @@ public abstract class BaseCallstackManager { } public long getPCAddrBySeq(int seq) { - HashMap cdMap = getCallStackDataBySeqMap(); + Map cdMap = getCallStackDataBySeqMap(); if (null == cdMap) { return -1; } @@ -199,5 +230,134 @@ public abstract class BaseCallstackManager { return addrs.get(0); } + // TODO: remove unnecessary lines + // callstack symbol format : path(functionName + // ex. /usr/lib/libpthread.so(pthread_create + public String getCallStackSymbol(long addr, int pid, long time) { + String functionName = null; + String symbol = null; + ProcessInfoPackage processInfoPkg = AnalyzerManager + .getProject().getProcessInfoPackage(pid); + ProcessInfo processInfo = processInfoPkg.getProcessInfo(time); + + if (addr >= processInfo.getLowestAddress() + && addr <= processInfo.getHighestAddress()) { // application binary + String baseAddr = Long.toString(processInfo.getLowestAddress()); + String pcStr = Long.toString(addr); + BinaryInfo binInfo = processInfo.getTargetBinary(addr); + if(binInfo != null) { + String localPath = binInfo.getTempBinaryPath(); + boolean isPieBuild = true; + if (binInfo.getType() != 1) { + isPieBuild = false; + } + functionName = SymbolManager.addr2func(localPath, pcStr, isPieBuild, + baseAddr); + } + if (null == functionName || functionName.isEmpty() + || functionName.equals("_end")) { //$NON-NLS-1$ + functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION; +// ApiNameManager.getApiId(functionName); + } else { + String prevFunctionName = functionName; + functionName = SymbolManager + .demanglingFunctionName(prevFunctionName); +// ApiNameManager.getApiId(functionName); + } + // need to be checked again - in case pid is not main application + symbol = getUserFunctionPosition(pid, time) + + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING + + functionName; + } else { + HashMap binInfoMap = BinarySettingManager + .getInstance().getTargetBinInfoMap(); +// List binPaths = new ArrayList(); +// binPaths.addAll(binInfoMap.keySet()); + + List libObjs = processInfo.getLibObjs(); +// HashMap libHash = processInfo +// .getLibObjHash(); + LibraryObject libraryObject = null; + int size = libObjs.size(); + for (int i = 0; i < size; i++) { +// String binPath = binPaths.get(i); + LibraryObject libObj = libObjs.get(i); +// if (null == libObj) { +// continue; +// } + long lowAddr = libObj.getLowestAddress(); + long highAddr = libObj.getHighestAddress(); + + /** for debug */ +/* if (lowAddr > pcAddr || highAddr < pcAddr) { + System.out.print(sampleLog.getId() + + "lib : " + libObj.getLibPath() + " ==> "); + AnalyzerUtil.printHexdecimal(lowAddr); + System.out.print(" < "); + AnalyzerUtil.printHexdecimal(pcAddr); + System.out.print(" < "); + AnalyzerUtil.printHexdecimal(highAddr); + System.out.println(); + } +*/ + if (addr >= lowAddr && addr <= highAddr) { + libraryObject = libObj; + break; + } + else { +// System.out.print(sampleLog.getId() +// + "lib : " + libObj.getLibPath() + " ==> "); +// AnalyzerUtil.printHexdecimal(lowAddr); +// System.out.print(" < "); +// AnalyzerUtil.printHexdecimal(pcAddr); +// System.out.print(" < "); +// AnalyzerUtil.printHexdecimal(highAddr); +// System.out.println(); + } + } + if (null != libraryObject) { + String path = libraryObject.getLibPath(); + BinaryInfo binInfo = binInfoMap.get(path); + if (null != binInfo) { + String localPath = binInfo.getTempBinaryPath(); + String baseAddr = Long.toString(libraryObject + .getLowestAddress()); + String pcStr = Long.toString(addr); + boolean isPieBuild = true; + if (binInfo.getType() != 1) { + isPieBuild = false; + } + functionName = SymbolManager.addr2func(localPath, pcStr, + isPieBuild, baseAddr); + if (null == functionName || functionName.isEmpty() + || functionName.equals("_end")) { //$NON-NLS-1$ + functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION; +// ApiNameManager.getApiId(functionName); + } else { + String prevFunctionName = functionName; + functionName = SymbolManager + .demanglingFunctionName(prevFunctionName); +// ApiNameManager.getApiId(functionName); + } + // need to be checked again - in case pid is not main application + } else { + functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION; + } + symbol = path + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING + + functionName; + } else { + DA_LOG.debug("binary for the sample pc is not found :" + AnalyzerUtil.toHexdecimal(addr)); //$NON-NLS-1$ + symbol = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_LIBRARY + + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING + + AnalyzerUtil.toHexdecimal(addr); +// + InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION; + } + } + + AnalyzerManager.getFuncNameMapByPid(pid) + .put(addr, functionName); + return symbol; + } + abstract public void clear(); } diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/callstack/SWAPCallStackManager.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/callstack/SWAPCallStackManager.java index a953e59..9b6c17e 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/callstack/SWAPCallStackManager.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/callstack/SWAPCallStackManager.java @@ -33,13 +33,13 @@ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.M import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.TreeMap; +import java.util.Map; +import java.util.NavigableMap; import org.tizen.dynamicanalyzer.common.AnalyzerConstants; import org.tizen.dynamicanalyzer.common.AnalyzerManager; import org.tizen.dynamicanalyzer.common.GlobalInformation; import org.tizen.dynamicanalyzer.common.SymbolManager; -import org.tizen.dynamicanalyzer.communicator.DACommunicator; import org.tizen.dynamicanalyzer.logparser.LogCenterConstants; import org.tizen.dynamicanalyzer.swap.channel.control.BinaryInfo; import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfo; @@ -48,28 +48,29 @@ import org.tizen.dynamicanalyzer.swap.model.data.LogData; import org.tizen.dynamicanalyzer.swap.model.data.ProbeCommonData; import org.tizen.dynamicanalyzer.swap.model.data.ProfileData; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackData; +import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackInserter; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackItem; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackUnit; import org.tizen.dynamicanalyzer.ui.summary.profiling.ProfileDataMaker; -import org.tizen.dynamicanalyzer.util.DALogger; import org.tizen.dynamicanalyzer.utils.AnalyzerUtil; public class SWAPCallStackManager extends BaseCallstackManager { - private static final DALogger DA_LOG = DALogger.getInstance(); + + // callstackdata made in range analysis should not be saved to DB + public SWAPCallStackManager(boolean isRange) { + if (!isRange) { + callstackInserter = CallStackInserter.getInstance(); + } else { + callstackInserter = null; + } + } public void makeUserCallstack(LogData input, ProfileDataMaker profiler) { ProfileData log = (ProfileData) input; int pid = log.getPid(); long time = log.getTime(); - HashMap addrMap = getCallStackApiAddrByPidMap(pid); - boolean isPieBuild = AnalyzerUtil.isPieBuild(pid, time); - String baseAddr = Long.toString(AnalyzerManager.getProject() - .getBaseAddress(pid, time)); - String sourceBinPath = AnalyzerUtil.getBinarySourcePath(pid, time); - if (null == sourceBinPath || sourceBinPath.isEmpty()) { - return; - } + Map addrMap = getCallStackApiAddrByPidMap(pid); int seq = log.getSeq(); int tid = log.getTid(); @@ -77,19 +78,16 @@ public class SWAPCallStackManager extends BaseCallstackManager { long selfAddr = log.getPcAddr(); long callerAddr = log.getCallerPcAddr(); - String strSelfAddr = Long.toString(selfAddr); - String strCallerAddr = Long.toString(callerAddr); - CallStackData callstackData = new CallStackData(seq); CallStackUnit selfCallstackUnit = addrMap.get(selfAddr); if (null == selfCallstackUnit) { - String strSelfFuncName = SymbolManager.addr2func(sourceBinPath, - strSelfAddr, isPieBuild, baseAddr); - String strSelfSymbol = getUserFunctionPosition(pid, time) + String strSelfFuncName = log.getApiName(); + String strSelfSymbol = log.getBinaryPath() + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING + strSelfFuncName; selfCallstackUnit = new CallStackUnit(selfAddr, strSelfSymbol, log); + offerCallStackUnit(selfCallstackUnit); addrMap.put(selfAddr, selfCallstackUnit); } @@ -98,17 +96,14 @@ public class SWAPCallStackManager extends BaseCallstackManager { List userCallstack = getUserCallstack(tid); int size = userCallstack.size(); - TreeMap seqByTimeMap = getSeqTimeByTidMap(tid); + NavigableMap seqByTimeMap = getSeqTimeByTidMap(tid); CallStackUnit callerCallstackUnit = addrMap.get(callerAddr); if (null == callerCallstackUnit) { - String strCallerFuncName = SymbolManager.addr2func(sourceBinPath, - strCallerAddr, isPieBuild, baseAddr); - String strCallerSymbol = getUserFunctionPosition(pid, time) - + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING - + strCallerFuncName; + String strCallerSymbol = getCallStackSymbol(callerAddr, pid, time); callerCallstackUnit = new CallStackUnit(callerAddr, strCallerSymbol, log); + offerCallStackUnit(callerCallstackUnit); addrMap.put(callerAddr, callerCallstackUnit); } @@ -129,6 +124,7 @@ public class SWAPCallStackManager extends BaseCallstackManager { LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR, LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_SYMBOL, log); + offerCallStackUnit(defaultCallstackUnit); addrMap.put( LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR, defaultCallstackUnit); @@ -177,6 +173,7 @@ public class SWAPCallStackManager extends BaseCallstackManager { callstackData.getAddrs().add( userCallstack.get(i).getCallStackUnit().getAddr()); } + offerCallStackData(callstackData); getCallStackDataBySeqMap().put(seq, callstackData); seqByTimeMap.put(time, seq); } else if (eventType == MSG_FUNCTION_EXIT) { @@ -231,6 +228,7 @@ public class SWAPCallStackManager extends BaseCallstackManager { callstackData.getAddrs().add( userCallstack.get(i).getCallStackUnit().getAddr()); } + offerCallStackData(callstackData); getCallStackDataBySeqMap().put(seq, callstackData); seqByTimeMap.put(time, seq); } else { @@ -259,35 +257,21 @@ public class SWAPCallStackManager extends BaseCallstackManager { log = (ProbeCommonData) inputData; } - HashMap addrMap = getCallStackApiAddrByPidMap(inputData - .getPid()); + Map addrMap = + getCallStackApiAddrByPidMap(inputData.getPid()); int pid; long time; - boolean isPieBuild; - String baseAddr, sourceBinPath; if (isProfileData) { pid = pData.getPid(); time = pData.getTime(); - isPieBuild = isPieBuild(pid, time); - baseAddr = Long.toString(AnalyzerManager.getProject() - .getBaseAddress(pid, time)); - sourceBinPath = AnalyzerUtil.getBinarySourcePath(pid, time); } else { pid = log.getPid(); time = log.getTime(); - isPieBuild = isPieBuild(pid, time); - baseAddr = Long.toString(AnalyzerManager.getProject() - .getBaseAddress(pid, time)); - sourceBinPath = AnalyzerUtil.getBinarySourcePath(pid, time); - } - - if (null == sourceBinPath || sourceBinPath.isEmpty()) { - return; } int seq = inputData.getSeq(); int tid; - long callerAddr; + long callerAddr = -1; if (isProfileData) { tid = pData.getTid(); callerAddr = pData.getCallerPcAddr(); @@ -303,12 +287,12 @@ public class SWAPCallStackManager extends BaseCallstackManager { // getCallStackDataBySeqMap().put(seq, callstackData); // return; // } - if (callerAddr < 0) { + if (callerAddr < 0) { // TODO: verify which case this is CallStackData callstackData = new CallStackData(seq); + offerCallStackData(callstackData); getCallStackDataBySeqMap().put(seq, callstackData); return; } - String strCallerAddr = Long.toString(callerAddr); // System.out.println("tid :" + tid); List probeCallstack = new ArrayList( @@ -331,6 +315,7 @@ public class SWAPCallStackManager extends BaseCallstackManager { LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR, LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_SYMBOL, inputData); + offerCallStackUnit(defaultCallstackUnit); addrMap.put( LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR, defaultCallstackUnit); @@ -338,13 +323,10 @@ public class SWAPCallStackManager extends BaseCallstackManager { } else { CallStackUnit callerCallstackUnit = addrMap.get(callerAddr); if (null == callerCallstackUnit) { - String strCallerFuncName = SymbolManager.addr2func( - sourceBinPath, strCallerAddr, isPieBuild, baseAddr); - String strCallerSymbol = getUserFunctionPosition(pid, time) - + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING - + strCallerFuncName; + String strCallerSymbol = getCallStackSymbol(callerAddr, pid, time); callerCallstackUnit = new CallStackUnit(callerAddr, strCallerSymbol, inputData); + offerCallStackUnit(callerCallstackUnit); addrMap.put(callerAddr, callerCallstackUnit); } @@ -364,6 +346,7 @@ public class SWAPCallStackManager extends BaseCallstackManager { callstackData.getAddrs().add( probeCallstack.get(i).getCallStackUnit().getAddr()); } + offerCallStackData(callstackData); getCallStackDataBySeqMap().put(seq, callstackData); } @@ -371,7 +354,7 @@ public class SWAPCallStackManager extends BaseCallstackManager { // check irregular enter/exit log (multiple logs from 1 function call) public boolean isIrregularUserCall(LogData log) { ProfileData input = (ProfileData) log; - HashMap addrMap = getCallStackApiAddrByPidMap(input + Map addrMap = getCallStackApiAddrByPidMap(input .getPid()); HashMap dupUserCallMap = getDupUserCallByTidMap(); @@ -460,12 +443,12 @@ public class SWAPCallStackManager extends BaseCallstackManager { if (null == processInfo) { return false; } - - if (addr >= processInfo.getLowestAddress() - && addr <= processInfo.getHighestAddress()) { - return true; - } else { + // return true when addr is within memory range of main executable + // or library which is set in the binary setting + if (null == processInfo.getTargetBinary(addr)) { return false; + } else { + return true; } } diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/logparser/SWAPLogParser.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/logparser/SWAPLogParser.java index 4fbd928..6925c2c 100755 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/logparser/SWAPLogParser.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/logparser/SWAPLogParser.java @@ -4,6 +4,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * WooJin Jung * Jooyoul Lee * Juyoung Kim * @@ -155,69 +156,66 @@ public class SWAPLogParser implements Runnable { if (id != DataChannelConstants.MSG_DATA_SAMPLE) { ProfileData pData = (ProfileData) log; - long pcAddr = pData.getPcAddr(); - - ProcessInfoPackage processInfoPkg = AnalyzerManager - .getProject().getProcessInfoPackage(pData.getPid()); - - String apiName = pData.getApiName(); - if (null == apiName || apiName.isEmpty() - || apiName.equals("_end")) { //$NON-NLS-1$ - apiName = getFuncName(pData); - if (apiName == null - || apiName.equals("")) { - continue; - } else { - pData.setApiName(apiName); + System.out.println("@@@@ " + pData.getProbeType() + pData.getProbeSubType() + " @@@@@"); + // function_exit log doesn't have probe type yet +// if (pData.getProbeType() +// == AnalyzerConstants.FUNCTION_TYPE_APPINST) { + + ProcessInfoPackage processInfoPkg = AnalyzerManager + .getProject().getProcessInfoPackage(pData.getPid()); + + String apiName = pData.getApiName(); + if (null == apiName || apiName.isEmpty() + || apiName.equals("_end")) { //$NON-NLS-1$ + apiName = getFuncName(pData); + if (apiName == null + || apiName.equals("")) { + continue; + } else { + pData.setApiName(apiName); + } } - } - - if (processInfoPkg.isDropLog()) { - apiName = pData.getApiName(); - if (apiName.contains(OSP_MAIN)) { - processInfoPkg.setDropLog(false); - } else { - continue; + System.out.println("@@@@ " + pData.getApiName() + " @@@@@"); + if (processInfoPkg.isDropLog()) { + apiName = pData.getApiName(); + if (apiName.contains(OSP_MAIN)) { + processInfoPkg.setDropLog(false); + } else { + continue; + } } - } - - // irregular call check still necessary? - // if (AnalyzerManager.getCallstackManager() - // .isIrregularUserCall(pData)) { - // continue; - // } - - ProcessInfo processInfo = processInfoPkg - .getProcessInfo(pData.getTime()); - - // for debug - // System.out.println(" PROFILE LOG DEBUG = ID: " - // + pData.getId() - // + " PC : " - // + AnalyzerUtil.toHexdecimal(pData.getPcAddr()) - // + " Api : " - // + pData.getApiName() - // + " caller : " - // + AnalyzerUtil.toHexdecimal(pData.getCallerPcAddr()) - // + " base addr : " - // + AnalyzerUtil.toHexdecimal(processInfo - // .getLowestAddress())); - - pushLog(log, logPack); - if (pcAddr >= processInfo.getLowestAddress() - && pcAddr <= processInfo.getHighestAddress()) { - /* user callstack create by entry and exit */ - AnalyzerManager.getCallstackManager() - .makeUserCallstack( - pData, - FunctionUsageProfiler.getInstance() - .getProfileDataMakerByPid( - pData.getPid())); - } else { - AnalyzerManager.getCallstackManager() - .makeCallstackWithoutBacktrace(pData); - } - } else { + + // irregular call check still necessary? + // if (AnalyzerManager.getCallstackManager() + // .isIrregularUserCall(pData)) { + // continue; + // } + + + // for debug + // System.out.println(" PROFILE LOG DEBUG = ID: " + // + pData.getId() + // + " PC : " + // + AnalyzerUtil.toHexdecimal(pData.getPcAddr()) + // + " Api : " + // + pData.getApiName() + // + " caller : " + // + AnalyzerUtil.toHexdecimal(pData.getCallerPcAddr()) + // + " base addr : " + // + AnalyzerUtil.toHexdecimal(processInfo + // .getLowestAddress())); + + pushLog(log, logPack); + AnalyzerManager.getCallstackManager() + .makeUserCallstack( + pData, + FunctionUsageProfiler.getInstance() + .getProfileDataMakerByPid( + pData.getPid())); +// } else { // system call enter/exit : not used yet +// pushLog(log, logPack); +// } + } else { // sample log pushLog(log, logPack); } } else if (log instanceof ReplayData) { @@ -426,6 +424,7 @@ public class SWAPLogParser implements Runnable { // System.out.println(" ]"); // } + // TODO: remove unnecessary code private String getFuncName(ProfileData input) { long pcAddr = input.getPcAddr(); HashMap funcNameMap = AnalyzerManager @@ -528,6 +527,7 @@ public class SWAPLogParser implements Runnable { String baseAddr = Long.toString(libraryObject .getLowestAddress()); String pcStr = Long.toString(pcAddr); + input.setBinaryPath(binInfo.getTargetBinaryPath()); boolean isPieBuild = true; if (binInfo.getType() != 1) { isPieBuild = false; diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallStackInserter.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallStackInserter.java new file mode 100644 index 0000000..d4481bb --- /dev/null +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallStackInserter.java @@ -0,0 +1,184 @@ +/* + * Dynamic Analyzer + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * WooJin Jung + * Juyoung Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.dynamicanalyzer.ui.info.callstack; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.tizen.dynamicanalyzer.common.AnalyzerConstants; +import org.tizen.dynamicanalyzer.constant.CommonConstants; +import org.tizen.dynamicanalyzer.sql.DBTableInfo; +import org.tizen.dynamicanalyzer.sql.DBTableManager; +import org.tizen.dynamicanalyzer.sql.SqlManager; + +// TODO: apply new DB schema, class, API +// inserter thread for callstackdata, callstackunit +public class CallStackInserter implements Runnable { + private static CallStackInserter instance = null; + private ConcurrentLinkedQueue callstackDataQueue = new ConcurrentLinkedQueue(); + private ConcurrentLinkedQueue callstackUnitQueue = new ConcurrentLinkedQueue(); + private static volatile Thread inserterThread = null; + private static final int FULL_COUNT = 100; + private static boolean stopTrace = false; + + public synchronized static CallStackInserter getInstance() { + if (null == instance) { + instance = new CallStackInserter(); + } + return instance; + } + + public synchronized void startInserterThread() { + if (inserterThread == null) { + stopTrace = false; + inserterThread = new Thread(null, getInstance()); + inserterThread.start(); + } + + } + + public void stopInserterThread() { + if (inserterThread != null && inserterThread.isAlive()) { + try { + stopTrace = true; + inserterThread.join(AnalyzerConstants.THREAD_JOIN_WAIT_TIME); + inserterThread = null; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void saveCallStackUnits() { + DBTableInfo unitTableInfo = DBTableManager.getInstance().getTableInfo( + DBTableManager.TABLE_INDEX_CALLSTACK_UNITS); + List> insetData = new ArrayList>(); + String insertQuery = unitTableInfo.insertQuery(); + CallStackUnit csu = null; + int insertCount = FULL_COUNT; + + while ((csu = callstackUnitQueue.poll()) != null) { + List insetRowData = new ArrayList(); + try { + insetRowData.add(Long.toString(csu.getAddr())); + insetRowData.add(csu.getSymbol()); + insetRowData.add(Integer.toString(csu.getPid())); + insetRowData.add(Long.toString(csu.getTime())); + } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + } + insetData.add(insetRowData); + if ((insertCount-- <= 0) && (stopTrace == false)) { + break; + } + } + if (insetData.size() > 0) { + SqlManager.getInstance().insertQuery(insertQuery, insetData); + } + } + + private void saveCallStackData() { + DBTableInfo callstackData = DBTableManager.getInstance().getTableInfo( + DBTableManager.TABLE_INDEX_CALLSTACK_DATA); + List> insetData = new ArrayList>(); + String insertQuery = callstackData.insertQuery(); + CallStackData csd = null; + int insertCount = FULL_COUNT; + + while ((csd = callstackDataQueue.poll()) != null) { + List insetRowData = new ArrayList(); + String addrs = makeLongList2String(csd.getAddrs()); + try { + insetRowData.add(Integer.toString(csd.getSeq())); + insetRowData.add(addrs); + } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + } + insetData.add(insetRowData); + if ((insertCount-- <= 0) && (stopTrace == false)) { + break; + } + } + if (insetData.size() > 0) { + SqlManager.getInstance().insertQuery(insertQuery, insetData); + } + } + + public void offerCallstackUnit(CallStackUnit csu) { + if (null != csu) { + callstackUnitQueue.offer(csu); + } + } + + public void offerCallstackData(CallStackData csd) { + if (null != csd) { + callstackDataQueue.offer(csd); + } + } + + @Override + public void run() { + while (!stopTrace) { + if (callstackUnitQueue.size() > FULL_COUNT) + saveCallStackUnits(); + if (callstackDataQueue.size() > FULL_COUNT) + saveCallStackData(); + + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + saveCallStackUnits(); + saveCallStackData(); + } + + public static String makeLongList2String(List input) { + if (null == input || input.isEmpty()) { + return null; + } + + int size = input.size(); + StringBuffer str = new StringBuffer(); + for (int i = 0; i < size; i++) { + try { + str.append(input.get(i)); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + if (i + 1 == size) { + break; + } else { + str.append(CommonConstants.SLASH); + } + } + return str.toString(); + } + +} \ No newline at end of file diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallStackManager.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallStackManager.java index 3171588..608133b 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallStackManager.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallStackManager.java @@ -30,6 +30,7 @@ package org.tizen.dynamicanalyzer.ui.info.callstack; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import org.tizen.dynamicanalyzer.common.AnalyzerConstants; import org.tizen.dynamicanalyzer.common.AnalyzerManager; @@ -41,15 +42,13 @@ import org.tizen.dynamicanalyzer.swap.model.data.LogData; import org.tizen.dynamicanalyzer.swap.model.data.ProbeCommonData; import org.tizen.dynamicanalyzer.swap.model.data.UserFunctionData; import org.tizen.dynamicanalyzer.ui.summary.profiling.ProfileDataMaker; -import org.tizen.dynamicanalyzer.util.DALogger; import org.tizen.dynamicanalyzer.utils.AnalyzerUtil; public class CallStackManager extends BaseCallstackManager { - private static final DALogger DA_LOG = DALogger.getInstance(); public void makeUserCallstack(LogData input, ProfileDataMaker profiler) { UserFunctionData log = (UserFunctionData) input; - HashMap addrMap = getCallStackApiAddrByPidMap(log.getPid()); + Map addrMap = getCallStackApiAddrByPidMap(log.getPid()); boolean isPieBuild = AnalyzerUtil.isPieBuild(log.getPid(), log.getTime()); String baseAddr = Long.toString(AnalyzerManager.getProject() @@ -215,7 +214,7 @@ public class CallStackManager extends BaseCallstackManager { } public void makeCallstackWithoutBacktrace(LogData inputData) { - HashMap addrMap = getCallStackApiAddrByPidMap(inputData.getPid()); + Map addrMap = getCallStackApiAddrByPidMap(inputData.getPid()); boolean isPieBuild = AnalyzerUtil.isPieBuild(inputData.getPid(), inputData.getTime()); String baseAddr = Long.toString(AnalyzerManager.getProject() @@ -305,7 +304,7 @@ public class CallStackManager extends BaseCallstackManager { // check irregular enter/exit log (multiple logs from 1 function call) public boolean isIrregularUserCall(LogData data) { UserFunctionData input = (UserFunctionData) data; - HashMap addrMap = getCallStackApiAddrByPidMap(input.getPid()); + Map addrMap = getCallStackApiAddrByPidMap(input.getPid()); HashMap dupUserCallMap = getDupUserCallByTidMap(); boolean isPieBuild = AnalyzerUtil.isPieBuild(input.getPid(), diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallstackTable.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallstackTable.java index 169e159..52682ad 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallstackTable.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/info/callstack/CallstackTable.java @@ -4,6 +4,7 @@ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * WooJin Jung * Jooyoul Lee * Juyoung Kim * @@ -26,8 +27,9 @@ package org.tizen.dynamicanalyzer.ui.info.callstack; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.eclipse.nebula.widgets.grid.GridItem; import org.eclipse.swt.SWT; @@ -37,7 +39,9 @@ import org.eclipse.swt.widgets.Composite; import org.tizen.dynamicanalyzer.common.AnalyzerConstants; import org.tizen.dynamicanalyzer.common.AnalyzerManager; import org.tizen.dynamicanalyzer.common.DASelectionData; +import org.tizen.dynamicanalyzer.constant.CommonConstants; import org.tizen.dynamicanalyzer.model.TableInput; +import org.tizen.dynamicanalyzer.sql.SqlManager; import org.tizen.dynamicanalyzer.swap.model.data.LogData; import org.tizen.dynamicanalyzer.ui.file.FilePage; import org.tizen.dynamicanalyzer.ui.opengl.GLPage; @@ -47,10 +51,12 @@ import org.tizen.dynamicanalyzer.ui.summary.SummaryPage; import org.tizen.dynamicanalyzer.ui.userinterface.UIPage; import org.tizen.dynamicanalyzer.ui.widgets.table.DATableComposite; import org.tizen.dynamicanalyzer.ui.widgets.table.DATableDataFormat; +import org.tizen.dynamicanalyzer.util.DALogger; import org.tizen.dynamicanalyzer.utils.Formatter; import org.tizen.dynamicanalyzer.widgets.da.view.DAViewData; public class CallstackTable extends DATableComposite { + private static final DALogger DA_LOG = DALogger.getInstance(); public CallstackTable(Composite parent, int compStyle, int tableStyle) { super(parent, compStyle, tableStyle); @@ -132,25 +138,50 @@ public class CallstackTable extends DATableComposite { libName = logData.getLibName(); } - HashMap cdMap = AnalyzerManager + Map cdMap = AnalyzerManager .getCallstackManager().getCallStackDataBySeqMap(); - HashMap addrMap = AnalyzerManager + Map addrMap = AnalyzerManager .getCallstackManager().getCallStackApiAddrByPidMap(pid); if (null == cdMap || null == addrMap) { return; } CallStackData csd = cdMap.get(seqNum); - if (null == csd) { - return; + List addrs = null; + if (null == csd) { // callstackdata is not in memory, find from DB + // TODO: apply new DB schema + String callstackQuery = "where seqnumber = " + seqNum; + List> dbInfo = SqlManager.getInstance() + .selectQuery(null, new String[] { "callstack" }, + "CallstackData", callstackQuery); + if (null == dbInfo || 0 == dbInfo.size() + || null == dbInfo.get(0)) { // not found + return; + } + String strAddrs = dbInfo.get(0).get(0); + if (null == strAddrs) { + return; + } + String[] splitAddrs = strAddrs.split(CommonConstants.SLASH); + int size = splitAddrs.length; + addrs = new ArrayList(); + for (int j = 0; j < size; j++) { + long addr = Long.parseLong(splitAddrs[j]); + addrs.add(addr); + } + } else { // callstackdata is in memory + addrs = csd.getAddrs(); } - List addrs = csd.getAddrs(); int size = addrs.size(); for (int i = 0; i < size; i++) { CallStackUnit api = addrMap.get(addrs.get(i)); String hexAddr = Formatter.toHexString(addrs.get(i).toString()); String path = api.getPath(); + if (null == path) { + DA_LOG.debug("callstackunit for addr : " + hexAddr + " not found"); + return; + } // if path has "da_probe.so" then reject if (path.contains(AnalyzerConstants.PROBE_LIB_TIZEN) || path.contains(AnalyzerConstants.PROBE_LIB_OSP)) { diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/range/RangeDataManager.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/range/RangeDataManager.java index 301266c..63fb719 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/range/RangeDataManager.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/range/RangeDataManager.java @@ -4,6 +4,7 @@ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * WooJin Jung * Jooyoul Lee * Juyoung Kim * @@ -39,8 +40,6 @@ import org.tizen.dynamicanalyzer.sql.SqlManager; import org.tizen.dynamicanalyzer.swap.callstack.BaseCallstackManager; import org.tizen.dynamicanalyzer.swap.callstack.SWAPCallStackManager; import org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants; -import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfo; -import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfoPackage; import org.tizen.dynamicanalyzer.swap.logparser.LogPackage; import org.tizen.dynamicanalyzer.swap.logparser.Logs; import org.tizen.dynamicanalyzer.swap.model.data.LogData; @@ -86,7 +85,7 @@ public class RangeDataManager implements Runnable { leakDetector = new LeakDetector(); warningChecker = new WarningChecker(); callstackManager = new CallStackManager(); - swapCallstackManager = new SWAPCallStackManager(); + swapCallstackManager = new SWAPCallStackManager(true); // fileDataMaker = new FileDataMaker(failedChecker, leakDetector, // warningChecker); @@ -438,24 +437,15 @@ public class RangeDataManager implements Runnable { ProfileDataMaker profileDataMaker = getProfileDataMakerByPid(input .getPid()); if (input.getId() != DataChannelConstants.MSG_DATA_SAMPLE) { - ProcessInfoPackage processInfoPkg = AnalyzerManager - .getProject().getProcessInfoPackage(input.getPid()); - ProcessInfo processInfo = processInfoPkg - .getProcessInfo(input.getTime()); - long pcAddr = input.getPcAddr(); - if (pcAddr >= processInfo.getLowestAddress() - && pcAddr <= processInfo.getHighestAddress()) { - /* user callstack create by entry and exit */ + // function_exit log doesn't have probe type yet +// if (input.getProbeType() +// == AnalyzerConstants.FUNCTION_TYPE_APPINST) { swapCallstackManager.makeUserCallstack(input, profileDataMaker); - } else { - swapCallstackManager - .makeCallstackWithoutBacktrace(input); - } +// } } else { profileDataMaker.makeFunctionUsageProfileData(input); } - } } } diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/FunctionUsageProfiler.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/FunctionUsageProfiler.java index 891d541..0e23e6f 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/FunctionUsageProfiler.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/FunctionUsageProfiler.java @@ -29,7 +29,11 @@ package org.tizen.dynamicanalyzer.ui.summary.profiling; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.NavigableMap; +import java.util.SortedMap; import org.tizen.dynamicanalyzer.common.AnalyzerManager; import org.tizen.dynamicanalyzer.constant.CommonConstants; @@ -105,15 +109,45 @@ public class FunctionUsageProfiler extends PageDataManager { ConfigureLabels.FUNCTION_PROFILING_SAMPLING_PERIODIC); } - Logs logs = pack.getLogs(DataChannelConstants.MSG_DATA_SAMPLE); - if (null != logs && logs.getRawLogs().size() != 0) { - List sample = logs.getLogs(); - int size = sample.size(); - for (int i = 0; i < size; i++) { - getInstance().getProfileDataMakerByPid(sample.get(i).getPid()) - .makeFunctionUsageProfileData( - (ProfileData) sample.get(i)); + if (ConfigurationDialogDataManager.getInstance() // sampling is on + .getfeatureValue( + ConfigureLabels.FEATURE_FUNCTION_PROFILING) != 0) { + Logs logs = pack.getLogs(DataChannelConstants.MSG_DATA_SAMPLE); + if (null != logs && logs.getRawLogs().size() != 0) { + List sample = logs.getLogs(); + int size = sample.size(); + for (int i = 0; i < size; i++) { + ProfileData sampleLog = (ProfileData) sample.get(i); + getInstance().getProfileDataMakerByPid( + sample.get(i).getPid()) + .makeFunctionUsageProfileData(sampleLog); + // remove unnecessary callstackdata from memory + NavigableMap seqByTimeMap = + AnalyzerManager.getCallstackManager() + .getSeqTimeByTidMap(sampleLog.getTid()); + // find the time of callstackdata which was made + // right before the current sample time + // callstackdatas made before that time is needless + Long lastTime = seqByTimeMap + .floorKey(sampleLog.getTime()); + if (null != lastTime) { + SortedMap headMap = + seqByTimeMap.headMap(lastTime); + Iterator> itr = headMap + .entrySet().iterator(); + while (itr.hasNext()) { + Map.Entry entry = itr.next(); + AnalyzerManager.getCallstackManager() + .getCallStackDataBySeqMap() + .remove(entry.getValue()); + itr.remove(); + } + } + } } + } else { // sampling is off, callstackdata is not needed in memory + AnalyzerManager.getCallstackManager() + .getCallStackDataBySeqMap().clear(); } } } diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/ProfileDataMaker.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/ProfileDataMaker.java index f8c65f2..d2dc784 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/ProfileDataMaker.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/ProfileDataMaker.java @@ -32,29 +32,22 @@ import static org.tizen.dynamicanalyzer.swap.channel.data.DataChannelConstants.M import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.TreeMap; +import java.util.Map; +import java.util.NavigableMap; +import java.util.concurrent.ConcurrentHashMap; import org.tizen.dynamicanalyzer.common.AnalyzerConstants; -import org.tizen.dynamicanalyzer.common.AnalyzerManager; -import org.tizen.dynamicanalyzer.common.SymbolManager; import org.tizen.dynamicanalyzer.common.path.PathConstants; import org.tizen.dynamicanalyzer.communicator.DACommunicator; import org.tizen.dynamicanalyzer.logparser.LogCenterConstants; -import org.tizen.dynamicanalyzer.nl.InformationViewLabels; import org.tizen.dynamicanalyzer.swap.callstack.BaseCallstackManager; -import org.tizen.dynamicanalyzer.swap.channel.control.BinaryInfo; -import org.tizen.dynamicanalyzer.swap.channel.data.LibraryObject; -import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfo; -import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfoPackage; import org.tizen.dynamicanalyzer.swap.model.data.LogData; import org.tizen.dynamicanalyzer.swap.model.data.ProfileData; import org.tizen.dynamicanalyzer.swap.model.data.UserFunctionData; -import org.tizen.dynamicanalyzer.swap.platform.BinarySettingManager; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackData; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackItem; import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackUnit; import org.tizen.dynamicanalyzer.util.DALogger; -import org.tizen.dynamicanalyzer.utils.AnalyzerUtil; import org.tizen.dynamicanalyzer.utils.Formatter; public class ProfileDataMaker { @@ -102,13 +95,13 @@ public class ProfileDataMaker { * key: seq - value : function usage profiling data hash map all function * usage profiling data are in this hash map **/ - private HashMap profilingDataMap = null; - private HashMap symbolSeqHash = null; + private ConcurrentHashMap profilingDataMap = null; + private ConcurrentHashMap symbolSeqHash = null; /** * key : seq - value : child seq list // all child lists are in this hash */ - private HashMap childListMap = null; + private ConcurrentHashMap childListMap = null; private ProfilingData appBin = null; private ProfilingData dependentLib = null; @@ -170,7 +163,7 @@ public class ProfileDataMaker { } public ProfilingData getProfilingDataByKey(String key) { - HashMap hash = getSymbolSeqHash(); + Map hash = getSymbolSeqHash(); String seq = hash.get(key); if (null != seq) { return getProfilingDataMap().get(Integer.parseInt(seq)); @@ -178,23 +171,23 @@ public class ProfileDataMaker { return null; } - public HashMap getProfilingDataMap() { + public Map getProfilingDataMap() { if (null == profilingDataMap) { - profilingDataMap = new HashMap(); + profilingDataMap = new ConcurrentHashMap(); } return profilingDataMap; } - public HashMap getChildListMap() { + public Map getChildListMap() { if (null == childListMap) { - childListMap = new HashMap(); + childListMap = new ConcurrentHashMap(); } return childListMap; } - public HashMap getSymbolSeqHash() { + public Map getSymbolSeqHash() { if (null == symbolSeqHash) { - symbolSeqHash = new HashMap(); + symbolSeqHash = new ConcurrentHashMap(); } return symbolSeqHash; } @@ -271,136 +264,7 @@ public class ProfileDataMaker { } } } - - public String getSamplePCSymbol(ProfileData sampleLog) { - String functionName = null; - String symbol = null; - long pcAddr = sampleLog.getPcAddr(); - ProcessInfoPackage processInfoPkg = AnalyzerManager - .getProject().getProcessInfoPackage(sampleLog.getPid()); - ProcessInfo processInfo = processInfoPkg.getProcessInfo(sampleLog - .getTime()); - - if (pcAddr >= processInfo.getLowestAddress() - && pcAddr <= processInfo.getHighestAddress()) { // application binary - String baseAddr = Long.toString(processInfo.getLowestAddress()); - String pcStr = Long.toString(pcAddr); - BinaryInfo binInfo = processInfo.getTargetBinary(pcAddr); - if(binInfo != null) { - String localPath = binInfo.getTempBinaryPath(); - boolean isPieBuild = true; - if (binInfo.getType() != 1) { - isPieBuild = false; - } - functionName = SymbolManager.addr2func(localPath, pcStr, isPieBuild, - baseAddr); - } - if (null == functionName || functionName.isEmpty() - || functionName.equals("_end")) { //$NON-NLS-1$ - functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION; -// ApiNameManager.getApiId(functionName); - } else { - String prevFunctionName = functionName; - functionName = SymbolManager - .demanglingFunctionName(prevFunctionName); -// ApiNameManager.getApiId(functionName); - } - // need to be checked again - in case pid is not main application - symbol = callstackManager.getUserFunctionPosition( - sampleLog.getPid(), sampleLog.getTime()) - + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING - + functionName; - } else { - HashMap binInfoMap = BinarySettingManager - .getInstance().getTargetBinInfoMap(); -// List binPaths = new ArrayList(); -// binPaths.addAll(binInfoMap.keySet()); - - List libObjs = processInfo.getLibObjs(); -// HashMap libHash = processInfo -// .getLibObjHash(); - LibraryObject libraryObject = null; - int size = libObjs.size(); - for (int i = 0; i < size; i++) { -// String binPath = binPaths.get(i); - LibraryObject libObj = libObjs.get(i); -// if (null == libObj) { -// continue; -// } - long lowAddr = libObj.getLowestAddress(); - long highAddr = libObj.getHighestAddress(); - - /** for debug */ -/* if (lowAddr > pcAddr || highAddr < pcAddr) { - System.out.print(sampleLog.getId() - + "lib : " + libObj.getLibPath() + " ==> "); - AnalyzerUtil.printHexdecimal(lowAddr); - System.out.print(" < "); - AnalyzerUtil.printHexdecimal(pcAddr); - System.out.print(" < "); - AnalyzerUtil.printHexdecimal(highAddr); - System.out.println(); - } -*/ - if (pcAddr >= lowAddr && pcAddr <= highAddr) { - libraryObject = libObj; - break; - } - else { -// System.out.print(sampleLog.getId() -// + "lib : " + libObj.getLibPath() + " ==> "); -// AnalyzerUtil.printHexdecimal(lowAddr); -// System.out.print(" < "); -// AnalyzerUtil.printHexdecimal(pcAddr); -// System.out.print(" < "); -// AnalyzerUtil.printHexdecimal(highAddr); -// System.out.println(); - } - } - if (null != libraryObject) { - String path = libraryObject.getLibPath(); - BinaryInfo binInfo = binInfoMap.get(path); - if (null != binInfo) { - String localPath = binInfo.getTempBinaryPath(); - String baseAddr = Long.toString(libraryObject - .getLowestAddress()); - String pcStr = Long.toString(pcAddr); - boolean isPieBuild = true; - if (binInfo.getType() != 1) { - isPieBuild = false; - } - functionName = SymbolManager.addr2func(localPath, pcStr, - isPieBuild, baseAddr); - if (null == functionName || functionName.isEmpty() - || functionName.equals("_end")) { //$NON-NLS-1$ - functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION; -// ApiNameManager.getApiId(functionName); - } else { - String prevFunctionName = functionName; - functionName = SymbolManager - .demanglingFunctionName(prevFunctionName); -// ApiNameManager.getApiId(functionName); - } - // need to be checked again - in case pid is not main application - } else { - functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION; - } - symbol = path + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING - + functionName; - } else { - DA_LOG.debug("binary for the sample pc is not found :" + AnalyzerUtil.toHexdecimal(pcAddr)); //$NON-NLS-1$ - symbol = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_LIBRARY - + AnalyzerConstants.CALLSTACK_API_TOKEN_STRING - + AnalyzerUtil.toHexdecimal(pcAddr); -// + InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION; - } - } - - AnalyzerManager.getFuncNameMapByPid(sampleLog.getPid()) - .put(pcAddr, functionName); - return symbol; - } - + public void makeFunctionUsageProfileData(ProfileData sampleLog) { totalSampleCount++; List addrs = null; @@ -414,14 +278,15 @@ public class ProfileDataMaker { long callstackTime; Long longTime = null; CallStackData callstackData; - TreeMap seqByTimeMap = callstackManager.getSeqTimeByTidMap(tid); - HashMap addrMap = callstackManager + NavigableMap seqByTimeMap = callstackManager.getSeqTimeByTidMap(tid); + Map addrMap = callstackManager .getCallStackApiAddrByPidMap(pid); CallStackUnit callstackUnit = addrMap.get(selfAddr); if (null == callstackUnit) { CallStackUnit newCallstackUnit = new CallStackUnit(selfAddr, - getSamplePCSymbol(sampleLog), sampleLog); + callstackManager.getCallStackSymbol(selfAddr, pid, sampleTime), sampleLog); + callstackManager.offerCallStackUnit(newCallstackUnit); addrMap.put(selfAddr, newCallstackUnit); } @@ -460,7 +325,7 @@ public class ProfileDataMaker { addrs = makeCallstackHashAndList(sampleCallstack, sampleLog); } - HashMap addrMap = callstackManager + Map addrMap = callstackManager .getCallStackApiAddrByPidMap(pid); CallStackUnit inputData = addrMap.get(selfAddr); if (null == inputData) { @@ -510,10 +375,6 @@ public class ProfileDataMaker { } for (int i = 0; i < size; i++) { CallStackUnit callstackCsa = addrMap.get(addrs.get(i)); - // disable inclusive cpu time of dependent library - if (!callstackManager.checkUserCall(callstackCsa.getPath())) { - continue; - } if (callstackCsa.getFunctionName().equals( FunctionUsageProfiler.UNKNOWN)) { @@ -576,7 +437,7 @@ public class ProfileDataMaker { private List makeCallstackHashAndList(List callstackLog, LogData log) { int pid = log.getPid(); - HashMap addrMap = callstackManager + Map addrMap = callstackManager .getCallStackApiAddrByPidMap(pid); List addrs = new ArrayList(); int size = callstackLog.size(); @@ -604,6 +465,7 @@ public class ProfileDataMaker { String funcName = callstackLog.get(i + 1); CallStackUnit newCallstackUnit = new CallStackUnit(addr, funcName, log); + callstackManager.offerCallStackUnit(newCallstackUnit); addrMap.put(addr, newCallstackUnit); } } diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/ProfilingTable.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/ProfilingTable.java index 6b7ad3d..3455edd 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/ProfilingTable.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/summary/profiling/ProfilingTable.java @@ -288,17 +288,11 @@ public class ProfilingTable extends DATreeComposite { // INCLUSIVE // cpu time, cpu rate - if (inputType == AnalyzerConstants.FUPD_DEPENDENT_LIB) { - text.add(CommonConstants.DASH); - data.add(CommonConstants.ZERO); - text.add(CommonConstants.DASH); - data.add(CommonConstants.ZERO); - } else { - text.add(inTime); - data.add(profiler.getCpuTime(input, false)); - text.add(inRate + CommonConstants.SPACE + CommonConstants.PERCENT); - data.add(profiler.getCpuTime(input, false)); - } + text.add(inTime); + data.add(profiler.getCpuTime(input, false)); + text.add(inRate + CommonConstants.SPACE + CommonConstants.PERCENT); + data.add(profiler.getCpuTime(input, false)); + // elapsed time text.add(inExeTime); data.add(new Long(input.getElapsedTime())); diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/StopLogProcessor.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/StopLogProcessor.java index 5a64ed1..58624c5 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/StopLogProcessor.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/StopLogProcessor.java @@ -35,6 +35,7 @@ import org.tizen.dynamicanalyzer.logparser.LogParser; import org.tizen.dynamicanalyzer.project.Project; import org.tizen.dynamicanalyzer.sql.SqlManager; import org.tizen.dynamicanalyzer.swap.logparser.SWAPLogParser; +import org.tizen.dynamicanalyzer.ui.info.callstack.CallStackInserter; import org.tizen.dynamicanalyzer.ui.page.UpdateViewTimer; import org.tizen.dynamicanalyzer.util.DALogger; @@ -116,8 +117,9 @@ public class StopLogProcessor implements Runnable { SqlManager.getInstance().insertProcessInfo(); SqlManager.getInstance().saveLeakData(); SqlManager.getInstance().saveFailedData(); - SqlManager.getInstance().saveCallStackData(); - SqlManager.getInstance().saveCallStackUnits(); +// SqlManager.getInstance().saveCallStackData(); +// SqlManager.getInstance().saveCallStackUnits(); + CallStackInserter.getInstance().stopInserterThread(); SqlManager.getInstance().saveProfilingData(); SqlManager.getInstance().saveProfilingChildData(); SqlManager.getInstance().saveApiNames(); diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/configuration/ConfigurationDialogDataManager.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/configuration/ConfigurationDialogDataManager.java index da4afc6..e03fee2 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/configuration/ConfigurationDialogDataManager.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/configuration/ConfigurationDialogDataManager.java @@ -145,8 +145,8 @@ public class ConfigurationDialogDataManager { return optionalSettingName; } - public long getfeatureValue(String featues) { - long swapValue = featuresValueHashMap.get(featues).swapValue; + public long getfeatureValue(String features) { + long swapValue = featuresValueHashMap.get(features).swapValue; return swapValue; } @@ -199,14 +199,14 @@ public class ConfigurationDialogDataManager { } public String getOptionFeatureName(String featureName) { - String optionFeatusName = CommonConstants.EMPTY; + String optionFeaturesName = CommonConstants.EMPTY; if (featureName.equals(ConfigureLabels.SNAPSHOT_PERIODIC)) { - optionFeatusName = ConfigureLabels.SNAPSHOT_PERIODIC_AUTO; + optionFeaturesName = ConfigureLabels.SNAPSHOT_PERIODIC_AUTO; } else if (featureName.equals(ConfigureLabels.FEATURE_SCREENSHOT)) { - optionFeatusName = ConfigureLabels.SNAPSHOT_PERIODIC; + optionFeaturesName = ConfigureLabels.SNAPSHOT_PERIODIC; } else if (featureName .equals(ConfigureLabels.FEATURE_FUNCTION_PROFILING)) { - optionFeatusName = ConfigureLabels.FUNCTION_PROFILING_SAMPLING_PERIODIC; + optionFeaturesName = ConfigureLabels.FUNCTION_PROFILING_SAMPLING_PERIODIC; } else if (featureName.equals(ConfigureLabels.FEATURE_SYSTEM) || featureName.equals(ConfigureLabels.FEATURE_SYSTEM_CPU) || featureName.equals(ConfigureLabels.FEATURE_SYSTEM_PROCESSES) @@ -215,9 +215,9 @@ public class ConfigurationDialogDataManager { || featureName.equals(ConfigureLabels.FEATURE_SYSTEM_NETWORK) || featureName.equals(ConfigureLabels.FEATURE_SYSTEM_DEVICE) || featureName.equals(ConfigureLabels.FEATURE_SYSTEM_ENERGY)) { - optionFeatusName = ConfigureLabels.SYSTEM_INFOMATION_SAMPLING_PERIODIC; + optionFeaturesName = ConfigureLabels.SYSTEM_INFOMATION_SAMPLING_PERIODIC; } - return optionFeatusName; + return optionFeaturesName; } public void setFeaturesSwapValue(String featureName, boolean status) { @@ -509,8 +509,8 @@ public class ConfigurationDialogDataManager { return isChangeValue; } - public String isCheckFeatue(String featueName) { - if (AnalyzerConstants.FEATURE_OFF != getfeatureValue(featueName)) { + public String isCheckFeature(String featureName) { + if (AnalyzerConstants.FEATURE_OFF != getfeatureValue(featureName)) { return ConfigurationDialogFeaturesPage.ITEM_ALL_CHECKED; } else { return CommonConstants.EMPTY; diff --git a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/configuration/ConfigurationDialogFeaturesTable.java b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/configuration/ConfigurationDialogFeaturesTable.java index aa00e18..a0899ca 100644 --- a/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/configuration/ConfigurationDialogFeaturesTable.java +++ b/org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/toolbar/configuration/ConfigurationDialogFeaturesTable.java @@ -74,24 +74,24 @@ public class ConfigurationDialogFeaturesTable extends DATreeComposite { } } - private TreeInput makeInput(String featueName) { + private TreeInput makeInput(String featureName) { DATableDataFormat tableData = new DATableDataFormat(0); List text = new ArrayList(); - text.add(featueName); + text.add(featureName); String optionColumn = ConfigurationDialogDataManager.getInstance() - .isCheckFeatue(featueName); + .isCheckFeature(featureName); String parentFeatureName = ConfigurationDialogDataManager.getInstance() - .getParentFeatureName(featueName); + .getParentFeatureName(featureName); if (!parentFeatureName.equals(CommonConstants.EMPTY)) { optionColumn += (ConfigurationDialogFeaturesPage.ITEM_PARENT_FEATURE_NAME_ITEM + parentFeatureName); } String optionFeatureName = ConfigurationDialogDataManager.getInstance() - .getOptionFeatureName(featueName); + .getOptionFeatureName(featureName); if (!optionFeatureName.equals(CommonConstants.EMPTY) && ConfigurationDialogDataManager.getInstance() - .getParentFeatureName(featueName) + .getParentFeatureName(featureName) .equals(CommonConstants.EMPTY)) { optionColumn += (ConfigurationDialogFeaturesPage.FEATURE_OPTION_VALUE + ConfigurationDialogDataManager .getInstance().getOptionText(optionFeatureName)); -- 2.7.4