piprofiler/engine/src/ProfilerEngine.cpp
branchRCL_3
changeset 13 da2cedce4920
equal deleted inserted replaced
12:d27dfa8884ad 13:da2cedce4920
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32cons.h>
       
    20 #include <e32base.h>
       
    21 #include <f32file.h>
       
    22 #include <c32comm.h>
       
    23 #include <s32file.h>
       
    24 #include <pathinfo.h>
       
    25 #include <s32mem.h>
       
    26 #include <bautils.h>
       
    27 #include <sysutil.h>
       
    28 #include <piprofiler/ProfilerConfig.h>
       
    29 #include "ProfilerEngine.h"
       
    30 #include <piprofiler/ProfilerTraces.h>
       
    31 
       
    32 // properties
       
    33 const TUid KEngineStatusPropertyCat={0x2001E5AD};
       
    34 enum TEnginePropertyKeys
       
    35 	{
       
    36 	EProfilerEngineStatus = 8,
       
    37 	EProfilerErrorStatus
       
    38 	};
       
    39 
       
    40 static _LIT_SECURITY_POLICY_PASS( KAllowAllPolicy );
       
    41 
       
    42 // CONSTANTS 
       
    43 const TInt KStreamBufferSize = 32768;
       
    44 const TInt KSavedLineCount = 64;
       
    45 const TInt KFileNameBufSize = 128;
       
    46 // Use this UID if plugin belongs to DebOutWriterPlugin:
       
    47 const TUid KDebOutWriterPluginUid = { 0x2001E5BA };
       
    48 // Use this UID if plugin belongs to MmcOutWriterPlugin:
       
    49 const TUid KDiskWriterPluginUid = { 0x2001E5BB };
       
    50 
       
    51 // LITERALS
       
    52 _LIT8(KGenericTraceOutput, "output_type");
       
    53 _LIT8(KGenericTraceFilePrefix, "file_prefix");
       
    54 _LIT8(KGenericTraceFileSaveDrive, "save_file_location");
       
    55 _LIT8(KGenericTimedProfilingPeriod, "profiling_period");
       
    56 _LIT8(KEquals, "=");
       
    57 _LIT8(KNewLineSeparator, "\n");
       
    58 _LIT8(KProfilerVersionTag, "version");
       
    59 _LIT8(KEndMark, "[end]");
       
    60 _LIT8(KOutputToDebugOutput, "debug_output");
       
    61 
       
    62 /** 
       
    63  * 
       
    64  * The controller class used to provide the Profiler functions. 
       
    65  * This runs as a server in the engine thread
       
    66  * 
       
    67  */
       
    68 class CPServer : public CServer2, public MProfilerController
       
    69     {
       
    70 public:
       
    71     static MProfilerController*		NewL(TInt aPriority, MProfilerEngine& aEngine);
       
    72 
       
    73 private:
       
    74                         CPServer(TInt aPriority, MProfilerEngine& aEngine);
       
    75     void				Release();
       
    76     CSession2*			NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
       
    77     
       
    78 public:
       
    79     static TInt         iClientCount;
       
    80     };
       
    81 
       
    82 TInt CPServer::iClientCount = 0;
       
    83 
       
    84 // The session class used by the server controller
       
    85 class CPSession : public CSession2
       
    86     {
       
    87 private:
       
    88     inline const CPServer&	Server() const;
       
    89     void					ServiceL(const RMessage2& aMessage);
       
    90     };
       
    91 
       
    92 /*
       
    93  *
       
    94  *	CProfiler class implementation
       
    95  *
       
    96  */
       
    97 // --------------------------------------------------------------------------------------------
       
    98 CProfiler* CProfiler::NewLC(const TDesC& aSettingsFile)
       
    99     {
       
   100 	CProfiler* self = new(ELeave) CProfiler(aSettingsFile);
       
   101 	CleanupStack::PushL(self);
       
   102 	self->ConstructL();
       
   103 	return self;
       
   104     }
       
   105 
       
   106 // --------------------------------------------------------------------------------------------
       
   107 CProfiler::CProfiler(const TDesC& aSettingsFile) : 
       
   108     iSettingsFileLocation(aSettingsFile)
       
   109 	{
       
   110 	// define property for Profiler Engine status, UI may read it for control purposes
       
   111 	if ( RProperty::Define(KEngineStatusPropertyCat, 
       
   112 	        EProfilerEngineStatus, 
       
   113 	        RProperty::EInt, 
       
   114 	        KAllowAllPolicy, 
       
   115 	        KAllowAllPolicy, 
       
   116 	        0) != KErrAlreadyExists )
       
   117 	    {
       
   118 	    LOGTEXT(_L("CProfiler::CProfiler - status property already defined"));
       
   119 	    }
       
   120 
       
   121 	if ( RProperty::Define(KEngineStatusPropertyCat, 
       
   122 	        EProfilerErrorStatus, 
       
   123             RProperty::EInt, 
       
   124             KAllowAllPolicy, 
       
   125             KAllowAllPolicy, 
       
   126             0) != KErrAlreadyExists )
       
   127         {
       
   128         LOGTEXT(_L("CProfiler::CProfiler - status property already defined"));
       
   129         }
       
   130 
       
   131 	// attach to own property
       
   132 	iEngineStatus.Attach(KEngineStatusPropertyCat, EProfilerEngineStatus);
       
   133 	// set status idle
       
   134 	iEngineStatus.Set(KEngineStatusPropertyCat, EProfilerEngineStatus, RProfiler::EIdle);
       
   135 	
       
   136     // attach to own property
       
   137     iUpdateStatus.Attach(KEngineStatusPropertyCat, EProfilerErrorStatus);
       
   138     // set status idle
       
   139     iUpdateStatus.Set(KEngineStatusPropertyCat, EProfilerErrorStatus, EFalse);
       
   140 	}
       
   141 
       
   142 // --------------------------------------------------------------------------------------------
       
   143 CProfiler::~CProfiler()
       
   144     {
       
   145 	LOGTEXT(_L("CProfiler::~CProfiler - Enter"));
       
   146 
       
   147 	// delete error checker
       
   148     if(iErrorChecker)
       
   149         {
       
   150         iErrorChecker->Cancel();
       
   151         delete iErrorChecker;
       
   152         iErrorChecker = NULL;
       
   153         }
       
   154 	
       
   155 	// delete settings array
       
   156 	if(iDefaultSamplerAttributesArray)
       
   157 	    {
       
   158 	    iDefaultSamplerAttributesArray->Reset();
       
   159 	    delete iDefaultSamplerAttributesArray;
       
   160 	    iDefaultSamplerAttributesArray = NULL;
       
   161 	    }
       
   162 
       
   163     // delete settings file raw line array
       
   164     if(iSavedLineArray)
       
   165         {
       
   166         iSavedLineArray->Reset();
       
   167         delete iSavedLineArray;
       
   168         iSavedLineArray = NULL;
       
   169         }
       
   170 		
       
   171 	// delete sampler controller, cleans up the sampler plugin instances
       
   172 	if(iSamplerHandler)
       
   173 		{
       
   174 		delete iSamplerHandler;
       
   175 		iSamplerHandler = NULL;
       
   176 		}
       
   177 	// delete writer controller, cleans up the writer plugin instances
       
   178 	if(iWriterHandler)
       
   179 		{
       
   180 		delete iWriterHandler;
       
   181 		iWriterHandler = NULL;
       
   182 		}
       
   183 
       
   184     // delete user side sampler stream 
       
   185 	if(iUserStream)
       
   186 		{
       
   187 		delete iUserStream;
       
   188 		iUserStream = NULL;
       
   189 		}
       
   190 
       
   191 	// close engine status property
       
   192 	iEngineStatus.Close();
       
   193 	if (RProperty::Delete(KEngineStatusPropertyCat, EProfilerEngineStatus) != KErrNotFound)
       
   194 	    {
       
   195 	    LOGTEXT(_L("CProfiler::~CProfiler - cannot close status property"));
       
   196 	    }
       
   197     // close engine update property
       
   198     iUpdateStatus.Close();
       
   199     if (RProperty::Delete(KEngineStatusPropertyCat, EProfilerErrorStatus) != KErrNotFound)
       
   200         {
       
   201         LOGTEXT(_L("CProfiler::~CProfiler - cannot close update property"));
       
   202         }
       
   203     
       
   204     // close server process
       
   205     if (iServer)
       
   206         {
       
   207         LOGTEXT(_L("CProfiler::~CProfiler - Releasing server"));
       
   208         iServer->Release();        
       
   209         }
       
   210     
       
   211     if( iTimer )
       
   212         {
       
   213         iTimer->Cancel();
       
   214         delete iTimer;
       
   215         iTimer = 0;
       
   216         }
       
   217     
       
   218 	LOGTEXT(_L("CProfiler::~CProfiler - Finished"));
       
   219     }
       
   220 
       
   221 // --------------------------------------------------------------------------------------------
       
   222 void CProfiler::ConstructL()
       
   223     {
       
   224 	LOGTEXT(_L("CProfiler::ConstructL - Enter"));
       
   225 	TInt err(0);
       
   226 	TLex lex;
       
   227 	
       
   228 	if ( iSettingsFileLocation.CompareF(KNullDesC) != 0 )
       
   229 	    {
       
   230         lex=(iSettingsFileLocation);
       
   231         // parse the first command line argument, the command itself
       
   232         lex.Mark();
       
   233         lex.SkipCharacters();
       
   234         if(lex.TokenLength() != 0)
       
   235             {
       
   236             // there is another item in the list
       
   237             TPtrC filename = lex.MarkedToken();
       
   238             LOGSTRING2("filename %S", &filename);
       
   239             lex.SkipSpace();
       
   240             lex.Mark();
       
   241             lex.SkipCharacters();
       
   242             if(lex.TokenLength() != 0)
       
   243                 {
       
   244                 TPtrC boot = lex.MarkedToken();
       
   245                 LOGTEXT(_L("boot mode"));
       
   246                 }
       
   247             }
       
   248 	    }
       
   249 	
       
   250     // create new sampler stream instance
       
   251     iUserStream = CProfilerSampleStream::NewL(KStreamBufferSize);
       
   252     if(!iUserStream)
       
   253         {
       
   254         LOGTEXT(_L("Profiler engine cannot reserve memory"));
       
   255         User::Leave(KErrCancel);   // operation cancelled
       
   256         }
       
   257 	
       
   258     // engine status checker
       
   259     iErrorChecker = CProfilerErrorChecker::NewL();
       
   260     iErrorChecker->SetObserver(this);
       
   261 
       
   262 	// create and initiate plug-in controller instances
       
   263     iSamplerHandler = CSamplerController::NewL(*iUserStream);
       
   264     iWriterHandler = CWriterController::NewL(*iUserStream);
       
   265     
       
   266     iWriterHandler->InitialiseWriterListL();
       
   267     
       
   268     // set engine as an observer to sampler controller to get the notification of plugin load has ended
       
   269     iSamplerHandler->SetObserver(this);
       
   270     
       
   271     // default settings from sampler plugins, maximum 20 sampler plugins
       
   272     iDefaultSamplerAttributesArray = new(ELeave) CArrayFixFlat<TSamplerAttributes>(20); 
       
   273     
       
   274     // set profiler status to initializing
       
   275     iState = RProfiler::EInitializing;
       
   276 	iEngineStatus.Set(RProfiler::EInitializing);
       
   277 	
       
   278 	// set default general settings, will be overdriven if changed in settings file
       
   279 	iGeneralAttributes.iTraceOutput.Copy(KDefaultTraceOutput);
       
   280 	iGeneralAttributes.iTraceFilePrefix.Copy(KDefaultTraceFilePrefix);
       
   281 	iGeneralAttributes.iSaveFileDrive.Copy(KDefaultTraceFileSaveDrive);
       
   282 	iGeneralAttributes.iTimedSamplingPeriod = KDefaultTimedSamplingPeriod;
       
   283 	
       
   284 	RThread me;
       
   285 	
       
   286 	me.SetPriority(EPriorityRealTime);
       
   287 
       
   288 	err = KErrGeneral;
       
   289 	TInt count = 0;
       
   290 
       
   291 	while(err != KErrNone && count < 30)
       
   292 	    {
       
   293 		err = User::RenameThread(KProfilerName);
       
   294 		if(err != KErrNone)
       
   295 		    {
       
   296 		    LOGSTRING2("CProfiler: error renaming the thread, err %d", err);
       
   297 			User::Leave(err);
       
   298 		    }
       
   299 		else break;
       
   300 	    }
       
   301 
       
   302 	// set settings file loading preferences
       
   303 	iSettingsFileLoaded = EFalse;
       
   304 
       
   305 	// change status property to idle since initialization successfull
       
   306 	iState = RProfiler::EIdle;
       
   307 	if( iEngineStatus.Set((TInt)RProfiler::EIdle) != KErrNone )
       
   308 	    {
       
   309 	    LOGTEXT(_L("CProfiler::ConstructL - engine status property change failed"));
       
   310 	    }
       
   311 
       
   312     if( iUpdateStatus.Set(EFalse) != KErrNone )
       
   313         {
       
   314         LOGTEXT(_L("CProfiler::ConstructL - engine status property change failed"));
       
   315         }
       
   316 
       
   317 	// create a server instance for clients to communicate with 
       
   318 	iServer = CPServer::NewL(10,*this);
       
   319 	
       
   320 	// close the handle 
       
   321 	me.Close();
       
   322 	
       
   323 	iTimer = CProfilerTimer::NewL(CActive::EPriorityStandard, *this);
       
   324 	
       
   325 	LOGTEXT(_L("CProfiler::ConstructL - Exit"));
       
   326 	
       
   327     }
       
   328 
       
   329 CProfilerSampleStream* CProfiler::GetSamplerStream()
       
   330     {
       
   331     return iUserStream;
       
   332     }
       
   333 
       
   334 void CProfiler::HandleSamplerControllerReadyL()
       
   335     {
       
   336     // load settings
       
   337     // check if settings file already loaded
       
   338     if(!iSettingsFileLoaded)
       
   339         {
       
   340         // load default settings file
       
   341         LoadSettingsL();
       
   342 
       
   343         iSettingsFileLoaded = ETrue;
       
   344         }
       
   345     
       
   346     // notify engine's launcher(UI or PIProfilerLauncher) to continue launch
       
   347     RProcess::Rendezvous(KErrNone); 
       
   348     }
       
   349 
       
   350 void CProfiler::NotifyRequesterForSettingsUpdate()
       
   351     {
       
   352     // set update status P&S property true => update needed on UI side
       
   353     iUpdateStatus.Set(ETrue);
       
   354     }
       
   355 
       
   356 void CProfiler::HandleProfilerErrorChangeL(TInt aError)
       
   357     {
       
   358     LOGSTRING2("CProfiler::HandleProfilerErrorChangeL() - error received, %d", aError);
       
   359     
       
   360     // check if profiler running
       
   361     if(iState == RProfiler::ERunning)
       
   362         {
       
   363         // stop profiler if error occurred during the trace
       
   364         iEngineStatus.Set(aError);
       
   365         
       
   366         // stop samplers, NOTE! Writer plugins not stopped since 
       
   367         iSamplerHandler->StopSamplerPlugins();
       
   368 
       
   369         // stop debug output plugin and write the rest of the trace data to output
       
   370         if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0)   
       
   371             {
       
   372             // write the rest of trace data only if debug output selected
       
   373             iWriterHandler->StopSelectedPlugin();
       
   374             }
       
   375         LOGSTRING2("CProfiler::HandleProfilerErrorChangeL - sampling stopped, going to state %d", RProfiler::EIdle);
       
   376         }
       
   377     }
       
   378 
       
   379 // ----------------------------------------------------------------------------
       
   380 // Gets a value from settings file for certain attribute.
       
   381 // ----------------------------------------------------------------------------
       
   382 void CProfiler::DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TDes8& aValue)
       
   383     {
       
   384     LOGTEXT(_L("CProfiler::DoGetValueFromSettingsFile()"));
       
   385     _LIT8(KSettingItemSeparator, "=");
       
   386     
       
   387     // read a line of given array
       
   388     for (TInt i=0; i<aLineArray->MdcaCount(); i++)
       
   389         {
       
   390         // check if this line has a separator
       
   391         TInt sepPos = aLineArray->MdcaPoint(i).Find(KSettingItemSeparator);
       
   392         if (sepPos > 0)
       
   393             {
       
   394             // check that the element matches
       
   395             if (aLineArray->MdcaPoint(i).Left(sepPos).CompareF(aAttribute) == 0)
       
   396                 {
       
   397                 // get the value
       
   398                 aValue.Copy(aLineArray->MdcaPoint(i).Right(aLineArray->MdcaPoint(i).Length()-sepPos-1));
       
   399                 break;
       
   400                 }
       
   401             }
       
   402         }
       
   403     }
       
   404 
       
   405 void CProfiler::DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TInt& aValue)
       
   406     {
       
   407     LOGTEXT(_L("CProfiler::DoGetValueFromSettingsFile()"));
       
   408     _LIT8(KSettingItemSeparator, "=");
       
   409     
       
   410     // read a line of given array
       
   411     for (TInt i=0; i<aLineArray->MdcaCount(); i++)
       
   412         {
       
   413         // check if this line has a separator
       
   414         TInt sepPos = aLineArray->MdcaPoint(i).Find(KSettingItemSeparator);
       
   415         if (sepPos > 0)
       
   416             {
       
   417             // check that the element matches
       
   418             if (aLineArray->MdcaPoint(i).Left(sepPos).CompareF(aAttribute) == 0)
       
   419                 {
       
   420                 // get the value                
       
   421                 TLex8 parser(aLineArray->MdcaPoint(i).Right(aLineArray->MdcaPoint(i).Length()-sepPos-1));
       
   422                 parser.Val(aValue);
       
   423                 break;
       
   424                 }
       
   425             }
       
   426         }
       
   427     }
       
   428 
       
   429 // --------------------------------------------------------------------------------------------
       
   430 TInt CProfiler::GetSamplerAttributesL(const RMessage2& aMessage)
       
   431     {
       
   432     TInt err(KErrNone);
       
   433     TInt pos(0);
       
   434 
       
   435     // get sampler count
       
   436     TInt count(iDefaultSamplerAttributesArray->Count());
       
   437 
       
   438     // write each of the default sampler plugin setting attributes over client-server session 
       
   439     for (TInt i(0); i<count; ++i)
       
   440        {
       
   441        TSamplerAttributes attr = iDefaultSamplerAttributesArray->At(i);
       
   442        TPckgC<TSamplerAttributes> attrPckg(attr);
       
   443        
       
   444        // write a TSamplerAttributes container at a time
       
   445        aMessage.WriteL(0, attrPckg, pos);
       
   446        pos += attrPckg.Length();
       
   447        }
       
   448 
       
   449     aMessage.Complete(err);
       
   450     return err;
       
   451     }
       
   452 
       
   453 // --------------------------------------------------------------------------------------------
       
   454 TInt CProfiler::SetSamplerAttributesL(const RMessage2& aMessage)
       
   455     {
       
   456     TSamplerAttributes attr;
       
   457     TPckg<TSamplerAttributes> inAttr(attr);
       
   458     
       
   459     TInt err = aMessage.Read(0, inAttr, 0);    
       
   460     
       
   461     // apply the changes directly to a plugin
       
   462     iSamplerHandler->SetSamplerSettingsL(attr.iUid, attr);
       
   463     
       
   464     aMessage.Complete(err);
       
   465     return err;
       
   466     }
       
   467 
       
   468 // --------------------------------------------------------------------------------------------
       
   469 TInt CProfiler::GetGeneralAttributesL(const RMessage2& aMessage)
       
   470     {
       
   471     TPckgBuf<TGeneralAttributes> generalSettings( iGeneralAttributes );
       
   472     
       
   473     // write general attributes over client-server session
       
   474     TInt err = aMessage.Write(0, generalSettings);
       
   475     
       
   476     aMessage.Complete(err);
       
   477     return err;
       
   478     }
       
   479 
       
   480 // --------------------------------------------------------------------------------------------
       
   481 TInt CProfiler::SetGeneralAttributesL(const RMessage2& aMessage)
       
   482     {
       
   483     // read the general settings from message
       
   484     TGeneralAttributes attr;
       
   485     TPckg<TGeneralAttributes> inPckg(attr);
       
   486     TInt err = aMessage.Read(0, inPckg, 0);
       
   487     
       
   488     // copy to the general attributes
       
   489     iGeneralAttributes.iSaveFileDrive.Copy(attr.iSaveFileDrive);
       
   490     iGeneralAttributes.iTraceFilePrefix.Copy(attr.iTraceFilePrefix);
       
   491     iGeneralAttributes.iTraceOutput.Copy(attr.iTraceOutput);
       
   492     iGeneralAttributes.iTimedSamplingPeriod = attr.iTimedSamplingPeriod;
       
   493     
       
   494     aMessage.Complete(err);
       
   495     return err;
       
   496     }
       
   497 
       
   498 TInt CProfiler::GetSamplerAttributeCountL(const RMessage2& aMessage)
       
   499     {
       
   500     // get the plugin array count and wrap it to TPckgBuf<>
       
   501     TPckgBuf<TInt> attributeCount(iDefaultSamplerAttributesArray->Count());
       
   502     
       
   503     // write general attributes over client-server session
       
   504     TInt err = aMessage.Write(0, attributeCount);
       
   505     
       
   506     aMessage.Complete(err);
       
   507     return err;
       
   508     }
       
   509 
       
   510 TInt CProfiler::RefreshStatus(const RMessage2& aMessage)
       
   511     {
       
   512     TInt err(KErrNone);
       
   513     
       
   514     // update profiler status for requester
       
   515     iEngineStatus.Set(iState);
       
   516     
       
   517     aMessage.Complete(err);
       
   518     return err;
       
   519     }
       
   520 
       
   521 // --------------------------------------------------------------------------------------------
       
   522 TInt CProfiler::LoadSettingsL(/*const TDesC& configFile*/)
       
   523     {
       
   524 	RFs fileServer;
       
   525 	RFile file;
       
   526 	TInt err(KErrNone);
       
   527     
       
   528 	// connect to file server 
       
   529 	err = fileServer.Connect();
       
   530 	
       
   531 	// check if file server can be connected
       
   532 	if (err != KErrNone)
       
   533 	    {
       
   534 		// file server couldn't be connected
       
   535 		return KErrGeneral;
       
   536 	    }
       
   537 
       
   538 	// check if settings file location length reasonable
       
   539 	if ( iSettingsFileLocation.CompareF(KNullDesC) == 0 )
       
   540 	    {
       
   541 		// open the file with the default path and name
       
   542 		TBuf<256> pathAndName;
       
   543 		pathAndName.Append(PathInfo::PhoneMemoryRootPath());
       
   544 		pathAndName.Append(KProfilerSettingsFileName);
       
   545 		iSettingsFileLocation.Copy(pathAndName);
       
   546 		LOGTEXT(_L("CProfiler::LoadSettings - Opening settings file with name (with the default path)"));
       
   547 		LOGTEXT(pathAndName);
       
   548 	    }
       
   549 
       
   550     // open the file with the given path and name
       
   551     err = file.Open(fileServer,iSettingsFileLocation,EFileRead);
       
   552 
       
   553 	
       
   554 	// check if RFile::Open() returned error
       
   555 	if (err != KErrNone)
       
   556 	    {
       
   557 		// file couldn't be opened
       
   558 		LOGTEXT(_L("CProfiler::LoadSettings - Failed to open settings, using default"));
       
   559 
       
   560 		// check if settings already loaded
       
   561 		if(iDefaultSamplerAttributesArray->Count() > 0)
       
   562 		    {
       
   563 		    // reset default settings array
       
   564 		    iDefaultSamplerAttributesArray->Reset();
       
   565 		    }
       
   566 		
       
   567 		// load default settings, instead of settings file ones
       
   568 		iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray);
       
   569 		
       
   570 		fileServer.Close();
       
   571 		return KErrNone;
       
   572 	    }
       
   573 	
       
   574 	// initialize iSavedLineArray, initial settings file lines 64
       
   575 	if(iSavedLineArray)
       
   576 	    {
       
   577         iSavedLineArray->Reset();
       
   578 	    }
       
   579 	else
       
   580 	    {
       
   581         iSavedLineArray = new (ELeave) CDesC8ArrayFlat(KSavedLineCount);
       
   582 	    }
       
   583 	
       
   584 	iSavedLinesCount = KSavedLineCount;
       
   585 	
       
   586     // get size of the file
       
   587     TInt fileSize(0);
       
   588     err = file.Size(fileSize);
       
   589     // check if an error occurred reading the file size
       
   590     if(err != KErrNone)
       
   591         {
       
   592         return KErrGeneral; // could not find the size
       
   593         }
       
   594         
       
   595     // sanity check for the file size
       
   596     if (fileSize < 3 || fileSize > 20000)
       
   597         {
       
   598         fileSize = KSettingsFileSize;
       
   599         return KErrNotSupported;
       
   600         }
       
   601     
       
   602 	// read the contents of the file to buffer. 
       
   603 	iSettingsBuffer.Zero();
       
   604 	file.Read(iSettingsBuffer, fileSize);
       
   605 	file.Close();
       
   606 	fileServer.Close();
       
   607 	LOGSTRING2("CProfiler::LoadSettings: read %d bytes",iSettingsBuffer.Length());
       
   608 
       
   609 	// append end mark "[end]"
       
   610     iSettingsBuffer.Append(KEndMark);
       
   611 	// force an ending newline
       
   612 	iSettingsBuffer.Append('\n');
       
   613 
       
   614 	// next fill the saved settings array (CDesC8ArrayFlat) for further comparison with changes and default values
       
   615     TBuf8<384> tmpBuf;
       
   616     TInt lineCount(0);
       
   617     TBool commentFound(EFalse);
       
   618     for (TInt i(0); i<iSettingsBuffer.Length(); i++)  // loop all chars
       
   619         {
       
   620         // if new line char found, create a new text line
       
   621         if (iSettingsBuffer[i]=='\r' || iSettingsBuffer[i]=='\n')
       
   622             {
       
   623             // check if collected string has reasonable length
       
   624             if (tmpBuf.Length() > 0)
       
   625                 {
       
   626                 // remove extra spaces
       
   627                 tmpBuf.TrimAll();
       
   628                 // check if the size of the array too small
       
   629                 if(lineCount >= iSavedLinesCount)
       
   630                     {
       
   631                     iSavedLineArray->ExpandL(20);   // expand by 20 lines
       
   632                     iSavedLinesCount += 20;
       
   633                     }
       
   634                 iSavedLineArray->AppendL(tmpBuf);
       
   635                 tmpBuf.Copy(KNullDesC8);
       
   636                 lineCount++;
       
   637                 }
       
   638             commentFound = EFalse;
       
   639             }
       
   640         // check if comment mark ';' is found on the line, skip the rest of the line
       
   641         else if(iSettingsBuffer[i]==';')
       
   642             {
       
   643             commentFound = ETrue;
       
   644             }
       
   645         // otherwise append a char to the temp line buffer if it is a wanted ASCII char
       
   646         else if (iSettingsBuffer[i]>=32 && iSettingsBuffer[i]<=127 && !commentFound)
       
   647             {
       
   648             tmpBuf.Append(iSettingsBuffer[i]);
       
   649             }
       
   650         }
       
   651     
       
   652     // empty tmpBuf
       
   653     tmpBuf.Copy(KNullDesC8);
       
   654     // check settings file version
       
   655     DoGetValueFromSettingsArray(iSavedLineArray, KProfilerVersionTag, tmpBuf); 
       
   656 
       
   657     TBuf8<32> version;
       
   658     version.Copy(PROFILER_VERSION_SHORT);
       
   659     
       
   660     // check if settings file version is 
       
   661     if(tmpBuf.CompareF(version) >= 0)
       
   662         {
       
   663         // update general attributes
       
   664         UpdateSavedGeneralAttributes(iSavedLineArray);
       
   665         
       
   666         // update settings to sampler plugins and save the attributes to default array
       
   667         iSamplerHandler->UpdateSavedSamplerAttributesL(iSavedLineArray, iDefaultSamplerAttributesArray);
       
   668         }
       
   669     else
       
   670         {
       
   671         // check if settings already loaded
       
   672         if(iDefaultSamplerAttributesArray)
       
   673             {
       
   674             // reset default settings array
       
   675             iDefaultSamplerAttributesArray->Reset();
       
   676 
       
   677 			// get the default settings if settings file version too old
       
   678 			iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray);
       
   679 			}
       
   680         }
       
   681     
       
   682 	return err; 
       
   683     }
       
   684 
       
   685 // --------------------------------------------------------------------------------------------
       
   686 void CProfiler::UpdateSavedGeneralAttributes(CDesC8ArrayFlat* aSavedAttributes)
       
   687     {
       
   688     // get saved general settings
       
   689     DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceOutput, iGeneralAttributes.iTraceOutput);
       
   690     DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceFilePrefix, iGeneralAttributes.iTraceFilePrefix);
       
   691     DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceFileSaveDrive, iGeneralAttributes.iSaveFileDrive);
       
   692     DoGetValueFromSettingsArray(aSavedAttributes, KGenericTimedProfilingPeriod, iGeneralAttributes.iTimedSamplingPeriod);
       
   693     }
       
   694 
       
   695 TBool CProfiler::CheckLocationSanity(RFs& fs, const TDesC8& aLocation)
       
   696     {
       
   697     TBool ret(EFalse);
       
   698     TBool noDiskSpace(EFalse);
       
   699     TBuf<32> drive;
       
   700     
       
   701     CnvUtfConverter::ConvertToUnicodeFromUtf8(drive, aLocation);
       
   702     TDriveUnit driveUnit = TDriveUnit(drive);
       
   703     
       
   704     // check that the root folder is correct
       
   705     if (drive.Length() > 2 && BaflUtils::CheckFolder(fs, drive.Left(3)) == KErrNone)
       
   706         {
       
   707         // test available disk space 
       
   708         TRAP_IGNORE((noDiskSpace = SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, driveUnit)));
       
   709         if(!noDiskSpace)
       
   710             ret = ETrue;
       
   711         }
       
   712     
       
   713     return ret;
       
   714     }
       
   715 
       
   716 TInt CProfiler::HandleGeneralSettingsChange()
       
   717     {
       
   718     // local literals
       
   719     _LIT8(KBackSlash, "\\");
       
   720     _LIT8(KTraceFileExtension, ".dat");
       
   721     
       
   722     TBuf8<KFileNameBufSize> fileNameBuf;
       
   723     TBuf8<10> number;
       
   724     TInt result(0);
       
   725     TInt index(1);
       
   726     TInt hashLocation(0);
       
   727     TParse parse;
       
   728 
       
   729     // check if plugin writer changed
       
   730     if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0)
       
   731         {
       
   732         iWriterHandler->SetPluginActive( KDebOutWriterPluginUid, EWriterPluginEnabled );
       
   733         }
       
   734     else
       
   735         {
       
   736         RFs fileServer;
       
   737         RFile file;
       
   738         
       
   739         // connect to the file server
       
   740         result = fileServer.Connect();
       
   741         if(result == KErrNone)
       
   742             {
       
   743             // disk writer plugin will be activated
       
   744             iWriterHandler->SetPluginActive( KDiskWriterPluginUid, EWriterPluginEnabled );
       
   745             
       
   746             // fix the trace data file location as well
       
   747             iTotalPrefix.Zero();
       
   748             iTotalPrefix.Append(iGeneralAttributes.iSaveFileDrive);
       
   749             
       
   750             // check that trace file location sane
       
   751             if(!CProfiler::CheckLocationSanity(fileServer, iTotalPrefix))
       
   752                 {
       
   753                 fileServer.Close();
       
   754                 return KErrPathNotFound;
       
   755                 }
       
   756             
       
   757             // remove extra spaces
       
   758             iTotalPrefix.TrimAll();
       
   759             
       
   760             // check the directory contains a trailing backlash
       
   761             if(iTotalPrefix.Right(1) != _L8("\\") && 
       
   762                     iTotalPrefix.Right(1) != _L8("/"))
       
   763                 {
       
   764                 // append backslash to end
       
   765                 iTotalPrefix.Append(KBackSlash);
       
   766                 }
       
   767             
       
   768             // append trace file name prefix e.g. PIProfiler_#
       
   769             iTotalPrefix.Append(iGeneralAttributes.iTraceFilePrefix);
       
   770     
       
   771             // locate '#' mark for finding the next free trace file name, e.g. E:\data\PIProfiler_4.dat
       
   772             hashLocation = iTotalPrefix.Locate('#');
       
   773             if( hashLocation == KErrNotFound )
       
   774                 {
       
   775                 // append simply at the end of the trace file prefix, no need to inform user
       
   776                 iTotalPrefix.Append('#');
       
   777                 // get new hash mark location
       
   778                 hashLocation = iTotalPrefix.Locate('#');
       
   779                 }
       
   780     
       
   781             // add the file extension
       
   782             iTotalPrefix.Append(KTraceFileExtension);
       
   783 
       
   784             // search for files with different indices
       
   785             // until a free filename is found
       
   786             while(result != KErrNotFound)
       
   787                 {
       
   788                 fileNameBuf.Zero();
       
   789                 // start with the original prefix
       
   790                 fileNameBuf.Append(iTotalPrefix);
       
   791                 // convert the number to a descriptor
       
   792                 number.Num(index);
       
   793                 // replace the hashmark with the real number
       
   794                 fileNameBuf.Replace(hashLocation,1,number);
       
   795                 
       
   796                 // make a copy to the iFileNameStream descriptor
       
   797                 iFileNameStream.Zero();
       
   798                 CnvUtfConverter::ConvertToUnicodeFromUtf8(iFileNameStream, fileNameBuf);
       
   799                 
       
   800                 LOGSTRING2("CProfiler::HandleGeneralSettingsChange() - trying to open files %S ",&iFileNameStream);
       
   801 
       
   802                 if((result = parse.Set(iFileNameStream, NULL, NULL)) != KErrNone)
       
   803                     {
       
   804                     // break loop if fails, problems in file name => change to log into debug output
       
   805                     break;
       
   806                     }
       
   807                 
       
   808                 // create directory for trace files if not exists
       
   809                 result = fileServer.MkDirAll(parse.FullName());
       
   810 
       
   811                 // check that file server responded with KErrNone or KErrAlreadyExists
       
   812                 if( result != KErrNone && result != KErrAlreadyExists)
       
   813                     {
       
   814                     // if some other result, e.g. memory full => break
       
   815                     break;
       
   816                     }
       
   817 
       
   818                 // attempt opening the file
       
   819                 result = file.Open(fileServer,parse.FullName(),EFileShareReadersOnly);
       
   820                 if(result != KErrNotFound)
       
   821                     {
       
   822                     if( result != KErrNotReady && 
       
   823                         result != KErrServerBusy ) 
       
   824                         {
       
   825                         // close the file if it could be opened
       
   826                         LOGSTRING2("Found STREAM file with index %d",index);
       
   827                         index++;
       
   828                         }
       
   829                     else 
       
   830                         {
       
   831                         // in boot measurements the file system might not be ready yet.
       
   832                         LOGSTRING2("Problem in opening STREAM file %d",index);
       
   833                         }
       
   834                     file.Close();
       
   835                     }
       
   836                 } // while
       
   837             }
       
   838         else
       
   839             {
       
   840             // return error code
       
   841             return result;
       
   842             }
       
   843         
       
   844         TUint32 id(iWriterHandler->GetActiveWriter()->GetWriterType());
       
   845         
       
   846         // check if a file name is one that does not exist and selected plugin is disk writer
       
   847         if(result == KErrNotFound && id == KDiskWriterPluginUid.iUid)
       
   848             {
       
   849             // write right trace data file name to disk writer plugin
       
   850             iWriterHandler->SetPluginSettings( KDiskWriterPluginUid, iFileNameStream );
       
   851             }
       
   852         else
       
   853             {
       
   854             // return error if could not create trace log file
       
   855             return result;
       
   856             }
       
   857         // close file server
       
   858         fileServer.Close();
       
   859         }   // if output == KOutputToDebugOutput
       
   860     return KErrNone;
       
   861     }
       
   862 
       
   863 // --------------------------------------------------------------------------------------------
       
   864 void CProfiler::HandleTimerExpiresL(TInt aError)
       
   865     {
       
   866     LOGSTRING2("CProfiler::HandleTimerExpiresL - Error: %d", aError);
       
   867     this->ControlL(RProfiler::EStopSampling);
       
   868     if( CPServer::iClientCount <= 0 )
       
   869         {
       
   870         LOGSTRING("CProfiler::HandleTimerExpiresL - No clients attached, shutting down server...");
       
   871         this->ControlL(RProfiler::EExitProfiler);                
       
   872         }
       
   873     }
       
   874 
       
   875 // --------------------------------------------------------------------------------------------
       
   876 void CProfiler::SaveSettingsL()
       
   877     {
       
   878     LOGTEXT(_L("CProfiler::SaveSettings()"));
       
   879     
       
   880     // local literal
       
   881     _LIT(KGeneralHeader, "[general]");
       
   882     _LIT(KVersionHeader, "version");
       
   883     _LIT8(KPIProfilerSettingsHeader, "; PI Profiler Settings File");
       
   884     _LIT8(KGeneralSettingsHeader, "; general settings");
       
   885     _LIT8(KOutputFileDescription,"; \"output_type=file_system\" writes *.dat file to external memory");
       
   886     _LIT8(KOutputDebugDescription,"; \"output_type=debug_output\" writes *.dat file to debug port");
       
   887     _LIT8(KOutputFilePrefixDescription,"; if writing to file, prefix of the *.dat file\r\n; first '#' in the prefix is replaced with an integer");
       
   888     _LIT8(KOutputSaveDriveDescription,"; if writing to file, the location to store the *.dat file");
       
   889     _LIT8(KTimedProfilingPeriod,"; period (in seconds) used when using timed profiling");
       
   890     
       
   891     RFs fs;
       
   892     RFile settingsFile;
       
   893     TInt err(KErrNone);
       
   894     TBuf8<384> line;
       
   895     
       
   896     // connect to file server
       
   897     err = fs.Connect();
       
   898     if( err != KErrNone )
       
   899         {
       
   900         // failed to write settings to settings file
       
   901         return;
       
   902         }
       
   903     
       
   904     // create and set the private path
       
   905     fs.CreatePrivatePath(EDriveC);
       
   906     fs.SetSessionToPrivate(EDriveC);
       
   907   
       
   908     // create the new settings file
       
   909     err = settingsFile.Replace(fs, iSettingsFileLocation, EFileWrite);
       
   910     if(err != KErrNone)
       
   911         return;
       
   912     
       
   913     CleanupClosePushL(settingsFile);  
       
   914 
       
   915     // write the header
       
   916     line.Copy(KPIProfilerSettingsHeader);
       
   917     line.Append(KNewLineSeparator);
       
   918     line.Append(KNewLineSeparator);
       
   919     settingsFile.Write(line);
       
   920     
       
   921     // write the header
       
   922     line.Copy(KGeneralSettingsHeader);
       
   923     line.Append(KNewLineSeparator);
       
   924     settingsFile.Write(line);
       
   925 
       
   926     // write all generic settings
       
   927     line.Copy(KGeneralHeader);
       
   928     line.Append(KNewLineSeparator);
       
   929     settingsFile.Write(line);
       
   930 
       
   931     // write version info
       
   932     line.Copy(KVersionHeader);
       
   933     line.Append(KEquals);
       
   934     line.Append(PROFILER_VERSION_SHORT);
       
   935     line.Append(KNewLineSeparator);
       
   936     settingsFile.Write(line);
       
   937 
       
   938     // output explanation
       
   939     line.Copy(KOutputFileDescription);
       
   940     line.Append(KNewLineSeparator);
       
   941     line.Append(KOutputDebugDescription);
       
   942     line.Append(KNewLineSeparator);
       
   943     settingsFile.Write(line);
       
   944     
       
   945     // write trace output
       
   946     line.Copy(KGenericTraceOutput);
       
   947     line.Append(KEquals);
       
   948     line.Append(iGeneralAttributes.iTraceOutput);
       
   949     line.Append(KNewLineSeparator);
       
   950     settingsFile.Write(line);
       
   951     
       
   952     // file prefix explanation
       
   953     line.Copy(KOutputFilePrefixDescription);
       
   954     line.Append(KNewLineSeparator);
       
   955     settingsFile.Write(line);
       
   956 
       
   957     // write trace file prefix
       
   958     line.Copy(KGenericTraceFilePrefix);
       
   959     line.Append(KEquals);
       
   960     line.Append(iGeneralAttributes.iTraceFilePrefix);
       
   961     line.Append(KNewLineSeparator);
       
   962     settingsFile.Write(line);
       
   963     
       
   964     // file prefix explanation
       
   965     line.Copy(KOutputSaveDriveDescription);
       
   966     line.Append(KNewLineSeparator);
       
   967     settingsFile.Write(line);
       
   968 
       
   969     // write trace file location
       
   970     line.Copy(KGenericTraceFileSaveDrive);
       
   971     line.Append(KEquals);
       
   972     line.Append(iGeneralAttributes.iSaveFileDrive);
       
   973     line.Append(KNewLineSeparator);
       
   974     settingsFile.Write(line);
       
   975     
       
   976     // timed profiling period explanation
       
   977     line.Copy(KTimedProfilingPeriod);
       
   978     line.Append(KNewLineSeparator);
       
   979     settingsFile.Write(line);
       
   980     
       
   981     // Write timed profiling period value
       
   982     line.Copy(KGenericTimedProfilingPeriod);
       
   983     line.Append(KEquals);
       
   984     TBuf<16> tmpNum;
       
   985     tmpNum.AppendNum(iGeneralAttributes.iTimedSamplingPeriod);
       
   986     line.Append(tmpNum);
       
   987     line.Append(KNewLineSeparator);
       
   988     settingsFile.Write(line);
       
   989         
       
   990     // reset the default attributes array
       
   991     iDefaultSamplerAttributesArray->Reset();
       
   992     
       
   993     // update the latest changes from plugins
       
   994     iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray);
       
   995     
       
   996     // call CSamplerController to write all sampler settings
       
   997     iSamplerHandler->ComposeAttributesToSettingsFileFormat(settingsFile, iDefaultSamplerAttributesArray);
       
   998     
       
   999     CleanupStack::PopAndDestroy(); //settingsFile
       
  1000     // close file
       
  1001     fs.Close();
       
  1002     }
       
  1003 
       
  1004 TInt CProfiler::CheckOldProfilerRunning()
       
  1005     {
       
  1006     TFindProcess procName;
       
  1007     procName.Find(_L("BappeaProf.exe*"));
       
  1008     TFullName aResult;
       
  1009     TInt err(KErrNone);
       
  1010     RProcess proc;    
       
  1011     
       
  1012     // now check if old Profiler is still running on
       
  1013     err = procName.Next(aResult);
       
  1014     // check if old profiler process found 
       
  1015     if(err == KErrNone)
       
  1016         {
       
  1017         // other process found, i.e. right process to communicate with, in case started from eshell
       
  1018         err = proc.Open(procName);
       
  1019         if(err == KErrNone)
       
  1020             {
       
  1021             if(proc.ExitCategory().Length() > 0)
       
  1022                 {
       
  1023                 proc.Close();
       
  1024                 // process already exited => create a new one
       
  1025                 return KErrNotFound;
       
  1026                 }
       
  1027             proc.Close();
       
  1028             }
       
  1029         // return error for error handling
       
  1030         return KErrAlreadyExists;
       
  1031         }
       
  1032     return err;
       
  1033     }
       
  1034 
       
  1035 // --------------------------------------------------------------------------------------------
       
  1036 void CProfiler::HandleError(TInt aErr)
       
  1037     {
       
  1038     // write error to status property to inform requester
       
  1039     TInt err(iEngineStatus.Set(KEngineStatusPropertyCat, EProfilerEngineStatus, aErr));
       
  1040     if(err != KErrNone)
       
  1041         RDebug::Print(_L("CProfiler::HandleError() - error setting status: %d"), err);
       
  1042     }
       
  1043 
       
  1044 // --------------------------------------------------------------------------------------------
       
  1045 TInt CProfiler::ControlDataL(TInt aCommand,TAny* value1,TAny* /*value2*/)
       
  1046     {
       
  1047 	LOGSTRING3("CProfiler::ControlData %d, 0x%x",aCommand,value1);
       
  1048 
       
  1049 	_LIT(KDebugOutput, "debug_output");
       
  1050 	_LIT(KFileOutput, "file_system");
       
  1051 	_LIT8(KOutputToDebugOutput, "debug_output");
       
  1052 	
       
  1053 	TDes* desc;
       
  1054 	TPtrC ptrDesc;
       
  1055 	
       
  1056 	switch(aCommand)
       
  1057 	    {
       
  1058 		// new controls
       
  1059 	    case RProfiler::EGetFileName:
       
  1060 	        {
       
  1061             LOGTEXT(_L("Profiler::EGetFileName - start"));
       
  1062             LOGSTRING2("Profiler::EGetFileName - total file name is: %S",(TDes*)value1);
       
  1063             desc = (TDes*)value1;
       
  1064             desc->Zero();
       
  1065             desc->Append(iFileNameStream);
       
  1066             LOGSTRING2("Profiler::EGetFileName - now total file name is: %S",(TDes*)value1);
       
  1067             return KErrNone;
       
  1068 	        }
       
  1069         case RProfiler::EGetActiveWriter:
       
  1070             {
       
  1071             LOGTEXT(_L("Profiler::EGetActiveWriter - start"));
       
  1072             desc = (TDes*)value1;
       
  1073             desc->Zero();
       
  1074             if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0)
       
  1075                 {
       
  1076                 desc->Append(KDebugOutput);
       
  1077                 }
       
  1078             else
       
  1079                 {
       
  1080                 desc->Append(KFileOutput);
       
  1081                 }
       
  1082             return KErrNone;
       
  1083             }
       
  1084 	    }
       
  1085 
       
  1086 	return KErrNone;
       
  1087     }
       
  1088 
       
  1089 // --------------------------------------------------------------------------------------------
       
  1090 TInt CProfiler::ControlL(TInt aCommand)
       
  1091     {
       
  1092 	LOGSTRING2("CProfiler::Control - Controlling ProfilerEngine %d",aCommand);
       
  1093 	TInt err(KErrNone);
       
  1094 	
       
  1095 	switch (aCommand)
       
  1096 	    {
       
  1097 		case RProfiler::EStartSampling:
       
  1098 		case RProfiler::EStartTimedSampling:
       
  1099 		    {
       
  1100 		    // check first if old Profiler already running
       
  1101 		    err = CheckOldProfilerRunning();
       
  1102 		    if(err == KErrAlreadyExists)
       
  1103 		        {
       
  1104 		        // if exists do not start a profiling process since corrupts the collected trace data  
       
  1105 		        HandleError(err);
       
  1106 		        err = KErrNone;
       
  1107 		        return err;
       
  1108 		        }
       
  1109 		    
       
  1110 		    // save settings before launching the profiler
       
  1111 		    // reason: the profiling may have set to the background => need for get right settings
       
  1112 		    SaveSettingsL();
       
  1113 		    
       
  1114 		    // set the general settings to writer plugins to reflect the latest changes
       
  1115 		    err = HandleGeneralSettingsChange();
       
  1116 		    if(err == KErrNone)
       
  1117 		        {
       
  1118                 // reset the buffers before new profiling
       
  1119                 iUserStream->ResetBuffers();
       
  1120     
       
  1121                 // give the CProfilerSampleStream a handle to current writer
       
  1122                 iUserStream->SetWriter(*iWriterHandler->GetActiveWriter());
       
  1123                 
       
  1124                 // set initially debug output writer active
       
  1125                 err = iWriterHandler->StartSelectedPlugin();
       
  1126     
       
  1127                 // check that writer plugin started
       
  1128                 if(err != KErrNone)
       
  1129                     {
       
  1130                     // if not started handle error
       
  1131                     HandleError(err);
       
  1132                     }
       
  1133                 else
       
  1134                     {
       
  1135                     // start activated sampler plug-in, NOTE: plugins check if errors occur in startup for some reason
       
  1136                     iSamplerHandler->StartSamplerPluginsL();
       
  1137         
       
  1138                     // set engine state P&S property to running, e.g. for PIProfiler UI to read
       
  1139                     iState = RProfiler::ERunning;
       
  1140         
       
  1141                     // set the engine into running mode
       
  1142                     iEngineStatus.Set(iState);
       
  1143                     }
       
  1144                 }
       
  1145 		    else
       
  1146 		        {
       
  1147 		        // handle error and notify requester
       
  1148 		        HandleError(err);
       
  1149 		        }
       
  1150 		    
       
  1151 		    if( aCommand == RProfiler::EStartTimedSampling )
       
  1152 		        {
       
  1153                 iTimer->After(iGeneralAttributes.iTimedSamplingPeriod);
       
  1154                 LOGTEXT(_L("CProfiler::Control - Finished processing EStartTimedSampling!"));
       
  1155 		        }
       
  1156 		    else
       
  1157 		        {
       
  1158                 LOGTEXT(_L("CProfiler::Control - Finished processing EStartSampling!"));
       
  1159 		        }
       
  1160 
       
  1161 			return err;
       
  1162 		    }
       
  1163 		case RProfiler::EStopSampling:
       
  1164 			LOGTEXT(_L("CProfiler::Control - Starting to stop sampling..."));
       
  1165 			// stop sampler plugins
       
  1166 			if(iState == RProfiler::ERunning)
       
  1167 				{
       
  1168 				iState = RProfiler::EStopping;
       
  1169 				iEngineStatus.Set(RProfiler::EStopping);
       
  1170 				
       
  1171 				iSamplerHandler->StopSamplerPlugins();
       
  1172 	
       
  1173 				// finalize the filled buffer writing
       
  1174 				iUserStream->Finalise();
       
  1175 				
       
  1176 				// stop output plugin and write the rest of the trace data to output
       
  1177 				LOGTEXT(_L("CProfiler::Control - stopping writer"));
       
  1178 				iWriterHandler->StopSelectedPlugin();
       
  1179 	
       
  1180 				// set engine state P&S property idle 
       
  1181 				iState = RProfiler::EIdle;
       
  1182 				iEngineStatus.Set(RProfiler::EIdle);
       
  1183 				
       
  1184 				LOGSTRING2("CProfiler::Control - sampling stopped, going to state %d", RProfiler::EIdle);
       
  1185 				}
       
  1186 			return KErrNone;
       
  1187 
       
  1188 		case RProfiler::EExitProfiler:
       
  1189 		    {
       
  1190 		    // save settings into settings file when exiting
       
  1191 		    SaveSettingsL();
       
  1192 
       
  1193             if(iUserStream)
       
  1194                 {
       
  1195                 delete iUserStream;
       
  1196                 iUserStream = NULL;
       
  1197                 }
       
  1198 		    
       
  1199             // set engine state P&S property idle 
       
  1200             iState = RProfiler::EIdle;
       
  1201             iEngineStatus.Set(RProfiler::EIdle);
       
  1202                
       
  1203             LOGTEXT(_L("Stopping Activer Scheduler"));
       
  1204             CActiveScheduler::Stop();
       
  1205             LOGTEXT(_L("Stopped Activer Scheduler"));
       
  1206 
       
  1207             return KErrNone;
       
  1208 		    }
       
  1209 		    
       
  1210 		case RProfiler::EAttachClient:
       
  1211 		    {
       
  1212 		    // Increase client reference count
       
  1213 		    ++CPServer::iClientCount;
       
  1214 		    LOGSTRING2("Increased client reference count to: %d", CPServer::iClientCount);
       
  1215 		    return KErrNone;
       
  1216 		    }
       
  1217 		case RProfiler::ERemoveClient:
       
  1218 		    {
       
  1219 		    // Decrease client reference count
       
  1220 		    --CPServer::iClientCount;
       
  1221 		    LOGSTRING2("Decreasing client reference count to: %d", CPServer::iClientCount);
       
  1222 		    return KErrNone;
       
  1223 		    }
       
  1224 	    }
       
  1225 
       
  1226 	LOGTEXT(_L("CProfiler::Control - returning"));
       
  1227 
       
  1228 	return err;
       
  1229     }
       
  1230 
       
  1231 // --------------------------------------------------------------------------------------------
       
  1232 void CProfiler::Finalise()
       
  1233     {	
       
  1234 	LOGTEXT(_L("CProfiler::Finalise - Finished processing EStopSampling!"));
       
  1235     }
       
  1236 
       
  1237 // --------------------------------------------------------------------------------------------
       
  1238 RProfiler::TSamplerState CProfiler::State() const
       
  1239     {
       
  1240 	return iState;
       
  1241     }
       
  1242 
       
  1243 /*
       
  1244  *
       
  1245  *	Class CPServer definition
       
  1246  *
       
  1247  */
       
  1248 // --------------------------------------------------------------------------------------------
       
  1249 inline const CPServer& CPSession::Server() const
       
  1250     {
       
  1251 	return *static_cast<const CPServer*>(CSession2::Server());
       
  1252     }
       
  1253 
       
  1254 // --------------------------------------------------------------------------------------------
       
  1255 void CPSession::ServiceL(const RMessage2& aMessage)
       
  1256     {
       
  1257 	LOGTEXT(_L("CPSession::ServiceL - Starting to process message"));
       
  1258 	TInt err(KErrNone);
       
  1259 	
       
  1260 	if(aMessage.Function() == RProfiler::EGetGeneralAttributes)
       
  1261 	    {
       
  1262 	    Server().GetGeneralAttributesL(aMessage);
       
  1263 	    }
       
  1264 	else if(aMessage.Function() == RProfiler::ESetGeneralAttributes)
       
  1265 	    {
       
  1266         Server().SetGeneralAttributesL(aMessage);
       
  1267 	    }
       
  1268 	else if(aMessage.Function() == RProfiler::EGetSamplerAttributes)
       
  1269 	    {
       
  1270         Server().GetSamplerAttributesL(aMessage);
       
  1271 	    }
       
  1272     else if(aMessage.Function() == RProfiler::EGetSamplerAttributeCount)
       
  1273         {
       
  1274         Server().GetSamplerAttributeCountL(aMessage);
       
  1275         }
       
  1276     else if(aMessage.Function() == RProfiler::ESetSamplerAttributes)
       
  1277         {
       
  1278         Server().SetSamplerAttributesL(aMessage);
       
  1279         }
       
  1280     else if(aMessage.Function() == RProfiler::ERefreshProfilerStatus)
       
  1281         {
       
  1282         Server().RefreshStatus(aMessage);
       
  1283         }
       
  1284 	else if(aMessage.Ptr0() == 0 && aMessage.Ptr1() == 0 && aMessage.Ptr2() == 0)
       
  1285 		{	
       
  1286 		LOGTEXT(_L("Ptr0 && Ptr1 == 0 && Ptr2 == 0"));
       
  1287 		aMessage.Complete(Server().ControlL(RProfiler::TCommand(aMessage.Function())));
       
  1288 		LOGTEXT(_L("CPSession::ServiceL - Message completed"));
       
  1289 		} 
       
  1290 	else if(aMessage.Ptr0() != 0 && aMessage.Ptr1() != 0 && aMessage.Ptr2() != 0)
       
  1291 		{
       
  1292 		LOGTEXT(_L("Error with message, all pointers contain data!"));
       
  1293 		}
       
  1294 		
       
  1295 	else if (aMessage.Ptr0() != 0)
       
  1296 		{
       
  1297 		if(aMessage.Ptr1() == 0)
       
  1298 			{
       
  1299 			LOGTEXT(_L("ServiceL: Ptr0 != 0 && Ptr1 == 0"));
       
  1300 			// provided value is a descriptor
       
  1301 			TBuf<64>* dst = new TBuf<64>;
       
  1302 			aMessage.ReadL(0,*dst,0);
       
  1303 	
       
  1304 			err = Server().ControlDataL(aMessage.Function(),(TAny*)dst);
       
  1305 			delete dst;
       
  1306 			aMessage.Complete(err);
       
  1307 			LOGTEXT(_L("CPSession::ServiceL - Message completed"));
       
  1308 			}
       
  1309 		else
       
  1310 			{
       
  1311 			LOGTEXT(_L("ServiceL: Ptr0 != 0 && Ptr1 != 0"));
       
  1312 			// provided value is a descriptor
       
  1313 			TBuf<64>* dst = new TBuf<64>;
       
  1314 			aMessage.ReadL(0,*dst,0);
       
  1315 			
       
  1316 			TUint32 num1 = (TUint32)aMessage.Ptr1();
       
  1317 			
       
  1318 			err = Server().ControlDataL(aMessage.Function(),(TAny*)dst, (TAny*)num1);
       
  1319 			delete dst;
       
  1320 			aMessage.Complete(err);
       
  1321 			LOGTEXT(_L("CPSession::ServiceL - Message completed"));
       
  1322 			}
       
  1323 		}
       
  1324 	else if (aMessage.Ptr1() != 0)
       
  1325 		{
       
  1326 		LOGTEXT(_L("ServiceL: Ptr1 != 0"));
       
  1327 		// provided value is a TUint32
       
  1328 		if( ((TUint32)aMessage.Ptr3()) == 0xffffffff)
       
  1329 			{
       
  1330 			TUint32 num = (TUint32)aMessage.Ptr1();
       
  1331 			err = Server().ControlDataL(aMessage.Function(),(TAny*)num);
       
  1332 			aMessage.Complete(err);
       
  1333 			LOGTEXT(_L("CPSession::ServiceL - Message completed"));
       
  1334 			}
       
  1335 		else
       
  1336 			{
       
  1337 			LOGTEXT(_L("ServiceL: Ptr3 != 0xffffffff"));
       
  1338 			TUint32 num1 = (TUint32)aMessage.Ptr1();
       
  1339 			TUint32 num2 = (TUint32)aMessage.Ptr3();
       
  1340 			err = Server().ControlDataL(aMessage.Function(),(TAny*)num1,(TAny*)num2);
       
  1341 			aMessage.Complete(err);
       
  1342 			LOGTEXT(_L("CPSession::ServiceL - Message completed"));
       
  1343 			}
       
  1344 		}
       
  1345 	else if (aMessage.Ptr2() != 0)
       
  1346 		{
       
  1347 		// command requests for data, provided 
       
  1348 		// value should be a descriptor
       
  1349 		if( ((TUint32)aMessage.Ptr3()) == 0xffffffff)
       
  1350 			{
       
  1351 			LOGTEXT(_L("ServiceL: Ptr2 != 0 && Ptr3 == 0xffffffff"));
       
  1352 	
       
  1353 			TBuf<256>* src = new TBuf<256>;
       
  1354 			src->Zero();
       
  1355 			err = Server().ControlDataL(aMessage.Function(),(TAny*)src);
       
  1356 	
       
  1357 			LOGSTRING2("Got sampler data %S",src);
       
  1358 			
       
  1359 			aMessage.WriteL(2, *src, 0);
       
  1360 	
       
  1361 			delete src;
       
  1362 			aMessage.Complete(err);
       
  1363 			LOGTEXT(_L("CPSession::ServiceL - Message completed"));
       
  1364 			}
       
  1365 		else 
       
  1366 			{
       
  1367 			LOGTEXT(_L("ServiceL: Ptr2 != 0 && Ptr3 != 0xffffffff"));
       
  1368 			
       
  1369 			TUint32 num1 = (TUint32)aMessage.Ptr2();	// containing id
       
  1370 			TBuf<256>* buffer = new TBuf<256>;		// Text data, e.g. plug-in name or description
       
  1371 
       
  1372 			LOGSTRING3("Getting data for sampler: 0x%X, buffer max len %d",num1, aMessage.GetDesMaxLength(3));
       
  1373 
       
  1374 			err = Server().ControlDataL(aMessage.Function(), (TAny*)num1, (TAny*)buffer);
       
  1375 
       
  1376 			LOGSTRING2("Got sampler data %S",&buffer);
       
  1377 			
       
  1378 			// write back to same parameter
       
  1379 			aMessage.WriteL(3, *buffer, 0);
       
  1380 			
       
  1381 			delete buffer;
       
  1382 			aMessage.Complete(err);
       
  1383 			LOGTEXT(_L("CPSession::ServiceL - Message completed"));	
       
  1384 			}
       
  1385 		}
       
  1386 	LOGTEXT(_L("CPSession::ServiceL - Message processed"));
       
  1387     }
       
  1388 
       
  1389 // --------------------------------------------------------------------------------------------
       
  1390 MProfilerController* CPServer::NewL(TInt aPriority, MProfilerEngine& aEngine)
       
  1391     {
       
  1392 	LOGTEXT(_L("CPServer::NewL - Enter"));
       
  1393 	CPServer* self = new(ELeave) CPServer(aPriority, aEngine);
       
  1394 	CleanupStack::PushL(self);
       
  1395 	self->StartL(KProfilerName);
       
  1396 	CleanupStack::Pop();
       
  1397 	LOGTEXT(_L("CPSession::NewL - Exit"));
       
  1398 	return self;
       
  1399     }
       
  1400 
       
  1401 // --------------------------------------------------------------------------------------------
       
  1402 CPServer::CPServer(TInt aPriority, MProfilerEngine& aEngine)
       
  1403 	: CServer2(aPriority), MProfilerController(aEngine)
       
  1404     {
       
  1405 
       
  1406     }
       
  1407 
       
  1408 // --------------------------------------------------------------------------------------------
       
  1409 void CPServer::Release()
       
  1410     {
       
  1411 	delete this;
       
  1412     }
       
  1413 
       
  1414 // --------------------------------------------------------------------------------------------
       
  1415 CSession2* CPServer::NewSessionL(const TVersion&,const RMessage2&) const
       
  1416     {
       
  1417 	return new(ELeave) CPSession();
       
  1418     }
       
  1419 
       
  1420 /*
       
  1421  *
       
  1422  * Static methods for controlling the profiler
       
  1423  * through command line
       
  1424  *
       
  1425  */
       
  1426 // --------------------------------------------------------------------------------------------
       
  1427 static void RunEngineServerL(const TDesC& aSettingsFile)
       
  1428     {
       
  1429 	RDebug::Print(_L("Profiler: RunEngineServerL() - Install active scheduler"));
       
  1430 	CActiveScheduler* pS = new CActiveScheduler;
       
  1431 	CActiveScheduler::Install(pS);
       
  1432 	CProfiler* p = CProfiler::NewLC(aSettingsFile);
       
  1433 	CActiveScheduler::Start();
       
  1434 	p->Finalise();
       
  1435 	CleanupStack::PopAndDestroy(p);
       
  1436 	delete pS;
       
  1437     }
       
  1438 
       
  1439 // --------------------------------------------------------------------------------------------
       
  1440 static TInt TestSettingsFile(const TDesC& configFile)
       
  1441     {
       
  1442     RFs fs;
       
  1443     LOGSTRING2("TestSettingsFile: entry %S", &configFile);
       
  1444     // check if file server can be connected
       
  1445     if (fs.Connect() != KErrNone)
       
  1446         {
       
  1447         LOGTEXT(_L("TestSettingsFile: could not connect file server"));
       
  1448         // file server couldn't be connected, return false
       
  1449         return KErrNotFound;
       
  1450         }
       
  1451 
       
  1452     // check if config file name length is > 0
       
  1453     if (configFile.Length() > 0)
       
  1454         {
       
  1455         LOGTEXT(_L("TestSettingsFile: checking location sanity"));
       
  1456         // check sanity of settings file location
       
  1457         if(BaflUtils::CheckFolder(fs, configFile) != KErrNone)
       
  1458             {
       
  1459             LOGTEXT(_L("TestSettingsFile: location sanity check failed"));
       
  1460             fs.Close();
       
  1461             return KErrGeneral;
       
  1462             }
       
  1463         }
       
  1464     else
       
  1465         {
       
  1466         // configFile length 0, return false
       
  1467         LOGTEXT(_L("TestSettingsFile: config file string null length"));
       
  1468         fs.Close();
       
  1469         return KErrNotFound;
       
  1470         }
       
  1471     // return true if tests passed
       
  1472     LOGTEXT(_L("TestSettingsFile: exiting..."));
       
  1473     fs.Close();
       
  1474     return KErrNone;
       
  1475     }
       
  1476 
       
  1477 // --------------------------------------------------------------------------------------------
       
  1478 GLDEF_C TInt E32Main()
       
  1479     {
       
  1480     // parse command line arguments 
       
  1481     TBuf<256> c;
       
  1482     TInt err(KErrNone);
       
  1483     
       
  1484     // copy the full command line with arguments into a buffer
       
  1485     User::CommandLine(c);
       
  1486 
       
  1487     TBuf<256> fileName;
       
  1488     fileName.Append(c); // only one settings param should be
       
  1489     LOGSTRING3("Filename is %S, response %d 1", &fileName, err);
       
  1490     err = TestSettingsFile(fileName);
       
  1491     if(err != KErrNone)
       
  1492         {
       
  1493         LOGSTRING3("Filename is %S, response %d 2", &fileName, err);
       
  1494         // settings file does not exist, copy null desc to file name
       
  1495         fileName.Copy(KNullDesC);
       
  1496         }
       
  1497 
       
  1498     LOGSTRING3("Filename is %S, response %d 3", &fileName, err);
       
  1499     
       
  1500     // if no command line arguments found just start the profiler process
       
  1501     __UHEAP_MARK;
       
  1502     CTrapCleanup* cleanup = CTrapCleanup::New();
       
  1503     TInt ret(KErrNoMemory);
       
  1504     if( cleanup )
       
  1505         {
       
  1506         TRAPD( ret, RunEngineServerL(fileName) );
       
  1507         RDebug::Print(_L("Profiler: E32Main() - ret %d"), ret);
       
  1508         delete cleanup;
       
  1509         } 
       
  1510     __UHEAP_MARKEND;
       
  1511 
       
  1512     return ret;
       
  1513     } 
       
  1514 
       
  1515