--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/engine/src/ProfilerEngine.cpp Tue May 25 14:22:58 2010 +0300
@@ -0,0 +1,1515 @@
+/*
+* 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 <e32cons.h>
+#include <e32base.h>
+#include <f32file.h>
+#include <c32comm.h>
+#include <s32file.h>
+#include <pathinfo.h>
+#include <s32mem.h>
+#include <bautils.h>
+#include <sysutil.h>
+#include <piprofiler/ProfilerConfig.h>
+#include "ProfilerEngine.h"
+#include <piprofiler/ProfilerTraces.h>
+
+// properties
+const TUid KEngineStatusPropertyCat={0x2001E5AD};
+enum TEnginePropertyKeys
+ {
+ EProfilerEngineStatus = 8,
+ EProfilerErrorStatus
+ };
+
+static _LIT_SECURITY_POLICY_PASS( KAllowAllPolicy );
+
+// CONSTANTS
+const TInt KStreamBufferSize = 32768;
+const TInt KSavedLineCount = 64;
+const TInt KFileNameBufSize = 128;
+// Use this UID if plugin belongs to DebOutWriterPlugin:
+const TUid KDebOutWriterPluginUid = { 0x2001E5BA };
+// Use this UID if plugin belongs to MmcOutWriterPlugin:
+const TUid KDiskWriterPluginUid = { 0x2001E5BB };
+
+// LITERALS
+_LIT8(KGenericTraceOutput, "output_type");
+_LIT8(KGenericTraceFilePrefix, "file_prefix");
+_LIT8(KGenericTraceFileSaveDrive, "save_file_location");
+_LIT8(KGenericTimedProfilingPeriod, "profiling_period");
+_LIT8(KEquals, "=");
+_LIT8(KNewLineSeparator, "\n");
+_LIT8(KProfilerVersionTag, "version");
+_LIT8(KEndMark, "[end]");
+_LIT8(KOutputToDebugOutput, "debug_output");
+
+/**
+ *
+ * The controller class used to provide the Profiler functions.
+ * This runs as a server in the engine thread
+ *
+ */
+class CPServer : public CServer2, public MProfilerController
+ {
+public:
+ static MProfilerController* NewL(TInt aPriority, MProfilerEngine& aEngine);
+
+private:
+ CPServer(TInt aPriority, MProfilerEngine& aEngine);
+ void Release();
+ CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
+
+public:
+ static TInt iClientCount;
+ };
+
+TInt CPServer::iClientCount = 0;
+
+// The session class used by the server controller
+class CPSession : public CSession2
+ {
+private:
+ inline const CPServer& Server() const;
+ void ServiceL(const RMessage2& aMessage);
+ };
+
+/*
+ *
+ * CProfiler class implementation
+ *
+ */
+// --------------------------------------------------------------------------------------------
+CProfiler* CProfiler::NewLC(const TDesC& aSettingsFile)
+ {
+ CProfiler* self = new(ELeave) CProfiler(aSettingsFile);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+// --------------------------------------------------------------------------------------------
+CProfiler::CProfiler(const TDesC& aSettingsFile) :
+ iSettingsFileLocation(aSettingsFile)
+ {
+ // define property for Profiler Engine status, UI may read it for control purposes
+ if ( RProperty::Define(KEngineStatusPropertyCat,
+ EProfilerEngineStatus,
+ RProperty::EInt,
+ KAllowAllPolicy,
+ KAllowAllPolicy,
+ 0) != KErrAlreadyExists )
+ {
+ LOGTEXT(_L("CProfiler::CProfiler - status property already defined"));
+ }
+
+ if ( RProperty::Define(KEngineStatusPropertyCat,
+ EProfilerErrorStatus,
+ RProperty::EInt,
+ KAllowAllPolicy,
+ KAllowAllPolicy,
+ 0) != KErrAlreadyExists )
+ {
+ LOGTEXT(_L("CProfiler::CProfiler - status property already defined"));
+ }
+
+ // attach to own property
+ iEngineStatus.Attach(KEngineStatusPropertyCat, EProfilerEngineStatus);
+ // set status idle
+ iEngineStatus.Set(KEngineStatusPropertyCat, EProfilerEngineStatus, RProfiler::EIdle);
+
+ // attach to own property
+ iUpdateStatus.Attach(KEngineStatusPropertyCat, EProfilerErrorStatus);
+ // set status idle
+ iUpdateStatus.Set(KEngineStatusPropertyCat, EProfilerErrorStatus, EFalse);
+ }
+
+// --------------------------------------------------------------------------------------------
+CProfiler::~CProfiler()
+ {
+ LOGTEXT(_L("CProfiler::~CProfiler - Enter"));
+
+ // delete error checker
+ if(iErrorChecker)
+ {
+ iErrorChecker->Cancel();
+ delete iErrorChecker;
+ iErrorChecker = NULL;
+ }
+
+ // delete settings array
+ if(iDefaultSamplerAttributesArray)
+ {
+ iDefaultSamplerAttributesArray->Reset();
+ delete iDefaultSamplerAttributesArray;
+ iDefaultSamplerAttributesArray = NULL;
+ }
+
+ // delete settings file raw line array
+ if(iSavedLineArray)
+ {
+ iSavedLineArray->Reset();
+ delete iSavedLineArray;
+ iSavedLineArray = NULL;
+ }
+
+ // delete sampler controller, cleans up the sampler plugin instances
+ if(iSamplerHandler)
+ {
+ delete iSamplerHandler;
+ iSamplerHandler = NULL;
+ }
+ // delete writer controller, cleans up the writer plugin instances
+ if(iWriterHandler)
+ {
+ delete iWriterHandler;
+ iWriterHandler = NULL;
+ }
+
+ // delete user side sampler stream
+ if(iUserStream)
+ {
+ delete iUserStream;
+ iUserStream = NULL;
+ }
+
+ // close engine status property
+ iEngineStatus.Close();
+ if (RProperty::Delete(KEngineStatusPropertyCat, EProfilerEngineStatus) != KErrNotFound)
+ {
+ LOGTEXT(_L("CProfiler::~CProfiler - cannot close status property"));
+ }
+ // close engine update property
+ iUpdateStatus.Close();
+ if (RProperty::Delete(KEngineStatusPropertyCat, EProfilerErrorStatus) != KErrNotFound)
+ {
+ LOGTEXT(_L("CProfiler::~CProfiler - cannot close update property"));
+ }
+
+ // close server process
+ if (iServer)
+ {
+ LOGTEXT(_L("CProfiler::~CProfiler - Releasing server"));
+ iServer->Release();
+ }
+
+ if( iTimer )
+ {
+ iTimer->Cancel();
+ delete iTimer;
+ iTimer = 0;
+ }
+
+ LOGTEXT(_L("CProfiler::~CProfiler - Finished"));
+ }
+
+// --------------------------------------------------------------------------------------------
+void CProfiler::ConstructL()
+ {
+ LOGTEXT(_L("CProfiler::ConstructL - Enter"));
+ TInt err(0);
+ TLex lex;
+
+ if ( iSettingsFileLocation.CompareF(KNullDesC) != 0 )
+ {
+ lex=(iSettingsFileLocation);
+ // parse the first command line argument, the command itself
+ lex.Mark();
+ lex.SkipCharacters();
+ if(lex.TokenLength() != 0)
+ {
+ // there is another item in the list
+ TPtrC filename = lex.MarkedToken();
+ LOGSTRING2("filename %S", &filename);
+ lex.SkipSpace();
+ lex.Mark();
+ lex.SkipCharacters();
+ if(lex.TokenLength() != 0)
+ {
+ TPtrC boot = lex.MarkedToken();
+ LOGTEXT(_L("boot mode"));
+ }
+ }
+ }
+
+ // create new sampler stream instance
+ iUserStream = CProfilerSampleStream::NewL(KStreamBufferSize);
+ if(!iUserStream)
+ {
+ LOGTEXT(_L("Profiler engine cannot reserve memory"));
+ User::Leave(KErrCancel); // operation cancelled
+ }
+
+ // engine status checker
+ iErrorChecker = CProfilerErrorChecker::NewL();
+ iErrorChecker->SetObserver(this);
+
+ // create and initiate plug-in controller instances
+ iSamplerHandler = CSamplerController::NewL(*iUserStream);
+ iWriterHandler = CWriterController::NewL(*iUserStream);
+
+ iWriterHandler->InitialiseWriterListL();
+
+ // set engine as an observer to sampler controller to get the notification of plugin load has ended
+ iSamplerHandler->SetObserver(this);
+
+ // default settings from sampler plugins, maximum 20 sampler plugins
+ iDefaultSamplerAttributesArray = new(ELeave) CArrayFixFlat<TSamplerAttributes>(20);
+
+ // set profiler status to initializing
+ iState = RProfiler::EInitializing;
+ iEngineStatus.Set(RProfiler::EInitializing);
+
+ // set default general settings, will be overdriven if changed in settings file
+ iGeneralAttributes.iTraceOutput.Copy(KDefaultTraceOutput);
+ iGeneralAttributes.iTraceFilePrefix.Copy(KDefaultTraceFilePrefix);
+ iGeneralAttributes.iSaveFileDrive.Copy(KDefaultTraceFileSaveDrive);
+ iGeneralAttributes.iTimedSamplingPeriod = KDefaultTimedSamplingPeriod;
+
+ RThread me;
+
+ me.SetPriority(EPriorityRealTime);
+
+ err = KErrGeneral;
+ TInt count = 0;
+
+ while(err != KErrNone && count < 30)
+ {
+ err = User::RenameThread(KProfilerName);
+ if(err != KErrNone)
+ {
+ LOGSTRING2("CProfiler: error renaming the thread, err %d", err);
+ User::Leave(err);
+ }
+ else break;
+ }
+
+ // set settings file loading preferences
+ iSettingsFileLoaded = EFalse;
+
+ // change status property to idle since initialization successfull
+ iState = RProfiler::EIdle;
+ if( iEngineStatus.Set((TInt)RProfiler::EIdle) != KErrNone )
+ {
+ LOGTEXT(_L("CProfiler::ConstructL - engine status property change failed"));
+ }
+
+ if( iUpdateStatus.Set(EFalse) != KErrNone )
+ {
+ LOGTEXT(_L("CProfiler::ConstructL - engine status property change failed"));
+ }
+
+ // create a server instance for clients to communicate with
+ iServer = CPServer::NewL(10,*this);
+
+ // close the handle
+ me.Close();
+
+ iTimer = CProfilerTimer::NewL(CActive::EPriorityStandard, *this);
+
+ LOGTEXT(_L("CProfiler::ConstructL - Exit"));
+
+ }
+
+CProfilerSampleStream* CProfiler::GetSamplerStream()
+ {
+ return iUserStream;
+ }
+
+void CProfiler::HandleSamplerControllerReadyL()
+ {
+ // load settings
+ // check if settings file already loaded
+ if(!iSettingsFileLoaded)
+ {
+ // load default settings file
+ LoadSettingsL();
+
+ iSettingsFileLoaded = ETrue;
+ }
+
+ // notify engine's launcher(UI or PIProfilerLauncher) to continue launch
+ RProcess::Rendezvous(KErrNone);
+ }
+
+void CProfiler::NotifyRequesterForSettingsUpdate()
+ {
+ // set update status P&S property true => update needed on UI side
+ iUpdateStatus.Set(ETrue);
+ }
+
+void CProfiler::HandleProfilerErrorChangeL(TInt aError)
+ {
+ LOGSTRING2("CProfiler::HandleProfilerErrorChangeL() - error received, %d", aError);
+
+ // check if profiler running
+ if(iState == RProfiler::ERunning)
+ {
+ // stop profiler if error occurred during the trace
+ iEngineStatus.Set(aError);
+
+ // stop samplers, NOTE! Writer plugins not stopped since
+ iSamplerHandler->StopSamplerPlugins();
+
+ // stop debug output plugin and write the rest of the trace data to output
+ if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0)
+ {
+ // write the rest of trace data only if debug output selected
+ iWriterHandler->StopSelectedPlugin();
+ }
+ LOGSTRING2("CProfiler::HandleProfilerErrorChangeL - sampling stopped, going to state %d", RProfiler::EIdle);
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Gets a value from settings file for certain attribute.
+// ----------------------------------------------------------------------------
+void CProfiler::DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TDes8& aValue)
+ {
+ LOGTEXT(_L("CProfiler::DoGetValueFromSettingsFile()"));
+ _LIT8(KSettingItemSeparator, "=");
+
+ // read a line of given array
+ for (TInt i=0; i<aLineArray->MdcaCount(); i++)
+ {
+ // check if this line has a separator
+ TInt sepPos = aLineArray->MdcaPoint(i).Find(KSettingItemSeparator);
+ if (sepPos > 0)
+ {
+ // check that the element matches
+ if (aLineArray->MdcaPoint(i).Left(sepPos).CompareF(aAttribute) == 0)
+ {
+ // get the value
+ aValue.Copy(aLineArray->MdcaPoint(i).Right(aLineArray->MdcaPoint(i).Length()-sepPos-1));
+ break;
+ }
+ }
+ }
+ }
+
+void CProfiler::DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TInt& aValue)
+ {
+ LOGTEXT(_L("CProfiler::DoGetValueFromSettingsFile()"));
+ _LIT8(KSettingItemSeparator, "=");
+
+ // read a line of given array
+ for (TInt i=0; i<aLineArray->MdcaCount(); i++)
+ {
+ // check if this line has a separator
+ TInt sepPos = aLineArray->MdcaPoint(i).Find(KSettingItemSeparator);
+ if (sepPos > 0)
+ {
+ // check that the element matches
+ if (aLineArray->MdcaPoint(i).Left(sepPos).CompareF(aAttribute) == 0)
+ {
+ // get the value
+ TLex8 parser(aLineArray->MdcaPoint(i).Right(aLineArray->MdcaPoint(i).Length()-sepPos-1));
+ parser.Val(aValue);
+ break;
+ }
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------------------------
+TInt CProfiler::GetSamplerAttributesL(const RMessage2& aMessage)
+ {
+ TInt err(KErrNone);
+ TInt pos(0);
+
+ // get sampler count
+ TInt count(iDefaultSamplerAttributesArray->Count());
+
+ // write each of the default sampler plugin setting attributes over client-server session
+ for (TInt i(0); i<count; ++i)
+ {
+ TSamplerAttributes attr = iDefaultSamplerAttributesArray->At(i);
+ TPckgC<TSamplerAttributes> attrPckg(attr);
+
+ // write a TSamplerAttributes container at a time
+ aMessage.WriteL(0, attrPckg, pos);
+ pos += attrPckg.Length();
+ }
+
+ aMessage.Complete(err);
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+TInt CProfiler::SetSamplerAttributesL(const RMessage2& aMessage)
+ {
+ TSamplerAttributes attr;
+ TPckg<TSamplerAttributes> inAttr(attr);
+
+ TInt err = aMessage.Read(0, inAttr, 0);
+
+ // apply the changes directly to a plugin
+ iSamplerHandler->SetSamplerSettingsL(attr.iUid, attr);
+
+ aMessage.Complete(err);
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+TInt CProfiler::GetGeneralAttributesL(const RMessage2& aMessage)
+ {
+ TPckgBuf<TGeneralAttributes> generalSettings( iGeneralAttributes );
+
+ // write general attributes over client-server session
+ TInt err = aMessage.Write(0, generalSettings);
+
+ aMessage.Complete(err);
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+TInt CProfiler::SetGeneralAttributesL(const RMessage2& aMessage)
+ {
+ // read the general settings from message
+ TGeneralAttributes attr;
+ TPckg<TGeneralAttributes> inPckg(attr);
+ TInt err = aMessage.Read(0, inPckg, 0);
+
+ // copy to the general attributes
+ iGeneralAttributes.iSaveFileDrive.Copy(attr.iSaveFileDrive);
+ iGeneralAttributes.iTraceFilePrefix.Copy(attr.iTraceFilePrefix);
+ iGeneralAttributes.iTraceOutput.Copy(attr.iTraceOutput);
+ iGeneralAttributes.iTimedSamplingPeriod = attr.iTimedSamplingPeriod;
+
+ aMessage.Complete(err);
+ return err;
+ }
+
+TInt CProfiler::GetSamplerAttributeCountL(const RMessage2& aMessage)
+ {
+ // get the plugin array count and wrap it to TPckgBuf<>
+ TPckgBuf<TInt> attributeCount(iDefaultSamplerAttributesArray->Count());
+
+ // write general attributes over client-server session
+ TInt err = aMessage.Write(0, attributeCount);
+
+ aMessage.Complete(err);
+ return err;
+ }
+
+TInt CProfiler::RefreshStatus(const RMessage2& aMessage)
+ {
+ TInt err(KErrNone);
+
+ // update profiler status for requester
+ iEngineStatus.Set(iState);
+
+ aMessage.Complete(err);
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+TInt CProfiler::LoadSettingsL(/*const TDesC& configFile*/)
+ {
+ RFs fileServer;
+ RFile file;
+ TInt err(KErrNone);
+
+ // connect to file server
+ err = fileServer.Connect();
+
+ // check if file server can be connected
+ if (err != KErrNone)
+ {
+ // file server couldn't be connected
+ return KErrGeneral;
+ }
+
+ // check if settings file location length reasonable
+ if ( iSettingsFileLocation.CompareF(KNullDesC) == 0 )
+ {
+ // open the file with the default path and name
+ TBuf<256> pathAndName;
+ pathAndName.Append(PathInfo::PhoneMemoryRootPath());
+ pathAndName.Append(KProfilerSettingsFileName);
+ iSettingsFileLocation.Copy(pathAndName);
+ LOGTEXT(_L("CProfiler::LoadSettings - Opening settings file with name (with the default path)"));
+ LOGTEXT(pathAndName);
+ }
+
+ // open the file with the given path and name
+ err = file.Open(fileServer,iSettingsFileLocation,EFileRead);
+
+
+ // check if RFile::Open() returned error
+ if (err != KErrNone)
+ {
+ // file couldn't be opened
+ LOGTEXT(_L("CProfiler::LoadSettings - Failed to open settings, using default"));
+
+ // check if settings already loaded
+ if(iDefaultSamplerAttributesArray->Count() > 0)
+ {
+ // reset default settings array
+ iDefaultSamplerAttributesArray->Reset();
+ }
+
+ // load default settings, instead of settings file ones
+ iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray);
+
+ fileServer.Close();
+ return KErrNone;
+ }
+
+ // initialize iSavedLineArray, initial settings file lines 64
+ if(iSavedLineArray)
+ {
+ iSavedLineArray->Reset();
+ }
+ else
+ {
+ iSavedLineArray = new (ELeave) CDesC8ArrayFlat(KSavedLineCount);
+ }
+
+ iSavedLinesCount = KSavedLineCount;
+
+ // get size of the file
+ TInt fileSize(0);
+ err = file.Size(fileSize);
+ // check if an error occurred reading the file size
+ if(err != KErrNone)
+ {
+ return KErrGeneral; // could not find the size
+ }
+
+ // sanity check for the file size
+ if (fileSize < 3 || fileSize > 20000)
+ {
+ fileSize = KSettingsFileSize;
+ return KErrNotSupported;
+ }
+
+ // read the contents of the file to buffer.
+ iSettingsBuffer.Zero();
+ file.Read(iSettingsBuffer, fileSize);
+ file.Close();
+ fileServer.Close();
+ LOGSTRING2("CProfiler::LoadSettings: read %d bytes",iSettingsBuffer.Length());
+
+ // append end mark "[end]"
+ iSettingsBuffer.Append(KEndMark);
+ // force an ending newline
+ iSettingsBuffer.Append('\n');
+
+ // next fill the saved settings array (CDesC8ArrayFlat) for further comparison with changes and default values
+ TBuf8<384> tmpBuf;
+ TInt lineCount(0);
+ TBool commentFound(EFalse);
+ for (TInt i(0); i<iSettingsBuffer.Length(); i++) // loop all chars
+ {
+ // if new line char found, create a new text line
+ if (iSettingsBuffer[i]=='\r' || iSettingsBuffer[i]=='\n')
+ {
+ // check if collected string has reasonable length
+ if (tmpBuf.Length() > 0)
+ {
+ // remove extra spaces
+ tmpBuf.TrimAll();
+ // check if the size of the array too small
+ if(lineCount >= iSavedLinesCount)
+ {
+ iSavedLineArray->ExpandL(20); // expand by 20 lines
+ iSavedLinesCount += 20;
+ }
+ iSavedLineArray->AppendL(tmpBuf);
+ tmpBuf.Copy(KNullDesC8);
+ lineCount++;
+ }
+ commentFound = EFalse;
+ }
+ // check if comment mark ';' is found on the line, skip the rest of the line
+ else if(iSettingsBuffer[i]==';')
+ {
+ commentFound = ETrue;
+ }
+ // otherwise append a char to the temp line buffer if it is a wanted ASCII char
+ else if (iSettingsBuffer[i]>=32 && iSettingsBuffer[i]<=127 && !commentFound)
+ {
+ tmpBuf.Append(iSettingsBuffer[i]);
+ }
+ }
+
+ // empty tmpBuf
+ tmpBuf.Copy(KNullDesC8);
+ // check settings file version
+ DoGetValueFromSettingsArray(iSavedLineArray, KProfilerVersionTag, tmpBuf);
+
+ TBuf8<32> version;
+ version.Copy(PROFILER_VERSION_SHORT);
+
+ // check if settings file version is
+ if(tmpBuf.CompareF(version) >= 0)
+ {
+ // update general attributes
+ UpdateSavedGeneralAttributes(iSavedLineArray);
+
+ // update settings to sampler plugins and save the attributes to default array
+ iSamplerHandler->UpdateSavedSamplerAttributesL(iSavedLineArray, iDefaultSamplerAttributesArray);
+ }
+ else
+ {
+ // check if settings already loaded
+ if(iDefaultSamplerAttributesArray)
+ {
+ // reset default settings array
+ iDefaultSamplerAttributesArray->Reset();
+
+ // get the default settings if settings file version too old
+ iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray);
+ }
+ }
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+void CProfiler::UpdateSavedGeneralAttributes(CDesC8ArrayFlat* aSavedAttributes)
+ {
+ // get saved general settings
+ DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceOutput, iGeneralAttributes.iTraceOutput);
+ DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceFilePrefix, iGeneralAttributes.iTraceFilePrefix);
+ DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceFileSaveDrive, iGeneralAttributes.iSaveFileDrive);
+ DoGetValueFromSettingsArray(aSavedAttributes, KGenericTimedProfilingPeriod, iGeneralAttributes.iTimedSamplingPeriod);
+ }
+
+TBool CProfiler::CheckLocationSanity(RFs& fs, const TDesC8& aLocation)
+ {
+ TBool ret(EFalse);
+ TBool noDiskSpace(EFalse);
+ TBuf<32> drive;
+
+ CnvUtfConverter::ConvertToUnicodeFromUtf8(drive, aLocation);
+ TDriveUnit driveUnit = TDriveUnit(drive);
+
+ // check that the root folder is correct
+ if (drive.Length() > 2 && BaflUtils::CheckFolder(fs, drive.Left(3)) == KErrNone)
+ {
+ // test available disk space
+ TRAP_IGNORE((noDiskSpace = SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, driveUnit)));
+ if(!noDiskSpace)
+ ret = ETrue;
+ }
+
+ return ret;
+ }
+
+TInt CProfiler::HandleGeneralSettingsChange()
+ {
+ // local literals
+ _LIT8(KBackSlash, "\\");
+ _LIT8(KTraceFileExtension, ".dat");
+
+ TBuf8<KFileNameBufSize> fileNameBuf;
+ TBuf8<10> number;
+ TInt result(0);
+ TInt index(1);
+ TInt hashLocation(0);
+ TParse parse;
+
+ // check if plugin writer changed
+ if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0)
+ {
+ iWriterHandler->SetPluginActive( KDebOutWriterPluginUid, EWriterPluginEnabled );
+ }
+ else
+ {
+ RFs fileServer;
+ RFile file;
+
+ // connect to the file server
+ result = fileServer.Connect();
+ if(result == KErrNone)
+ {
+ // disk writer plugin will be activated
+ iWriterHandler->SetPluginActive( KDiskWriterPluginUid, EWriterPluginEnabled );
+
+ // fix the trace data file location as well
+ iTotalPrefix.Zero();
+ iTotalPrefix.Append(iGeneralAttributes.iSaveFileDrive);
+
+ // check that trace file location sane
+ if(!CProfiler::CheckLocationSanity(fileServer, iTotalPrefix))
+ {
+ fileServer.Close();
+ return KErrPathNotFound;
+ }
+
+ // remove extra spaces
+ iTotalPrefix.TrimAll();
+
+ // check the directory contains a trailing backlash
+ if(iTotalPrefix.Right(1) != _L8("\\") &&
+ iTotalPrefix.Right(1) != _L8("/"))
+ {
+ // append backslash to end
+ iTotalPrefix.Append(KBackSlash);
+ }
+
+ // append trace file name prefix e.g. PIProfiler_#
+ iTotalPrefix.Append(iGeneralAttributes.iTraceFilePrefix);
+
+ // locate '#' mark for finding the next free trace file name, e.g. E:\data\PIProfiler_4.dat
+ hashLocation = iTotalPrefix.Locate('#');
+ if( hashLocation == KErrNotFound )
+ {
+ // append simply at the end of the trace file prefix, no need to inform user
+ iTotalPrefix.Append('#');
+ // get new hash mark location
+ hashLocation = iTotalPrefix.Locate('#');
+ }
+
+ // add the file extension
+ iTotalPrefix.Append(KTraceFileExtension);
+
+ // search for files with different indices
+ // until a free filename is found
+ while(result != KErrNotFound)
+ {
+ fileNameBuf.Zero();
+ // start with the original prefix
+ fileNameBuf.Append(iTotalPrefix);
+ // convert the number to a descriptor
+ number.Num(index);
+ // replace the hashmark with the real number
+ fileNameBuf.Replace(hashLocation,1,number);
+
+ // make a copy to the iFileNameStream descriptor
+ iFileNameStream.Zero();
+ CnvUtfConverter::ConvertToUnicodeFromUtf8(iFileNameStream, fileNameBuf);
+
+ LOGSTRING2("CProfiler::HandleGeneralSettingsChange() - trying to open files %S ",&iFileNameStream);
+
+ if((result = parse.Set(iFileNameStream, NULL, NULL)) != KErrNone)
+ {
+ // break loop if fails, problems in file name => change to log into debug output
+ break;
+ }
+
+ // create directory for trace files if not exists
+ result = fileServer.MkDirAll(parse.FullName());
+
+ // check that file server responded with KErrNone or KErrAlreadyExists
+ if( result != KErrNone && result != KErrAlreadyExists)
+ {
+ // if some other result, e.g. memory full => break
+ break;
+ }
+
+ // attempt opening the file
+ result = file.Open(fileServer,parse.FullName(),EFileShareReadersOnly);
+ if(result != KErrNotFound)
+ {
+ if( result != KErrNotReady &&
+ result != KErrServerBusy )
+ {
+ // close the file if it could be opened
+ LOGSTRING2("Found STREAM file with index %d",index);
+ index++;
+ }
+ else
+ {
+ // in boot measurements the file system might not be ready yet.
+ LOGSTRING2("Problem in opening STREAM file %d",index);
+ }
+ file.Close();
+ }
+ } // while
+ }
+ else
+ {
+ // return error code
+ return result;
+ }
+
+ TUint32 id(iWriterHandler->GetActiveWriter()->GetWriterType());
+
+ // check if a file name is one that does not exist and selected plugin is disk writer
+ if(result == KErrNotFound && id == KDiskWriterPluginUid.iUid)
+ {
+ // write right trace data file name to disk writer plugin
+ iWriterHandler->SetPluginSettings( KDiskWriterPluginUid, iFileNameStream );
+ }
+ else
+ {
+ // return error if could not create trace log file
+ return result;
+ }
+ // close file server
+ fileServer.Close();
+ } // if output == KOutputToDebugOutput
+ return KErrNone;
+ }
+
+// --------------------------------------------------------------------------------------------
+void CProfiler::HandleTimerExpiresL(TInt aError)
+ {
+ LOGSTRING2("CProfiler::HandleTimerExpiresL - Error: %d", aError);
+ this->ControlL(RProfiler::EStopSampling);
+ if( CPServer::iClientCount <= 0 )
+ {
+ LOGSTRING("CProfiler::HandleTimerExpiresL - No clients attached, shutting down server...");
+ this->ControlL(RProfiler::EExitProfiler);
+ }
+ }
+
+// --------------------------------------------------------------------------------------------
+void CProfiler::SaveSettingsL()
+ {
+ LOGTEXT(_L("CProfiler::SaveSettings()"));
+
+ // local literal
+ _LIT(KGeneralHeader, "[general]");
+ _LIT(KVersionHeader, "version");
+ _LIT8(KPIProfilerSettingsHeader, "; PI Profiler Settings File");
+ _LIT8(KGeneralSettingsHeader, "; general settings");
+ _LIT8(KOutputFileDescription,"; \"output_type=file_system\" writes *.dat file to external memory");
+ _LIT8(KOutputDebugDescription,"; \"output_type=debug_output\" writes *.dat file to debug port");
+ _LIT8(KOutputFilePrefixDescription,"; if writing to file, prefix of the *.dat file\r\n; first '#' in the prefix is replaced with an integer");
+ _LIT8(KOutputSaveDriveDescription,"; if writing to file, the location to store the *.dat file");
+ _LIT8(KTimedProfilingPeriod,"; period (in seconds) used when using timed profiling");
+
+ RFs fs;
+ RFile settingsFile;
+ TInt err(KErrNone);
+ TBuf8<384> line;
+
+ // connect to file server
+ err = fs.Connect();
+ if( err != KErrNone )
+ {
+ // failed to write settings to settings file
+ return;
+ }
+
+ // create and set the private path
+ fs.CreatePrivatePath(EDriveC);
+ fs.SetSessionToPrivate(EDriveC);
+
+ // create the new settings file
+ err = settingsFile.Replace(fs, iSettingsFileLocation, EFileWrite);
+ if(err != KErrNone)
+ return;
+
+ CleanupClosePushL(settingsFile);
+
+ // write the header
+ line.Copy(KPIProfilerSettingsHeader);
+ line.Append(KNewLineSeparator);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // write the header
+ line.Copy(KGeneralSettingsHeader);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // write all generic settings
+ line.Copy(KGeneralHeader);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // write version info
+ line.Copy(KVersionHeader);
+ line.Append(KEquals);
+ line.Append(PROFILER_VERSION_SHORT);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // output explanation
+ line.Copy(KOutputFileDescription);
+ line.Append(KNewLineSeparator);
+ line.Append(KOutputDebugDescription);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // write trace output
+ line.Copy(KGenericTraceOutput);
+ line.Append(KEquals);
+ line.Append(iGeneralAttributes.iTraceOutput);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // file prefix explanation
+ line.Copy(KOutputFilePrefixDescription);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // write trace file prefix
+ line.Copy(KGenericTraceFilePrefix);
+ line.Append(KEquals);
+ line.Append(iGeneralAttributes.iTraceFilePrefix);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // file prefix explanation
+ line.Copy(KOutputSaveDriveDescription);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // write trace file location
+ line.Copy(KGenericTraceFileSaveDrive);
+ line.Append(KEquals);
+ line.Append(iGeneralAttributes.iSaveFileDrive);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // timed profiling period explanation
+ line.Copy(KTimedProfilingPeriod);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // Write timed profiling period value
+ line.Copy(KGenericTimedProfilingPeriod);
+ line.Append(KEquals);
+ TBuf<16> tmpNum;
+ tmpNum.AppendNum(iGeneralAttributes.iTimedSamplingPeriod);
+ line.Append(tmpNum);
+ line.Append(KNewLineSeparator);
+ settingsFile.Write(line);
+
+ // reset the default attributes array
+ iDefaultSamplerAttributesArray->Reset();
+
+ // update the latest changes from plugins
+ iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray);
+
+ // call CSamplerController to write all sampler settings
+ iSamplerHandler->ComposeAttributesToSettingsFileFormat(settingsFile, iDefaultSamplerAttributesArray);
+
+ CleanupStack::PopAndDestroy(); //settingsFile
+ // close file
+ fs.Close();
+ }
+
+TInt CProfiler::CheckOldProfilerRunning()
+ {
+ TFindProcess procName;
+ procName.Find(_L("BappeaProf.exe*"));
+ TFullName aResult;
+ TInt err(KErrNone);
+ RProcess proc;
+
+ // now check if old Profiler is still running on
+ err = procName.Next(aResult);
+ // check if old profiler process found
+ if(err == KErrNone)
+ {
+ // other process found, i.e. right process to communicate with, in case started from eshell
+ err = proc.Open(procName);
+ if(err == KErrNone)
+ {
+ if(proc.ExitCategory().Length() > 0)
+ {
+ proc.Close();
+ // process already exited => create a new one
+ return KErrNotFound;
+ }
+ proc.Close();
+ }
+ // return error for error handling
+ return KErrAlreadyExists;
+ }
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+void CProfiler::HandleError(TInt aErr)
+ {
+ // write error to status property to inform requester
+ TInt err(iEngineStatus.Set(KEngineStatusPropertyCat, EProfilerEngineStatus, aErr));
+ if(err != KErrNone)
+ RDebug::Print(_L("CProfiler::HandleError() - error setting status: %d"), err);
+ }
+
+// --------------------------------------------------------------------------------------------
+TInt CProfiler::ControlDataL(TInt aCommand,TAny* value1,TAny* /*value2*/)
+ {
+ LOGSTRING3("CProfiler::ControlData %d, 0x%x",aCommand,value1);
+
+ _LIT(KDebugOutput, "debug_output");
+ _LIT(KFileOutput, "file_system");
+ _LIT8(KOutputToDebugOutput, "debug_output");
+
+ TDes* desc;
+ TPtrC ptrDesc;
+
+ switch(aCommand)
+ {
+ // new controls
+ case RProfiler::EGetFileName:
+ {
+ LOGTEXT(_L("Profiler::EGetFileName - start"));
+ LOGSTRING2("Profiler::EGetFileName - total file name is: %S",(TDes*)value1);
+ desc = (TDes*)value1;
+ desc->Zero();
+ desc->Append(iFileNameStream);
+ LOGSTRING2("Profiler::EGetFileName - now total file name is: %S",(TDes*)value1);
+ return KErrNone;
+ }
+ case RProfiler::EGetActiveWriter:
+ {
+ LOGTEXT(_L("Profiler::EGetActiveWriter - start"));
+ desc = (TDes*)value1;
+ desc->Zero();
+ if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0)
+ {
+ desc->Append(KDebugOutput);
+ }
+ else
+ {
+ desc->Append(KFileOutput);
+ }
+ return KErrNone;
+ }
+ }
+
+ return KErrNone;
+ }
+
+// --------------------------------------------------------------------------------------------
+TInt CProfiler::ControlL(TInt aCommand)
+ {
+ LOGSTRING2("CProfiler::Control - Controlling ProfilerEngine %d",aCommand);
+ TInt err(KErrNone);
+
+ switch (aCommand)
+ {
+ case RProfiler::EStartSampling:
+ case RProfiler::EStartTimedSampling:
+ {
+ // check first if old Profiler already running
+ err = CheckOldProfilerRunning();
+ if(err == KErrAlreadyExists)
+ {
+ // if exists do not start a profiling process since corrupts the collected trace data
+ HandleError(err);
+ err = KErrNone;
+ return err;
+ }
+
+ // save settings before launching the profiler
+ // reason: the profiling may have set to the background => need for get right settings
+ SaveSettingsL();
+
+ // set the general settings to writer plugins to reflect the latest changes
+ err = HandleGeneralSettingsChange();
+ if(err == KErrNone)
+ {
+ // reset the buffers before new profiling
+ iUserStream->ResetBuffers();
+
+ // give the CProfilerSampleStream a handle to current writer
+ iUserStream->SetWriter(*iWriterHandler->GetActiveWriter());
+
+ // set initially debug output writer active
+ err = iWriterHandler->StartSelectedPlugin();
+
+ // check that writer plugin started
+ if(err != KErrNone)
+ {
+ // if not started handle error
+ HandleError(err);
+ }
+ else
+ {
+ // start activated sampler plug-in, NOTE: plugins check if errors occur in startup for some reason
+ iSamplerHandler->StartSamplerPluginsL();
+
+ // set engine state P&S property to running, e.g. for PIProfiler UI to read
+ iState = RProfiler::ERunning;
+
+ // set the engine into running mode
+ iEngineStatus.Set(iState);
+ }
+ }
+ else
+ {
+ // handle error and notify requester
+ HandleError(err);
+ }
+
+ if( aCommand == RProfiler::EStartTimedSampling )
+ {
+ iTimer->After(iGeneralAttributes.iTimedSamplingPeriod);
+ LOGTEXT(_L("CProfiler::Control - Finished processing EStartTimedSampling!"));
+ }
+ else
+ {
+ LOGTEXT(_L("CProfiler::Control - Finished processing EStartSampling!"));
+ }
+
+ return err;
+ }
+ case RProfiler::EStopSampling:
+ LOGTEXT(_L("CProfiler::Control - Starting to stop sampling..."));
+ // stop sampler plugins
+ if(iState == RProfiler::ERunning)
+ {
+ iState = RProfiler::EStopping;
+ iEngineStatus.Set(RProfiler::EStopping);
+
+ iSamplerHandler->StopSamplerPlugins();
+
+ // finalize the filled buffer writing
+ iUserStream->Finalise();
+
+ // stop output plugin and write the rest of the trace data to output
+ LOGTEXT(_L("CProfiler::Control - stopping writer"));
+ iWriterHandler->StopSelectedPlugin();
+
+ // set engine state P&S property idle
+ iState = RProfiler::EIdle;
+ iEngineStatus.Set(RProfiler::EIdle);
+
+ LOGSTRING2("CProfiler::Control - sampling stopped, going to state %d", RProfiler::EIdle);
+ }
+ return KErrNone;
+
+ case RProfiler::EExitProfiler:
+ {
+ // save settings into settings file when exiting
+ SaveSettingsL();
+
+ if(iUserStream)
+ {
+ delete iUserStream;
+ iUserStream = NULL;
+ }
+
+ // set engine state P&S property idle
+ iState = RProfiler::EIdle;
+ iEngineStatus.Set(RProfiler::EIdle);
+
+ LOGTEXT(_L("Stopping Activer Scheduler"));
+ CActiveScheduler::Stop();
+ LOGTEXT(_L("Stopped Activer Scheduler"));
+
+ return KErrNone;
+ }
+
+ case RProfiler::EAttachClient:
+ {
+ // Increase client reference count
+ ++CPServer::iClientCount;
+ LOGSTRING2("Increased client reference count to: %d", CPServer::iClientCount);
+ return KErrNone;
+ }
+ case RProfiler::ERemoveClient:
+ {
+ // Decrease client reference count
+ --CPServer::iClientCount;
+ LOGSTRING2("Decreasing client reference count to: %d", CPServer::iClientCount);
+ return KErrNone;
+ }
+ }
+
+ LOGTEXT(_L("CProfiler::Control - returning"));
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+void CProfiler::Finalise()
+ {
+ LOGTEXT(_L("CProfiler::Finalise - Finished processing EStopSampling!"));
+ }
+
+// --------------------------------------------------------------------------------------------
+RProfiler::TSamplerState CProfiler::State() const
+ {
+ return iState;
+ }
+
+/*
+ *
+ * Class CPServer definition
+ *
+ */
+// --------------------------------------------------------------------------------------------
+inline const CPServer& CPSession::Server() const
+ {
+ return *static_cast<const CPServer*>(CSession2::Server());
+ }
+
+// --------------------------------------------------------------------------------------------
+void CPSession::ServiceL(const RMessage2& aMessage)
+ {
+ LOGTEXT(_L("CPSession::ServiceL - Starting to process message"));
+ TInt err(KErrNone);
+
+ if(aMessage.Function() == RProfiler::EGetGeneralAttributes)
+ {
+ Server().GetGeneralAttributesL(aMessage);
+ }
+ else if(aMessage.Function() == RProfiler::ESetGeneralAttributes)
+ {
+ Server().SetGeneralAttributesL(aMessage);
+ }
+ else if(aMessage.Function() == RProfiler::EGetSamplerAttributes)
+ {
+ Server().GetSamplerAttributesL(aMessage);
+ }
+ else if(aMessage.Function() == RProfiler::EGetSamplerAttributeCount)
+ {
+ Server().GetSamplerAttributeCountL(aMessage);
+ }
+ else if(aMessage.Function() == RProfiler::ESetSamplerAttributes)
+ {
+ Server().SetSamplerAttributesL(aMessage);
+ }
+ else if(aMessage.Function() == RProfiler::ERefreshProfilerStatus)
+ {
+ Server().RefreshStatus(aMessage);
+ }
+ else if(aMessage.Ptr0() == 0 && aMessage.Ptr1() == 0 && aMessage.Ptr2() == 0)
+ {
+ LOGTEXT(_L("Ptr0 && Ptr1 == 0 && Ptr2 == 0"));
+ aMessage.Complete(Server().ControlL(RProfiler::TCommand(aMessage.Function())));
+ LOGTEXT(_L("CPSession::ServiceL - Message completed"));
+ }
+ else if(aMessage.Ptr0() != 0 && aMessage.Ptr1() != 0 && aMessage.Ptr2() != 0)
+ {
+ LOGTEXT(_L("Error with message, all pointers contain data!"));
+ }
+
+ else if (aMessage.Ptr0() != 0)
+ {
+ if(aMessage.Ptr1() == 0)
+ {
+ LOGTEXT(_L("ServiceL: Ptr0 != 0 && Ptr1 == 0"));
+ // provided value is a descriptor
+ TBuf<64>* dst = new TBuf<64>;
+ aMessage.ReadL(0,*dst,0);
+
+ err = Server().ControlDataL(aMessage.Function(),(TAny*)dst);
+ delete dst;
+ aMessage.Complete(err);
+ LOGTEXT(_L("CPSession::ServiceL - Message completed"));
+ }
+ else
+ {
+ LOGTEXT(_L("ServiceL: Ptr0 != 0 && Ptr1 != 0"));
+ // provided value is a descriptor
+ TBuf<64>* dst = new TBuf<64>;
+ aMessage.ReadL(0,*dst,0);
+
+ TUint32 num1 = (TUint32)aMessage.Ptr1();
+
+ err = Server().ControlDataL(aMessage.Function(),(TAny*)dst, (TAny*)num1);
+ delete dst;
+ aMessage.Complete(err);
+ LOGTEXT(_L("CPSession::ServiceL - Message completed"));
+ }
+ }
+ else if (aMessage.Ptr1() != 0)
+ {
+ LOGTEXT(_L("ServiceL: Ptr1 != 0"));
+ // provided value is a TUint32
+ if( ((TUint32)aMessage.Ptr3()) == 0xffffffff)
+ {
+ TUint32 num = (TUint32)aMessage.Ptr1();
+ err = Server().ControlDataL(aMessage.Function(),(TAny*)num);
+ aMessage.Complete(err);
+ LOGTEXT(_L("CPSession::ServiceL - Message completed"));
+ }
+ else
+ {
+ LOGTEXT(_L("ServiceL: Ptr3 != 0xffffffff"));
+ TUint32 num1 = (TUint32)aMessage.Ptr1();
+ TUint32 num2 = (TUint32)aMessage.Ptr3();
+ err = Server().ControlDataL(aMessage.Function(),(TAny*)num1,(TAny*)num2);
+ aMessage.Complete(err);
+ LOGTEXT(_L("CPSession::ServiceL - Message completed"));
+ }
+ }
+ else if (aMessage.Ptr2() != 0)
+ {
+ // command requests for data, provided
+ // value should be a descriptor
+ if( ((TUint32)aMessage.Ptr3()) == 0xffffffff)
+ {
+ LOGTEXT(_L("ServiceL: Ptr2 != 0 && Ptr3 == 0xffffffff"));
+
+ TBuf<256>* src = new TBuf<256>;
+ src->Zero();
+ err = Server().ControlDataL(aMessage.Function(),(TAny*)src);
+
+ LOGSTRING2("Got sampler data %S",src);
+
+ aMessage.WriteL(2, *src, 0);
+
+ delete src;
+ aMessage.Complete(err);
+ LOGTEXT(_L("CPSession::ServiceL - Message completed"));
+ }
+ else
+ {
+ LOGTEXT(_L("ServiceL: Ptr2 != 0 && Ptr3 != 0xffffffff"));
+
+ TUint32 num1 = (TUint32)aMessage.Ptr2(); // containing id
+ TBuf<256>* buffer = new TBuf<256>; // Text data, e.g. plug-in name or description
+
+ LOGSTRING3("Getting data for sampler: 0x%X, buffer max len %d",num1, aMessage.GetDesMaxLength(3));
+
+ err = Server().ControlDataL(aMessage.Function(), (TAny*)num1, (TAny*)buffer);
+
+ LOGSTRING2("Got sampler data %S",&buffer);
+
+ // write back to same parameter
+ aMessage.WriteL(3, *buffer, 0);
+
+ delete buffer;
+ aMessage.Complete(err);
+ LOGTEXT(_L("CPSession::ServiceL - Message completed"));
+ }
+ }
+ LOGTEXT(_L("CPSession::ServiceL - Message processed"));
+ }
+
+// --------------------------------------------------------------------------------------------
+MProfilerController* CPServer::NewL(TInt aPriority, MProfilerEngine& aEngine)
+ {
+ LOGTEXT(_L("CPServer::NewL - Enter"));
+ CPServer* self = new(ELeave) CPServer(aPriority, aEngine);
+ CleanupStack::PushL(self);
+ self->StartL(KProfilerName);
+ CleanupStack::Pop();
+ LOGTEXT(_L("CPSession::NewL - Exit"));
+ return self;
+ }
+
+// --------------------------------------------------------------------------------------------
+CPServer::CPServer(TInt aPriority, MProfilerEngine& aEngine)
+ : CServer2(aPriority), MProfilerController(aEngine)
+ {
+
+ }
+
+// --------------------------------------------------------------------------------------------
+void CPServer::Release()
+ {
+ delete this;
+ }
+
+// --------------------------------------------------------------------------------------------
+CSession2* CPServer::NewSessionL(const TVersion&,const RMessage2&) const
+ {
+ return new(ELeave) CPSession();
+ }
+
+/*
+ *
+ * Static methods for controlling the profiler
+ * through command line
+ *
+ */
+// --------------------------------------------------------------------------------------------
+static void RunEngineServerL(const TDesC& aSettingsFile)
+ {
+ RDebug::Print(_L("Profiler: RunEngineServerL() - Install active scheduler"));
+ CActiveScheduler* pS = new CActiveScheduler;
+ CActiveScheduler::Install(pS);
+ CProfiler* p = CProfiler::NewLC(aSettingsFile);
+ CActiveScheduler::Start();
+ p->Finalise();
+ CleanupStack::PopAndDestroy(p);
+ delete pS;
+ }
+
+// --------------------------------------------------------------------------------------------
+static TInt TestSettingsFile(const TDesC& configFile)
+ {
+ RFs fs;
+ LOGSTRING2("TestSettingsFile: entry %S", &configFile);
+ // check if file server can be connected
+ if (fs.Connect() != KErrNone)
+ {
+ LOGTEXT(_L("TestSettingsFile: could not connect file server"));
+ // file server couldn't be connected, return false
+ return KErrNotFound;
+ }
+
+ // check if config file name length is > 0
+ if (configFile.Length() > 0)
+ {
+ LOGTEXT(_L("TestSettingsFile: checking location sanity"));
+ // check sanity of settings file location
+ if(BaflUtils::CheckFolder(fs, configFile) != KErrNone)
+ {
+ LOGTEXT(_L("TestSettingsFile: location sanity check failed"));
+ fs.Close();
+ return KErrGeneral;
+ }
+ }
+ else
+ {
+ // configFile length 0, return false
+ LOGTEXT(_L("TestSettingsFile: config file string null length"));
+ fs.Close();
+ return KErrNotFound;
+ }
+ // return true if tests passed
+ LOGTEXT(_L("TestSettingsFile: exiting..."));
+ fs.Close();
+ return KErrNone;
+ }
+
+// --------------------------------------------------------------------------------------------
+GLDEF_C TInt E32Main()
+ {
+ // parse command line arguments
+ TBuf<256> c;
+ TInt err(KErrNone);
+
+ // copy the full command line with arguments into a buffer
+ User::CommandLine(c);
+
+ TBuf<256> fileName;
+ fileName.Append(c); // only one settings param should be
+ LOGSTRING3("Filename is %S, response %d 1", &fileName, err);
+ err = TestSettingsFile(fileName);
+ if(err != KErrNone)
+ {
+ LOGSTRING3("Filename is %S, response %d 2", &fileName, err);
+ // settings file does not exist, copy null desc to file name
+ fileName.Copy(KNullDesC);
+ }
+
+ LOGSTRING3("Filename is %S, response %d 3", &fileName, err);
+
+ // if no command line arguments found just start the profiler process
+ __UHEAP_MARK;
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ TInt ret(KErrNoMemory);
+ if( cleanup )
+ {
+ TRAPD( ret, RunEngineServerL(fileName) );
+ RDebug::Print(_L("Profiler: E32Main() - ret %d"), ret);
+ delete cleanup;
+ }
+ __UHEAP_MARKEND;
+
+ return ret;
+ }
+
+