memspyui/ui/hb/src/enginewrapper.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:15:20 +0300
branchRCL_3
changeset 21 b3cee849fa46
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* 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:
* 
*/

#include <QMessageBox>

#include <memspy/engine/memspyenginehelpersysmemtrackerconfig.h>

#include "enginewrapper.h"

// CONSTANTS

const QString OUTPUT_MODE = "output/mode";
const QString OUTPUT_PATH = "output/path";
const QString SWMT_PERIOD = "swmt/period";
const QString SWMT_MODE = "swmt/mode";
const QString SWMT_CATEGORIES = "swmt/categories";
const QString HEAP_DUMPS_MODE = "heapdumps/mode";

QString MemSpyProcess::exitInfo() const
{
    QChar exitType[] = {'K', 'T', 'P', 'R'};
    QString result = QString("[%1]").arg(exitType[mProcess->ExitType()]);
    
    if (mProcess->ExitType() != EExitKill && mProcess->ExitType() != EExitPending) {
        
        QString exitCategory = QString((QChar*) mProcess->ExitCategory().Ptr(), mProcess->ExitCategory().Length());
        result.append(QString(" %1-%2").arg(exitCategory).arg(mProcess->ExitReason()));
    }
    
    return result;
}


MemSpyDwoProgressTracker::MemSpyDwoProgressTracker(RMemSpySession &session) :
	CActive(EPriorityStandard), mSession(session)
{
	CActiveScheduler::Add(this);
}

MemSpyDwoProgressTracker::~MemSpyDwoProgressTracker()
{
	Cancel();
}

void MemSpyDwoProgressTracker::start()
{
	mSession.NotifyDeviceWideOperationProgress(mProgress, iStatus);
	
	SetActive();
}

void MemSpyDwoProgressTracker::cancel()
{
	Cancel();
}

// Event handler method.
 
void MemSpyDwoProgressTracker::RunL()
    {
 
    // If an error occurred handle it in RunError().
    User::LeaveIfError(iStatus.Int());
 
    // Resubmit the request immediately
    
    mSession.NotifyDeviceWideOperationProgress(mProgress, iStatus);
 
    SetActive();
 
    emit progress(mProgress.Progress(), QString((QChar*) mProgress.Description().Ptr(), mProgress.Description().Length()));
    }
 
void MemSpyDwoProgressTracker::DoCancel()
{ 
	// this is not yet implemented, as it is not required in current use cases
}
 
TInt MemSpyDwoProgressTracker::RunError(TInt aError)
{ 
	// KErrNotReady and KErrCancel errors are OK, they just notify 
	// us about the outstanding notification request that won't be 
	// processed.
	Q_UNUSED(aError);
	
    return KErrNone;
}

MemSpyDwoTracker::MemSpyDwoTracker(RMemSpySession &session, DeviceWideOperation operation) :
	CActive(EPriorityStandard), 
	mSession(session),
	mProgressTracker(new MemSpyDwoProgressTracker(session)),
	mOperation(operation)
{
	CActiveScheduler::Add(this);
	connect(mProgressTracker, SIGNAL(progress(int,QString)), this, SIGNAL(progress(int,QString)));
}

MemSpyDwoTracker::~MemSpyDwoTracker()
{
	Cancel();
	
	delete mProgressTracker;
}

void MemSpyDwoTracker::start()
{
	void (RMemSpySession::*functions[])(TRequestStatus&) = { 
			&RMemSpySession::OutputPhoneInfo,
			&RMemSpySession::OutputDetailedPhoneInfo,
			&RMemSpySession::OutputHeapInfo,
			&RMemSpySession::OutputCompactHeapInfo,
			&RMemSpySession::OutputHeapCellListing,
			&RMemSpySession::OutputHeapData,
			&RMemSpySession::OutputStackInfo,
			&RMemSpySession::OutputCompactStackInfo,
			&RMemSpySession::OutputUserStackData,
			&RMemSpySession::OutputKernelStackData };
	
	(mSession.*functions[mOperation])(iStatus);
	
	mProgressTracker->start();
	
	SetActive();
}

void MemSpyDwoTracker::cancel()
{
	Cancel();
}

// Event handler method.
 
void MemSpyDwoTracker::RunL()
    {
 
    // If an error occurred handle it in RunError().
    User::LeaveIfError(iStatus.Int());
 
    // Operation has finished successfully 
    emit finished(0);
    }
 
void MemSpyDwoTracker::DoCancel()
{
	// Cancel progress tracker
	mProgressTracker->cancel();
	
	mSession.CancelDeviceWideOperationL();
}
 
TInt MemSpyDwoTracker::RunError(TInt aError)
{ 
	// Emit the finished signal to notify user 
	// operation was canceled
	emit finished(aError);
	
    return KErrNone;
}

