perfmon/src/perfmon_model.cpp
changeset 0 d6fe6244b863
child 11 4df3a095718c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/perfmon/src/perfmon_model.cpp	Tue Feb 02 00:17:27 2010 +0200
@@ -0,0 +1,951 @@
+/*
+* 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 FILES
+
+#include "perfmon_model.h"
+#include "perfmon_app.h"
+#include "perfmon_settingsviewdlg.h"
+#include "perfmon.hrh"
+#include "perfmon_valuescontainer.h"
+#include "perfmon_graphscontainer.h"
+#include "perfmon_datapopupcontainer.h"
+#include <perfmon.rsg>
+
+#include <coeutils.h>
+#include <bautils.h>
+#include <eikenv.h>
+#include <e32hal.h>
+#include <u32std.h>
+#include <s32file.h>
+#include <akntitle.h> 
+#include <eikspane.h>
+#include <aknnotewrappers.h>  
+
+_LIT(KAppName, "PerfMon");
+_LIT(KDefaultLogFilePath, "c:\\data\\PerfMon.log");
+
+const TInt KCalibrationLength = 2;
+const TInt KMinimumSamplesLength = 16;
+const TInt KCPUTimeMultiplier = 1000000; // used to avoid TReal conversions
+
+const TInt KSettingsDrive = EDriveC;
+_LIT(KSettingsFileName, "perfmon_settings.ini");
+
+
+// --------------------------------------------------------------------------------------------
+
+TInt CPULoadCount(TAny* aInt)
+	{
+	// increase the counter
+	(*(TUint*)aInt)++;
+	return 1;
+	}
+
+TInt CPULoadNOPThread(TAny* aParam)
+	{
+	CTrapCleanup* pC = CTrapCleanup::New();
+	CActiveScheduler* pS = new CActiveScheduler;
+	CActiveScheduler::Install(pS);
+
+	CIdle* idle = CIdle::NewL(CActive::EPriorityStandard);
+	TCallBack cb(CPULoadCount, aParam);
+	idle->Start(cb);
+
+	pS->Start();
+
+	delete idle;
+	delete pS;
+	delete pC;
+
+	return 0;
+	}
+
+// ===================================== MEMBER FUNCTIONS =====================================
+
+CPerfMonModel* CPerfMonModel::NewL()
+	{
+	CPerfMonModel* self = new(ELeave) CPerfMonModel;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+// --------------------------------------------------------------------------------------------
+
+CPerfMonModel::CPerfMonModel() : CActive(EPriorityUserInput)
+	{
+	}
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::ConstructL()
+	{
+	iDrawState = EDrawStateInvalid;
+	iCurrentCPUMode = ECPUModeNotSet;
+	iLogFileInitialized = EFalse;
+	
+    iEnv = CEikonEnv::Static();
+    User::LeaveIfError(iLs.Connect());
+
+    User::LeaveIfError(iTimer.CreateLocal());
+	CActiveScheduler::Add(this);
+	}
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::ActivateModelL()
+	{
+    // load settings
+    TRAP_IGNORE(LoadSettingsL());
+
+	// create data storages for the samples
+	CreateSamplesDataArrayL();
+	
+	// initialize the data popup container in top-right corner
+	iDataPopupContainer = new(ELeave) CPerfMonDataPopupContainer;
+	iDataPopupContainer->ConstructL(TRect(0,0,1,1));
+	
+	// set default modes
+	HandleSettingsChangeL();
+
+    // start sampling data immediately (jump to RunL)    
+    iTimer.After(iStatus, 100);
+    SetActive();
+	}
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::DeActivateModelL()
+	{
+	Cancel();
+	
+	DeActivateCPUMonitoring();
+
+	if (iDataPopupContainer)
+	    {
+	    delete iDataPopupContainer;
+	    iDataPopupContainer = NULL;
+	    }
+
+    // close log file
+	OpenLogFile(EFalse);
+	}
+	
+// --------------------------------------------------------------------------------------------
+
+CPerfMonModel::~CPerfMonModel()
+	{
+	iTimer.Close();
+
+    // clear data storages
+	if (iSampleEntryArray)
+	    {
+        for (TInt i=0; i<iSampleEntryArray->Count(); i++)
+            {
+            delete iSampleEntryArray->At(i).iSampleDataArray;
+            }
+	    
+	    delete iSampleEntryArray;
+	    }
+
+	    
+	iLs.Close();
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::DoCancel()
+	{
+    iTimer.Cancel();
+	}
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::RunL()
+	{
+	// calculate new values 
+	UpdateSamplesDataL();
+	
+	// log changes
+	AppendLatestSamplesToLogsL();
+	
+	// redraw views
+	SendDrawEventToContainersL();  
+
+    // continue
+    iTimer.After(iStatus, iSettings.iHeartBeat * 1000); // convert from milliseconds to microseconds
+    SetActive();
+	}
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::HandleSettingsChangeL()
+    {
+    // set priority of the thread
+    RThread().SetPriority(SettingItemToThreadPriority(iSettings.iPriority));
+    
+    // set visibility and location of the data popup
+    iDataPopupContainer->UpdateVisibility();
+    iDataPopupContainer->SetPositionAndSize();
+    
+    // init cpu monitor if setting has been changed
+    if (iCurrentCPUMode != iSettings.iCPUMode)
+        {
+        DeActivateCPUMonitoring();
+        ActivateCPUMonitoringL();
+        }
+    
+    // close log file
+    OpenLogFile(EFalse);
+    
+    // enable log file
+    if (iSettings.iLoggingEnabled && (iSettings.iLoggingMode == ELoggingModeLogFile || iSettings.iLoggingMode == ELoggingModeRDebugLogFile))
+        OpenLogFile(ETrue);
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::EnableLogging(TBool aEnable)
+    {
+    if (aEnable)
+        {
+        if (iSettings.iLoggingMode == ELoggingModeLogFile || iSettings.iLoggingMode == ELoggingModeRDebugLogFile)
+            OpenLogFile(ETrue);
+        
+        iSettings.iLoggingEnabled = ETrue;
+        }
+    else // disable
+        {
+        iSettings.iLoggingEnabled = EFalse;
+        OpenLogFile(EFalse);
+        }
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::OpenLogFile(TBool aOpen)
+    {
+    // open log file for writing
+    if (aOpen)
+        {
+        if (!iLogFileInitialized)
+            {
+            TInt err(KErrNone);
+            
+            // open the log file for writing
+            if (iLogFile.Open(iEnv->FsSession(), iSettings.iLoggingFilePath, EFileWrite) != KErrNone)
+                {
+                iEnv->FsSession().MkDirAll(iSettings.iLoggingFilePath);
+                err = iLogFile.Replace(iEnv->FsSession(), iSettings.iLoggingFilePath, EFileWrite);
+                }
+            else
+                {
+                // file opens correctly, seek to the end
+                TInt fileSize=0;
+                iLogFile.Size(fileSize);
+                err = iLogFile.Seek(ESeekCurrent, fileSize);
+                }
+            
+            if (err == KErrNone)
+                {
+                iLogFileInitialized = ETrue;
+                }
+            else
+                {
+                // show error
+                CAknErrorNote* note = new(ELeave) CAknErrorNote();
+                note->ExecuteLD(_L("Unable to create log file, check settings"));                
+                }
+            }        
+        }
+
+    // close handle to log file
+    else 
+        {
+        if (iLogFileInitialized)
+            {
+            iLogFile.Flush();
+            iLogFile.Close();
+            
+            iLogFileInitialized = EFalse;
+            }
+        }
+    }
+    
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::ActivateCPUMonitoringL()
+    {
+    // reset counter variables
+	iCPULoadCalibrating = ETrue;
+	iCPULoadCalibrationCounter = 0;
+	iCPULoadMaxValue = 999999999;
+	iCPULoadPreviousValue = 1;
+	iCPULoadCounter = 0;
+
+    // use null thread is cpu time is supported and the setting is on
+    if (CPUTimeSupported() && iSettings.iCPUMode == ECPUModeCPUTime) 
+        {
+        // try to open handle to null thread
+        if (OpenHandleToNullThread())
+            {
+            // handle is open, get initial value
+            TTimeIntervalMicroSeconds time;
+            iNullThread.GetCpuTime(time);
+            iCPULoadPreviousValue = time.Int64();
+            iPreviousTime.HomeTime();
+            
+            iCurrentCPUMode = ECPUModeCPUTime;
+            return; // cpu time is succesfully in use           
+            }
+        }
+
+    // otherwise use normal sampling with nops    
+    iCurrentCPUMode = ECPUModeNotSet;
+
+    // show a warning if cpu time cannot be taken in use
+    if (iSettings.iCPUMode == ECPUModeCPUTime)
+        {
+        CAknInformationNote* note = new(ELeave) CAknInformationNote();
+        note->ExecuteLD(_L("CPU Time not supported in this system, using NOPs sampling"));
+        }
+        
+    // create a thread for CPU load monitoring
+    User::LeaveIfError(iCPULoadThread.Create(_L("PerfMonCPULoad"), CPULoadNOPThread, 0x1000, 0x1000, 0x100000, &iCPULoadCounter));
+    iCPULoadThread.SetPriority(EPriorityLess);
+    iCPULoadThread.Resume();    
+    
+    iCurrentCPUMode = ECPUModeNOPs; // NOPs taken succesfully in use
+    }
+
+// --------------------------------------------------------------------------------------------
+
+TBool CPerfMonModel::OpenHandleToNullThread()
+    {
+    // find the kernel process and then the null thread
+    TFindProcess fp(_L("ekern.exe*"));
+    
+    TFullName kernelName;
+    if (fp.Next(kernelName) == KErrNone)
+        {
+        // process found, append null thread identifier
+        kernelName.Append(_L("::Null"));
+        
+        // find the thread
+        TFindThread ft(kernelName);
+
+        TFullName threadName;
+        if (ft.Next(threadName) == KErrNone)
+            {
+            // open instance to the thread
+            if (iNullThread.Open(threadName) != KErrNone)
+                return EFalse;                
+            }
+        }
+    
+    // process not found
+    else
+        return EFalse;
+    
+    // success!
+    return ETrue;        
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::DeActivateCPUMonitoring()
+    {
+    if (iCurrentCPUMode == ECPUModeCPUTime)
+        {
+        iNullThread.Close();
+        }
+    
+    else if (iCurrentCPUMode == ECPUModeNOPs)    
+        {
+        // kill the cpu load thread
+        iCPULoadThread.Kill(0);
+        iCPULoadThread.Close();        
+        } 
+    }
+
+// --------------------------------------------------------------------------------------------
+
+TBool CPerfMonModel::CPUTimeSupported()
+    {
+    TTimeIntervalMicroSeconds time;
+    TInt err = RThread().GetCpuTime(time);
+    
+    if (err == KErrNone && time.Int64() > 0)
+        return ETrue;
+    else
+        return EFalse;
+    }
+
+// --------------------------------------------------------------------------------------------
+
+TThreadPriority CPerfMonModel::SettingItemToThreadPriority(TInt aIndex)
+    {
+    TThreadPriority threadPriority = EPriorityNull;
+    
+    switch ( aIndex )
+        {
+        case EThreadPriorityTypeMuchLess:
+            {
+            threadPriority = EPriorityMuchLess; break;
+            }
+        case EThreadPriorityTypeLess:
+            {
+            threadPriority = EPriorityLess; break;
+            }
+        case EThreadPriorityTypeNormal:
+            {
+            threadPriority = EPriorityNormal; break;
+            }
+        case EThreadPriorityTypeMore:
+            {
+            threadPriority = EPriorityMore; break;
+            }
+        case EThreadPriorityTypeMuchMore:
+            {
+            threadPriority = EPriorityMuchMore; break;
+            }
+        case EThreadPriorityTypeRealTime:
+            {
+            threadPriority = EPriorityRealTime; break;
+            }
+        case EThreadPriorityTypeAbsoluteVeryLow:
+            {
+            threadPriority = EPriorityAbsoluteVeryLow; break;
+            }
+        case EThreadPriorityTypeAbsoluteLow:
+            {
+            threadPriority = EPriorityAbsoluteLow; break;
+            }
+        case EThreadPriorityTypeAbsoluteBackground:
+            {
+            threadPriority = EPriorityAbsoluteBackground; break;
+            }
+        case EThreadPriorityTypeAbsoluteForeground:
+            {
+            threadPriority = EPriorityAbsoluteForeground; break;
+            }
+        case EThreadPriorityTypeAbsoluteHigh:
+            {
+            threadPriority = EPriorityAbsoluteHigh; break;
+            }
+
+        default:
+            {
+            User::Panic(_L("Wrong tp index"), 276);
+            break;
+            }
+        }
+
+    return threadPriority;
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::CreateSamplesDataArrayL()
+    {
+    TInt maxSamples = iSettings.iMaxSamples >= KMinimumSamplesLength ? iSettings.iMaxSamples : KMinimumSamplesLength;
+
+    // create the data structure to store all samples
+    iSampleEntryArray = new(ELeave) CSampleEntryArray(16);
+
+    // add all source entries
+    for (TInt i=0; i<ESourcesLength; i++)
+        {
+        TSampleEntry newSampleEntry;
+        
+        if (i == ESourceCPU)
+            {
+            newSampleEntry.iDescription.Copy(_L("CPU"));
+            newSampleEntry.iUnitTypeShort.Copy(KNullDesC);
+            newSampleEntry.iUnitTypeLong.Copy(KNullDesC);
+            newSampleEntry.iDriveNumber = -1;
+            newSampleEntry.iGraphColor = KRgbYellow;            
+            }
+        
+        else if (i == ESourceRAM)
+            {
+            newSampleEntry.iDescription.Copy(_L("RAM"));
+            newSampleEntry.iUnitTypeShort.Copy(_L("b"));
+            newSampleEntry.iUnitTypeLong.Copy(_L("bytes"));
+            newSampleEntry.iDriveNumber = -1;
+            newSampleEntry.iGraphColor = KRgbGreen;            
+            }        
+        
+        else //drives
+            {
+            TChar driveLetter = 'C' + i-ESourceC; // C is the first drive
+
+            newSampleEntry.iDescription.Append(driveLetter);
+            newSampleEntry.iDescription.Append(_L(":"));
+            newSampleEntry.iUnitTypeShort.Copy(_L("b"));
+            newSampleEntry.iUnitTypeLong.Copy(_L("bytes"));
+            
+            iEnv->FsSession().CharToDrive(driveLetter, newSampleEntry.iDriveNumber);
+            
+            newSampleEntry.iGraphColor = KRgbCyan;
+            newSampleEntry.iGraphColor.SetGreen(255-(i-ESourceC)*30);
+            newSampleEntry.iGraphColor.SetRed(i*30);
+            }
+        
+        newSampleEntry.iSampleDataArray = new(ELeave) CSampleDataArray(maxSamples); 
+        
+        iSampleEntryArray->AppendL(newSampleEntry);        
+        }
+
+    // save current time as start time
+    iStartTime.HomeTime();
+    }
+	
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::UpdateSamplesDataL()
+    {
+    // reset inactivity timers
+    if (iSettings.iKeepBacklightOn)
+        User::ResetInactivityTime();
+   
+    // get current time
+    TTime currentTime;
+    currentTime.HomeTime();
+    
+    // calculate time difference
+    TTimeIntervalMicroSeconds timeDeltaFromPreviousSample = currentTime.MicroSecondsFrom(iPreviousTime);
+    
+    // remember current time as previous
+    iPreviousTime = currentTime;
+    
+    
+    // get CPU
+    TInt64 cpuLoadDelta(0);
+    TInt64 cpuLoadFree(0);
+    TInt64 cpuLoadSize(0);
+    TInt64 currentCPUValue(0);
+    
+    if (iCurrentCPUMode == ECPUModeCPUTime || iCurrentCPUMode == ECPUModeNOPs)
+        {
+        if (iCurrentCPUMode == ECPUModeCPUTime)
+            {
+            TTimeIntervalMicroSeconds time;
+            iNullThread.GetCpuTime(time);
+            currentCPUValue = time.Int64();
+            }
+        else if (iCurrentCPUMode == ECPUModeNOPs)
+            {
+            currentCPUValue = iCPULoadCounter;
+            }    
+            
+        // get delta and store the previous value
+        cpuLoadDelta = currentCPUValue - iCPULoadPreviousValue;
+        iCPULoadPreviousValue = currentCPUValue;
+        
+        // velocity = distance / time
+        cpuLoadFree = cpuLoadDelta * KCPUTimeMultiplier / timeDeltaFromPreviousSample.Int64();
+        
+
+        // detect maximum value
+        if (cpuLoadFree > iCPULoadMaxValue)
+            iCPULoadMaxValue = cpuLoadFree;
+     
+        
+        // check calibration status      
+    	if (iCPULoadCalibrating)
+    	    {
+    	    iCPULoadCalibrationCounter++;        
+            cpuLoadSize = cpuLoadFree;
+            
+            // check if need to calibrate anymore
+     	    if (iCPULoadCalibrationCounter > KCalibrationLength)
+    	        {
+    	        iCPULoadCalibrating = EFalse;
+    	        
+                // from the samples, get the minimum value, and let it be the max value 
+        		for (TInt i=0; i<iSampleEntryArray->At(0).iSampleDataArray->Count(); i++)
+        		    {
+        		    TInt64 newCPULoadMaxValue = iCPULoadMaxValue;
+        		    
+        		    if (iSampleEntryArray->At(0).iSampleDataArray->At(i).iFree < newCPULoadMaxValue)
+        		        {
+        		        newCPULoadMaxValue = iSampleEntryArray->At(0).iSampleDataArray->At(i).iFree;
+        		        }
+        		    
+        		    iCPULoadMaxValue = newCPULoadMaxValue;     		    
+        		    }	        
+    	        
+    	        // adjust priority of the poller thread
+                if (iCurrentCPUMode == ECPUModeNOPs)
+                    {
+                    iCPULoadThread.SetPriority(EPriorityAbsoluteVeryLow);
+                    }    	        
+    	        }
+
+    	    }
+    	else
+    	    {
+            cpuLoadSize = iCPULoadMaxValue;
+    	    }            
+        }
+
+	
+	// save cpu sample data    
+    TSampleData cpuSample;
+    cpuSample.iFree = cpuLoadFree;
+    cpuSample.iSize = cpuLoadSize;
+    cpuSample.iTimeFromStart = currentTime.MicroSecondsFrom(iStartTime);
+
+    iSampleEntryArray->At(0).iSampleDataArray->InsertL(0, cpuSample);
+    
+ 
+    
+    // get ram memory
+    TMemoryInfoV1Buf ramMemory;
+    UserHal::MemoryInfo(ramMemory);
+    
+    TSampleData memorySample;
+    memorySample.iFree = ramMemory().iFreeRamInBytes;
+    memorySample.iSize = ramMemory().iMaxFreeRamInBytes;
+    memorySample.iTimeFromStart = currentTime.MicroSecondsFrom(iStartTime);
+
+    iSampleEntryArray->At(1).iSampleDataArray->InsertL(0, memorySample); 
+    
+    
+    // all drives
+    for (TInt i=2; i<iSampleEntryArray->Count(); i++)
+        {
+        TSampleData driveSample;
+        
+        // get volume info from RFs
+        TVolumeInfo volumeInfo;
+        if (iEnv->FsSession().Volume(volumeInfo, iSampleEntryArray->At(i).iDriveNumber) == KErrNone)
+            {
+            driveSample.iFree = volumeInfo.iFree;
+            driveSample.iSize = volumeInfo.iSize;
+            }
+        else
+            {
+            driveSample.iFree = 0;
+            driveSample.iSize = 0;
+            }    
+
+        driveSample.iTimeFromStart = currentTime.MicroSecondsFrom(iStartTime);
+    
+        iSampleEntryArray->At(i).iSampleDataArray->InsertL(0, driveSample); 
+        }
+    
+    
+    // compress sample data arrays to save memory
+    TInt curLength(iSampleEntryArray->At(0).iSampleDataArray->Count());
+    
+    TInt maxSamples = iSettings.iMaxSamples >= KMinimumSamplesLength ? iSettings.iMaxSamples : KMinimumSamplesLength;
+    
+    if (curLength > maxSamples && curLength % 5 == 0)
+        {
+        for (TInt i=0; i<iSampleEntryArray->Count(); i++)
+            {
+            iSampleEntryArray->At(i).iSampleDataArray->ResizeL(maxSamples); // looses old samples
+            iSampleEntryArray->At(i).iSampleDataArray->Compress();
+            }         
+        }
+    }
+
+// --------------------------------------------------------------------------------------------
+    
+void CPerfMonModel::AppendLatestSamplesToLogsL()
+    {
+    if (iSettings.iLoggingEnabled && SampleEntryArray())
+        {
+        // loop all sources
+        for (TInt i=0; i<SampleEntryArray()->Count(); i++)
+            {
+            // check if this setting has been enabled and it has some data
+            if (iSettings.iLoggingSources.iSrcEnabled[i] && SampleEntryArray()->At(i).iSampleDataArray->Count() > 0)
+                {
+                // get current sample
+                TSampleData& currentSample = SampleEntryArray()->At(i).iSampleDataArray->At(0);
+                
+                TBuf<128> buf;
+                buf.Append(_L("PERFMON;"));
+                buf.Append(SampleEntryArray()->At(i).iDescription);
+                buf.Append(_L(";"));
+                buf.AppendNum(currentSample.iTimeFromStart.Int64());
+                buf.Append(_L(";"));
+                buf.AppendNum(currentSample.iFree);
+                buf.Append(_L(";"));
+                buf.AppendNum(currentSample.iSize);
+
+                // print to RDebug
+                if (iSettings.iLoggingMode == ELoggingModeRDebug || iSettings.iLoggingMode == ELoggingModeRDebugLogFile)
+                    {
+                    RDebug::Print(buf);
+                    }
+                
+                // print to log file
+                if (iSettings.iLoggingMode == ELoggingModeLogFile || iSettings.iLoggingMode == ELoggingModeRDebugLogFile)
+                    {
+                    buf.Append(_L("\r\n"));
+                    
+                    TBuf8<128> buf8;
+                    buf8.Copy(buf);
+                    
+                    iLogFile.Write(buf8);
+                    }        
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::SetValuesContainer(CPerfMonValuesContainer* aContainer)
+    {
+    iValuesContainer = aContainer;
+    iDrawState = EDrawStateValues;
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::SetGraphsContainer(CPerfMonGraphsContainer* aContainer)
+    {
+    iGraphsContainer = aContainer;
+    iDrawState = EDrawStateGraphs;
+    }
+    
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::SendDrawEventToContainersL()
+    {
+    if (iDrawState == EDrawStateValues && iValuesContainer)
+        iValuesContainer->DrawUpdate();
+    else if (iDrawState == EDrawStateGraphs && iGraphsContainer)
+        iGraphsContainer->DrawUpdate();
+           
+    if (iDataPopupContainer)
+        iDataPopupContainer->DrawUpdate();
+    }
+            
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::LoadSettingsL()
+    {
+    // set defaults
+    iSettings.iHeartBeat = 600;
+    iSettings.iMaxSamples = 64;
+    iSettings.iPriority = EThreadPriorityTypeNormal;
+    iSettings.iCPUMode = ECPUModeCPUTime;
+    iSettings.iKeepBacklightOn = ETrue;
+
+    iSettings.iDataPopupVisibility = EDataPopupVisbilityAlwaysOn;
+    iSettings.iDataPopupLocation = EDataPopupLocationTopRight;
+    iSettings.iDataPopupSources.SetDefaults1();
+
+    iSettings.iGraphsVerticalBarPeriod = 5;
+    iSettings.iGraphsSources.SetDefaults2();
+
+    iSettings.iLoggingMode = ELoggingModeRDebug;
+    iSettings.iLoggingFilePath.Copy(KDefaultLogFilePath);
+    iSettings.iLoggingSources.SetDefaults2();
+    
+    iSettings.iLoggingEnabled = EFalse;
+
+
+    // make sure that the private path of this app in c-drive exists
+    iEnv->FsSession().CreatePrivatePath( KSettingsDrive ); // c:\\private\\20011385\\
+    
+    // handle settings always in the private directory 
+    if (iEnv->FsSession().SetSessionToPrivate( KSettingsDrive ) == KErrNone)
+        {
+        // open or create a dictionary file store
+        CDictionaryFileStore* settingsStore = CDictionaryFileStore::OpenLC(iEnv->FsSession(), KSettingsFileName, KUidPerfMon);
+
+        LoadDFSValueL(settingsStore, KPMSettingHeartBeat,                   iSettings.iHeartBeat);
+        LoadDFSValueL(settingsStore, KPMSettingMaxSamples,                  iSettings.iMaxSamples);
+        LoadDFSValueL(settingsStore, KPMSettingPriority,                    iSettings.iPriority);
+        LoadDFSValueL(settingsStore, KPMSettingCPUMode,                     iSettings.iCPUMode);
+        LoadDFSValueL(settingsStore, KPMSettingKeepBackLightOn,             iSettings.iKeepBacklightOn);
+
+        LoadDFSValueL(settingsStore, KPMSettingDataPopupVisbility,          iSettings.iDataPopupVisibility);
+        LoadDFSValueL(settingsStore, KPMSettingDataPopupLocation,           iSettings.iDataPopupLocation);
+        LoadDFSValueL(settingsStore, KPMSettingDataPopupSources,            iSettings.iDataPopupSources);
+
+        LoadDFSValueL(settingsStore, KPMSettingGraphsVerticalBarPeriod,     iSettings.iGraphsVerticalBarPeriod);
+        LoadDFSValueL(settingsStore, KPMSettingGraphsSources,               iSettings.iGraphsSources);
+
+        LoadDFSValueL(settingsStore, KPMSettingLoggingMode,                 iSettings.iLoggingMode);
+        LoadDFSValueL(settingsStore, KPMSettingLoggingFilePath,             iSettings.iLoggingFilePath);
+        LoadDFSValueL(settingsStore, KPMSettingLoggingSources,              iSettings.iLoggingSources);
+
+        CleanupStack::PopAndDestroy(); // settingsStore         
+        }
+    }
+
+// --------------------------------------------------------------------------------------------
+
+void CPerfMonModel::SaveSettingsL()
+    {
+    // handle settings always in c:\\private\\20011385\\
+    if (iEnv->FsSession().SetSessionToPrivate( KSettingsDrive ) == KErrNone)
+        {
+        // delete existing store to make sure that it is clean and not eg corrupted
+        if (BaflUtils::FileExists(iEnv->FsSession(), KSettingsFileName))
+            {
+            iEnv->FsSession().Delete(KSettingsFileName);
+            }
+        
+        // create a dictionary file store
+        CDictionaryFileStore* settingsStore = CDictionaryFileStore::OpenLC(iEnv->FsSession(), KSettingsFileName, KUidPerfMon);
+
+        SaveDFSValueL(settingsStore, KPMSettingHeartBeat,                   iSettings.iHeartBeat);
+        SaveDFSValueL(settingsStore, KPMSettingMaxSamples,                  iSettings.iMaxSamples);
+        SaveDFSValueL(settingsStore, KPMSettingPriority,                    iSettings.iPriority);
+        SaveDFSValueL(settingsStore, KPMSettingCPUMode,                     iSettings.iCPUMode);
+        SaveDFSValueL(settingsStore, KPMSettingKeepBackLightOn,             iSettings.iKeepBacklightOn);
+
+        SaveDFSValueL(settingsStore, KPMSettingDataPopupVisbility,          iSettings.iDataPopupVisibility);
+        SaveDFSValueL(settingsStore, KPMSettingDataPopupLocation,           iSettings.iDataPopupLocation);
+        SaveDFSValueL(settingsStore, KPMSettingDataPopupSources,            iSettings.iDataPopupSources);
+
+        SaveDFSValueL(settingsStore, KPMSettingGraphsVerticalBarPeriod,     iSettings.iGraphsVerticalBarPeriod);
+        SaveDFSValueL(settingsStore, KPMSettingGraphsSources,               iSettings.iGraphsSources);
+
+        SaveDFSValueL(settingsStore, KPMSettingLoggingMode,                 iSettings.iLoggingMode);
+        SaveDFSValueL(settingsStore, KPMSettingLoggingFilePath,             iSettings.iLoggingFilePath);
+        SaveDFSValueL(settingsStore, KPMSettingLoggingSources,              iSettings.iLoggingSources);
+       
+        settingsStore->CommitL();
+        CleanupStack::PopAndDestroy(); // settingsStore             
+        }
+    }
+    	
+// --------------------------------------------------------------------------------------------
+
+TInt CPerfMonModel::LaunchSettingsDialogL()
+    {
+    // launch the settings dialog
+    TPerfMonSettings newSettings = iSettings;
+    
+    CPerfMonSettingsViewDlg* dlg = CPerfMonSettingsViewDlg::NewL(newSettings);
+    TInt returnValue = dlg->ExecuteLD(R_PERFMON_SETTINGS_DIALOG);
+    
+    // always save settings since the settings dialog does not provide a possibility to cancel
+    iSettings = newSettings;
+    SaveSettingsL();
+    HandleSettingsChangeL();
+
+    // make sure that the title of the application is correct
+    CEikStatusPane* sp = iEnv->AppUiFactory()->StatusPane();
+    CAknTitlePane* tp = static_cast<CAknTitlePane*>( sp->ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) );
+    tp->SetTextL(KAppName);
+    
+    return returnValue;
+    }
+	
+// ---------------------------------------------------------------------------
+
+void CPerfMonModel::LoadDFSValueL(CDictionaryFileStore* aDicFS, const TUid& aUid, TInt& aValue)
+    {
+    if (aDicFS->IsPresentL(aUid))
+        {
+        RDictionaryReadStream in;
+        in.OpenLC(*aDicFS, aUid);
+        aValue = in.ReadInt16L();
+        CleanupStack::PopAndDestroy(); // in        
+        }
+    }
+
+// ---------------------------------------------------------------------------
+
+void CPerfMonModel::LoadDFSValueL(CDictionaryFileStore* aDicFS, const TUid& aUid, TDes& aValue)
+    {
+    if (aDicFS->IsPresentL(aUid))
+        {
+        RDictionaryReadStream in;
+        in.OpenLC(*aDicFS, aUid);
+        TInt bufLength = in.ReadInt16L();   // get length of descriptor
+        in.ReadL(aValue, bufLength);        // get the descriptor itself
+        CleanupStack::PopAndDestroy(); // in
+        }
+    }
+
+// ---------------------------------------------------------------------------
+
+void CPerfMonModel::LoadDFSValueL(CDictionaryFileStore* aDicFS, const TUid& aUid, TPerfMonSources& aValue)
+    {
+    if (aDicFS->IsPresentL(aUid))
+        {
+        RDictionaryReadStream in;
+        in.OpenLC(*aDicFS, aUid);
+        TInt bufLength = in.ReadInt16L();   // get length of the array
+        
+        if (bufLength < 0 || bufLength > ESourcesLength)     // check for validaty
+            User::Leave(KErrNotSupported);
+        
+        for (TInt i=0; i<bufLength; i++)    // get all items
+            aValue.iSrcEnabled[i] = in.ReadInt16L();
+        
+        CleanupStack::PopAndDestroy(); // in
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+
+void CPerfMonModel::SaveDFSValueL(CDictionaryFileStore* aDicFS, const TUid& aUid, const TInt& aValue)
+    {
+    RDictionaryWriteStream out;
+    out.AssignLC(*aDicFS, aUid);
+    out.WriteInt16L(aValue);
+    out.CommitL(); 	
+    CleanupStack::PopAndDestroy(); // out
+    }
+
+// ---------------------------------------------------------------------------
+
+void CPerfMonModel::SaveDFSValueL(CDictionaryFileStore* aDicFS, const TUid& aUid, const TDes& aValue)
+    {
+    RDictionaryWriteStream out;
+    out.AssignLC(*aDicFS, aUid);
+    out.WriteInt16L(aValue.Length());       // write length of the descriptor
+    out.WriteL(aValue, aValue.Length());    // write the descriptor itself
+    out.CommitL(); 	
+    CleanupStack::PopAndDestroy(); // out
+    }
+
+// ---------------------------------------------------------------------------
+
+void CPerfMonModel::SaveDFSValueL(CDictionaryFileStore* aDicFS, const TUid& aUid, const TPerfMonSources& aValue)
+    {
+    RDictionaryWriteStream out;
+    out.AssignLC(*aDicFS, aUid);
+    
+    out.WriteInt16L(ESourcesLength);        // write length of the array
+    
+    for (TInt i=0; i<ESourcesLength; i++)   // write all items
+        out.WriteInt16L(aValue.iSrcEnabled[i]);
+    
+    out.CommitL(); 	
+    CleanupStack::PopAndDestroy(); // out
+    }
+    
+// ---------------------------------------------------------------------------
+    
+// End of File