MemSpyAsyncTracker::MemSpyAsyncTracker(RMemSpySession& session, void (RMemSpySession::*function)(TRequestStatus&)) :
	CActive(EPriorityStandard), 
	mFunction(function),
	mSession(session)
{
	CActiveScheduler::Add(this);
}

void MemSpyAsyncTracker::RunL()
{ 
    // If an error occurred handle it in RunError().
    User::LeaveIfError(iStatus.Int());
 
    // Operation has finished successfully 
    emit finished(0);
}

void MemSpyAsyncTracker::DoCancel()
{
	// nothing to do here
}

TInt MemSpyAsyncTracker::RunError(TInt aError)
{ 
	// Emit the finished signal to notify user 
	// that operation was canceled
	emit finished(aError);
	
    return KErrNone;
}

void MemSpyAsyncTracker::start()
{
	(mSession.*mFunction)(iStatus);
	
	SetActive();
}

MemSpySettings::MemSpySettings() : 
	QSettings("Nokia", "MemSpy") 
{
}

OutputMode MemSpySettings::outputMode() const
{
	return static_cast<OutputMode>(value(OUTPUT_MODE, 0).toInt());
}

void MemSpySettings::setOutputMode(OutputMode mode)
{
	setValue(OUTPUT_MODE, mode);
}
	
QString MemSpySettings::outputPath() const
{
	return value(OUTPUT_PATH).toString();
}

void MemSpySettings::setOutputPath(const QString& path)
{
	setValue(OUTPUT_PATH, path);
}

int MemSpySettings::swmtTimerPeriod() const
{
	return value(SWMT_PERIOD, 30).toInt();
}

void MemSpySettings::setSwmtMode(SwmtMode mode)
{
	setValue(SWMT_MODE, mode);
}

SwmtMode MemSpySettings::swmtMode() const
{
	return static_cast<SwmtMode>(value(SWMT_MODE, 0).toInt());
}

void MemSpySettings::setSwmtTimerPeriod(int period)
{
	setValue(SWMT_PERIOD, period);
}


QVariantList MemSpySettings::swmtCategories() const
{
	return value(SWMT_CATEGORIES).toList();
}

void MemSpySettings::setSwmtCategories(const QVariantList& categories)
{
	setValue(SWMT_CATEGORIES, categories);
}

HeapDumpsMode MemSpySettings::heapDumpsMode() const
{
	return static_cast<HeapDumpsMode>(value(HEAP_DUMPS_MODE).toInt());
}

void MemSpySettings::setHeapDumpsMode(HeapDumpsMode mode)
{
	setValue(HEAP_DUMPS_MODE, mode);
}


EngineWrapper::EngineWrapper() :
	mSwmtRunning(false)
{
}

EngineWrapper::~EngineWrapper()
{
	mSession.Close();
}

bool EngineWrapper::initialize()
{
	return mSession.Connect() == KErrNone;
}

MemSpySettings& EngineWrapper::settings()
{
	return mSettings;
}

const MemSpySettings& EngineWrapper::settings() const
{
	return mSettings;
}



QList<MemSpyProcess*> EngineWrapper::getProcesses()
{
	QList<MemSpyProcess*> result;
	
	RArray<CMemSpyApiProcess*> proc;
	
	QT_TRAP_THROWING(mSession.GetProcessesL(proc));
	
	for (TInt i=0; i<proc.Count(); i++)
        result.append(new MemSpyProcess(proc[i]));
	
	return result;
}

QList<MemSpyThread*> EngineWrapper::getThreads(ProcessId processId)
{
	QList<MemSpyThread*> result;
	
	RArray<CMemSpyApiThread*> proc;
	
	QT_TRAP_THROWING(mSession.GetThreadsL(processId, proc));
	
    for (TInt i=0; i<proc.Count(); i++)
        result.append(new MemSpyThread(proc[i]));
	
	return result;
}

QList<MemSpyThreadInfoItem*> EngineWrapper::getThreadInfo(ThreadId threadId, ThreadInfoType type)
{
	QList<MemSpyThreadInfoItem*> result;
	RArray<CMemSpyApiThreadInfoItem*> threadInfo;
	qt_symbian_throwIfError(mSession.GetThreadInfoItems(threadInfo, threadId, 
			static_cast<TMemSpyThreadInfoItemType>(type)));
	
	for (TInt i=0; i<threadInfo.Count(); i++)
		result.append(new MemSpyThreadInfoItem(threadInfo[i]));
	
	return result;
}

void EngineWrapper::setThreadPriority(ThreadId threadId, ThreadPriority priority)
{
	TRAP_IGNORE(mSession.SetThreadPriorityL(threadId, priority));
}

QList<MemSpyKernelObjectType*> EngineWrapper::getKernelObjectTypes()
{
	QList<MemSpyKernelObjectType*> result;
		
	RArray<CMemSpyApiKernelObject*> types;
	qt_symbian_throwIfError(mSession.GetKernelObjects(types));
	
	for(TInt i=0; i<types.Count(); i++)
		result.append(new MemSpyKernelObjectType(types[i]));
	
	return result;
}

QList<MemSpyKernelObject*> EngineWrapper::getKernelObjects(int type)
{
	QList<MemSpyKernelObject*> result;
		
	RArray<CMemSpyApiKernelObjectItem*> objects;
	qt_symbian_throwIfError(mSession.GetKernelObjectItems(objects, 
			static_cast<TMemSpyDriverContainerType>(type)));
	
	for(TInt i=0; i<objects.Count(); i++)
		result.append(new MemSpyKernelObject(objects[i]));
	
	return result;
}

MemSpyDwoTracker* EngineWrapper::createDeviceWideOperation(DeviceWideOperation operation)
{
	return new MemSpyDwoTracker(mSession, operation);
}

MemSpyKernelHeapDumpTracker* EngineWrapper::createKernelHeapDumpTracker()
{
	return new MemSpyKernelHeapDumpTracker(mSession);
}

MemSpySwmtDumpTracker* EngineWrapper::createSwmtDumpTracker()
{
	return new MemSpySwmtDumpTracker(mSession);
}

void EngineWrapper::setSwmtSettings(SwmtMode mode, const QVariantList& categories)
{
	int bits = 0;
	bool heapDumps = false;
	switch (mode)
	{
	case SwmtModeBasic:
		bits = TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryUserHeap | 
			TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryUserStacks |
			TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryGlobalData |
			TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategorySystemMemory;
		
		break;
		
	case SwmtModeFull:
		bits = TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryAll;
		heapDumps = true;
		
		break;
		
	case SwmtModeCustom:
		bits = 0;
		// this needs to be in sync. with swmt view categories
		TMemSpyEngineHelperSysMemTrackerConfig::TMemSpyEngineSysMemTrackerCategories cats[] = {
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryFileServerCache,
            //TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryBitmapHandles,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryUserHeap,
            //TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryKernelHeap,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryLocalChunks,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryGlobalChunks,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryRAMDrive,
            //TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryUserStacks,
            //TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryGlobalData,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryRAMLoadedCode,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryKernelHandles,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryOpenFiles,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryDiskusage,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategorySystemMemory,
            TMemSpyEngineHelperSysMemTrackerConfig::EMemSpyEngineSysMemTrackerCategoryWindowGroups
		};

		foreach (const QVariant& bit, categories)
			bits |= cats[bit.toInt()];
		
		break;
	}
	
	TRAP_IGNORE(mSession.SetSwmtCategoriesL(bits));
	TRAP_IGNORE(mSession.SetSwmtHeapDumpsEnabledL(heapDumps));
}

bool EngineWrapper::isSwmtRunning()
{
	return mSwmtRunning;
}
	
void EngineWrapper::startSwmt(int period)
{
	mSwmtRunning = true;
	updateOutputSettings();
	TRAP_IGNORE(mSession.StartSwmtTimerL(period));
}

void EngineWrapper::stopSwmt()
{
	mSwmtRunning = false;
	TRAP_IGNORE(mSession.StopSwmtTimerL());
}

void EngineWrapper::forceSwmtDump()
{
	updateOutputSettings();	
	TRAP_IGNORE(mSession.ForceSwmtUpdateL());
}

void EngineWrapper::outputKernelHeapData()
{
	updateOutputSettings();
	TRAP_IGNORE(mSession.OutputKernelHeapDataL());
}

int EngineWrapper::outputThreadHeapData(const QString& filter)
{
	TPtrC customFilterDesc(static_cast<const TUint16*>(filter.utf16()), filter.length());
	
	TRAPD(err, mSession.OutputThreadHeapDataL(customFilterDesc));
	
	return err;
}

void EngineWrapper::updateOutputSettings()
{
	switch (mSettings.outputMode()) {
		case OutputModeTrace:
			TRAP_IGNORE(mSession.SwitchOutputToTraceL());
			break;
		
		case OutputModeFile:
		
			if (mSettings.outputPath().isEmpty()) {
				TRAP_IGNORE(mSession.SwitchOutputToFileL(KNullDesC));
			
			} else {
				
				QString root = mSettings.outputPath();
				TPtrC rootDesc (static_cast<const TUint16*>(root.utf16()), root.length());
			
				TRAP_IGNORE(mSession.SwitchOutputToFileL(rootDesc));
			}
	
	}
}