traceservices/commsdebugutility/SSVR/comsdbgaux.cpp
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements flogger utility classes
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include "comsdbgaux.h"
       
    24 #include "comsdbgsvr.h"
       
    25 #include "comsdbgmessages.h"
       
    26 
       
    27 _LIT8(KSubsystemWildCard, "*");
       
    28 
       
    29 _LIT8(KLogKeyword, "Log");
       
    30 _LIT8(KMediaKeyword, "Media");
       
    31 _LIT8(KWin32DbgPortKeyword, "Win32Debug");
       
    32 _LIT8(KLogPathKeyword, "LogPath");
       
    33 _LIT8(KCommentKeyword, "//");
       
    34 _LIT8(KForceFlushKeyword, "Synchronous");
       
    35 const TUint8 KCarriageReturn = 0x000D;
       
    36 const TUint8 KLineFeed = 0x000A;
       
    37 
       
    38 
       
    39 
       
    40 CIniFileWatcher* CIniFileWatcher::NewL(RFs& aFs, CFileLoggerServer& aServer, const TDesC& aIniFile)
       
    41 	{
       
    42 	CIniFileWatcher* self = new(ELeave) CIniFileWatcher(aFs, aServer, aIniFile);
       
    43 	self->Initialize();
       
    44 	return self;
       
    45 	}
       
    46 
       
    47 CIniFileWatcher::CIniFileWatcher(RFs& aFs, CFileLoggerServer& aServer, const TDesC& aIniFile)
       
    48 : CActive(EPriorityStandard), iFs(aFs), iServer(aServer), iWatchedIniFile(aIniFile)
       
    49 {}
       
    50 
       
    51 void CIniFileWatcher::Initialize()
       
    52   	{
       
    53   	CActiveScheduler::Add(this);
       
    54   	NotifyChange();
       
    55   	}
       
    56 
       
    57 void CIniFileWatcher::NotifyChange()
       
    58 /* Listen for change on the CDU ini file. */
       
    59     {
       
    60     iFs.NotifyChange(ENotifyAll, iStatus, iWatchedIniFile);
       
    61   	SetActive();
       
    62   	}
       
    63 
       
    64 void CIniFileWatcher::RunL()
       
    65 	{
       
    66 	iStatus=KRequestPending;
       
    67    NotifyChange();
       
    68 	iServer.IniFileChanged(iWatchedIniFile);
       
    69 	}
       
    70 
       
    71 void CIniFileWatcher::DoCancel()
       
    72 	{
       
    73 	iFs.NotifyChangeCancel();
       
    74 	}
       
    75 
       
    76 
       
    77 CIniFileWatcher::~CIniFileWatcher()
       
    78 	{
       
    79 	Cancel();
       
    80 	}
       
    81 
       
    82 ///////////////CIniFileParser//////////////////////////////////////////////
       
    83 
       
    84 TInt CIniFileParser::ParseIniFile(TDesC& aIniFile)
       
    85 /*
       
    86  * Returns: KErrNotFound if file not found or KErrPathNotFound if path not found.
       
    87  */
       
    88 	{
       
    89 	TRAPD(err, DoParseIniFileL(aIniFile));
       
    90 	return err;
       
    91 	}
       
    92 
       
    93 TInt CIniFileParser::GetNextTokenAndCheck(TLex8& lex, TPtr8& tempPtr)
       
    94 /*
       
    95 Gets next token and ensures the token is simply not the EOF or a linefeed.
       
    96 lex is the lexical string to get the next token from.
       
    97 tempPtr points to the next token
       
    98 Returns KErrGeneral if token is bad or if we've already read past the end.
       
    99 */
       
   100 	{
       
   101 	TUint8 ch;
       
   102 	TInt len;
       
   103 
       
   104 	if (lex.Eos())
       
   105 		{
       
   106 		return KErrGeneral;
       
   107 		}
       
   108 	
       
   109 	tempPtr = lex.NextToken();
       
   110 
       
   111 	len = tempPtr.Length();
       
   112 	if (len == 0)
       
   113 		{
       
   114 		// lex has figured out what is left is just the EOF
       
   115 		return KErrGeneral;
       
   116 		}
       
   117 
       
   118 	// this next part may be superfluous but we've had so much strife with
       
   119 	// the parser thus far that for now we're leaving it in
       
   120 
       
   121 	ch = tempPtr[0];
       
   122 	if (ch == KCarriageReturn || ch == KLineFeed)
       
   123 		{
       
   124 		return KErrGeneral;
       
   125 		}
       
   126 
       
   127 	if (tempPtr.Length() < 2)
       
   128 		{
       
   129 		return KErrNone;
       
   130 		}
       
   131 	ch = tempPtr[1];
       
   132 	if (ch == KCarriageReturn || ch == KLineFeed)
       
   133 		{
       
   134 		return KErrGeneral;
       
   135 		}
       
   136 
       
   137 	return KErrNone;
       
   138 	}
       
   139 	
       
   140 void CIniFileParser::DoParseIniFileL(TDesC& aIniFile)
       
   141 /*
       
   142  * 
       
   143  * The force flush state is only updated if it is not already set to something other
       
   144  * than ENoValue. If force flush option is not found in ini file, force flush is set
       
   145  * to off.
       
   146  */
       
   147 	{
       
   148 
       
   149 	TInt fileLength;
       
   150 	TInt ret = KErrNone;
       
   151 	RFile iniFile;
       
   152 
       
   153 	// Open file
       
   154 	User::LeaveIfError(iniFile.Open(iFs, aIniFile, EFileShareAny));
       
   155 		
       
   156 	CleanupClosePushL(iniFile);
       
   157 	
       
   158 	// as we have been able to open the file, set the media to default.
       
   159 	// If the ini file is parsed correctly, this then gets overwritten.
       
   160 	// Otherwise the caller should pass thru a mesg to get the default enabled.
       
   161 	if (iLoggingMediaString.Length() == 0)
       
   162 		{
       
   163 		iLoggingMediaString = KDefaultMedia;
       
   164 		}
       
   165 		
       
   166 	
       
   167 
       
   168 	User::LeaveIfError(iniFile.Size(fileLength));
       
   169 
       
   170 	HBufC8* iniContents = HBufC8::NewLC(fileLength);
       
   171 	TPtr8 hbufPtr = iniContents->Des();
       
   172 	User::LeaveIfError(iniFile.Read(hbufPtr));
       
   173 	TLex8 lex(*iniContents);
       
   174 
       
   175 	//OK, file is open and ready for parsing. Make a tempory array and if there is a
       
   176 	//problem in the ini file leave settings as they were, leave, and
       
   177 	//the error will get picked up.
       
   178 
       
   179 	delete iIniSettings;
       
   180 	iIniSettings = NULL;
       
   181 	CIniLoggingPairs* iniSettings = CIniLoggingPairs::NewL();
       
   182 	CleanupStack::PushL(iniSettings);
       
   183 	TNameTag tempTag;
       
   184 	TNameTag tempTag2;
       
   185 	TChar  tempChar;
       
   186 
       
   187 	FOREVER
       
   188 		{
       
   189 		ret = GetNextTokenAndCheck(lex,hbufPtr);
       
   190 		if (ret != KErrNone)
       
   191 			{
       
   192 			break;
       
   193 			}
       
   194 		if (hbufPtr.Find(KCommentKeyword)!=KErrNotFound)		//found a Comment
       
   195 			{
       
   196 			tempChar = lex.Get();
       
   197 			while (!lex.Eos() && TUint(tempChar) != KCarriageReturn && TUint(tempChar) != KLineFeed)
       
   198 				{
       
   199 				tempChar = lex.Get();
       
   200 				}
       
   201 			}
       
   202 		else if (hbufPtr.CompareF(KMediaKeyword)==0)		//MediaSetting
       
   203 			{
       
   204 			User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr));
       
   205 			if (hbufPtr.Length()>KMaxMediaStringLength)
       
   206 				{
       
   207 				User::Leave(KErrGeneral);
       
   208 				}
       
   209 			iLoggingMediaString = hbufPtr;
       
   210 			}
       
   211 		else if (hbufPtr.CompareF(KLogKeyword)==0)		//LOG
       
   212 			{
       
   213 			User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr));
       
   214 
       
   215 			if (hbufPtr.Length()>KMaxTagLength)
       
   216 				{
       
   217 				tempTag = hbufPtr.Left(KMaxTagLength);
       
   218 				}
       
   219 			else
       
   220 				{
       
   221 				tempTag = hbufPtr;
       
   222 				}
       
   223 			User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr));
       
   224 			if (hbufPtr.Length()>KMaxTagLength)
       
   225 				{
       
   226 				tempTag2 = hbufPtr.Left(KMaxTagLength);
       
   227 				}
       
   228 			else
       
   229 				{
       
   230 				tempTag2 = hbufPtr;
       
   231 				}
       
   232 			iniSettings->AddSettingL(tempTag, tempTag2);
       
   233 			}
       
   234 		else if (hbufPtr.CompareF(KForceFlushKeyword)==0)		//ForceFlush
       
   235 			{
       
   236 			if (iForceFlushState == ENoValue)
       
   237 				{
       
   238 				iForceFlushState = EFlushOn;
       
   239 				}
       
   240 			}
       
   241 		else if (hbufPtr.CompareF(KLogPathKeyword) == 0)		//LogPath
       
   242 			{
       
   243 			User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr));
       
   244 			if (hbufPtr.Length()>KMaxName)
       
   245 				{
       
   246 				User::Leave(KErrOverflow);
       
   247 				}
       
   248 			iLoggingPathString.Copy(hbufPtr);
       
   249 			}
       
   250 		else if (hbufPtr.CompareF(KWin32DbgPortKeyword)==0)		//Win32DebugPort
       
   251 			{
       
   252 			iWin32DebugEnabled = ETrue;
       
   253 			}
       
   254 		else
       
   255 			User::Leave(KErrBadName);
       
   256 
       
   257 		if (lex.Eos())
       
   258 			{
       
   259 			break;
       
   260 			}
       
   261 		}
       
   262 	iIniSettings = iniSettings;
       
   263 	CleanupStack::Pop(iniSettings);
       
   264 	CleanupStack::PopAndDestroy();	//iniContents
       
   265 	CleanupStack::PopAndDestroy();	//iniFile
       
   266 
       
   267 	if (iForceFlushState == ENoValue)
       
   268 		{
       
   269 		iForceFlushState = EFlushOff;
       
   270 		}
       
   271 	}
       
   272 
       
   273 CIniFileParser* CIniFileParser::NewL(RFs& aFs)
       
   274 	{
       
   275 	return new(ELeave) CIniFileParser(aFs);
       
   276 	}
       
   277 
       
   278 CIniFileParser::~CIniFileParser()
       
   279 	{
       
   280 	delete iIniSettings;
       
   281 	}
       
   282 
       
   283 TBool CIniFileParser::LogValid(const TDesC8& aSubsystem, const TDesC8& aComponent) const
       
   284 // If no memory, this operation will return EFalse so user will not get logs, nor a msg to say so.
       
   285 	{
       
   286 	if (iIniSettings)
       
   287 		{
       
   288 		TBool result = iIniSettings->SettingValid(aSubsystem, aComponent);
       
   289 		return result;
       
   290 		}
       
   291 	else
       
   292 		{
       
   293 		return EFalse;
       
   294 		}
       
   295 	}
       
   296 
       
   297 void CIniFileParser::LogMediaSetting(TDes8& aString) const
       
   298 	{
       
   299 	aString=iLoggingMediaString;
       
   300 	}
       
   301 
       
   302 void CIniFileParser::LogPathSetting(TDes8& aString) const
       
   303 	{
       
   304 	aString.Copy(iLoggingPathString);
       
   305 	}
       
   306 
       
   307 void CIniFileParser::FlushingOn(TBool& aFlushingOn) const
       
   308 /*
       
   309  * Return whether flushing is on or off.
       
   310  */
       
   311 	{
       
   312 	if (iForceFlushState == EFlushOn)
       
   313 		{
       
   314 		aFlushingOn = ETrue;
       
   315 		}
       
   316 	else
       
   317 		{
       
   318 		aFlushingOn = EFalse;
       
   319 		}
       
   320 	}
       
   321 
       
   322 void CIniFileParser::FinaliseFlushSetting()
       
   323 /*
       
   324  * It is not safe to switch flush modes once we begin logging, so this is called
       
   325  * to let fileparser know that system is about to commence logging.
       
   326  * If the file parser has still not determined whether it should be logging or not,
       
   327  * then set flushing to off.
       
   328  */
       
   329 	{
       
   330 	if (iForceFlushState == ENoValue)
       
   331 		{
       
   332 		iForceFlushState = EFlushOff;
       
   333 		}
       
   334 	}
       
   335 
       
   336 CIniFileParser::CIniFileParser(RFs& aFs)
       
   337 : iFs(aFs)
       
   338 	{
       
   339 	iForceFlushState = ENoValue;
       
   340 	}
       
   341 
       
   342 /////////////////////////////////////////////
       
   343 
       
   344 CSubsystemSettings::~CSubsystemSettings()
       
   345 	{
       
   346 	iComponentArray.Close();
       
   347 	}
       
   348 
       
   349 TInt CSubsystemSettings::AddComponent(const TDesC8& aComponent)
       
   350 	{
       
   351 	return iComponentArray.InsertInOrder(TNameTag(aComponent),
       
   352 		TLinearOrder<TNameTag>(CompareTComponent));
       
   353 	}
       
   354 
       
   355 TBool CSubsystemSettings::ElementExistsInArray(const TDesC8& aComponent) const
       
   356 	{
       
   357 	return (iComponentArray.FindInOrder(aComponent, TLinearOrder<TNameTag>(CSubsystemSettings::CompareTComponent))!=KErrNotFound);
       
   358 	}
       
   359 
       
   360 CSubsystemSettings::CSubsystemSettings(const TDesC8& aName)
       
   361 : iSubsystemName(aName)
       
   362 	{}
       
   363 
       
   364 void CSubsystemSettings::SetSubsystemName(const TDesC8& aName)
       
   365 	{
       
   366 	iSubsystemName = aName;
       
   367 	}
       
   368 TInt CSubsystemSettings::CompareCSubsystemSettings(const CSubsystemSettings& aFirst, const CSubsystemSettings& aSecond)
       
   369 	{
       
   370 	return aFirst.iSubsystemName.CompareF(aSecond.iSubsystemName);
       
   371 	}
       
   372 
       
   373 TInt CSubsystemSettings::CompareTComponent(const TNameTag& aFirst, const TNameTag& aSecond)
       
   374 	{
       
   375 	return aFirst.CompareF(aSecond);
       
   376 	}
       
   377 
       
   378 void CSubsystemSettings::SetWildCarded(TBool aWildCarded)
       
   379 	{
       
   380 	iSubsystemWildcarded = aWildCarded;
       
   381 	}
       
   382 
       
   383 CIniLoggingPairs* CIniLoggingPairs::NewL()
       
   384 	{
       
   385 	CIniLoggingPairs* self = new(ELeave) CIniLoggingPairs;
       
   386 	if((self->iProbeSubsystem = new CSubsystemSettings(KNullDesC8)) == NULL)
       
   387 		{
       
   388 		delete self;
       
   389 		User::Leave(KErrNoMemory);
       
   390 		}
       
   391 	return self;
       
   392 	}
       
   393 	
       
   394 CIniLoggingPairs::~CIniLoggingPairs()
       
   395 	{
       
   396 	iSubsystems.ResetAndDestroy();
       
   397 	delete iProbeSubsystem;
       
   398 	}
       
   399 
       
   400 void CIniLoggingPairs::AddSettingL(const TDesC8& aSubsystem, const TDesC8& aComponent)
       
   401 	{
       
   402 	TBool subsystemIsNewInList(EFalse);
       
   403 	CSubsystemSettings* subsystemSetting;
       
   404 	iProbeSubsystem->SetSubsystemName(aSubsystem);
       
   405 	TInt subsysPos = iSubsystems.FindInOrder(iProbeSubsystem, TLinearOrder<CSubsystemSettings>(CSubsystemSettings::CompareCSubsystemSettings));
       
   406 	if (subsysPos == KErrNotFound)
       
   407 		{
       
   408 		subsystemSetting = new(ELeave) CSubsystemSettings(aSubsystem);
       
   409 		CleanupStack::PushL(subsystemSetting);
       
   410 		iSubsystems.InsertInOrderL(subsystemSetting, TLinearOrder<CSubsystemSettings>(CSubsystemSettings::CompareCSubsystemSettings));
       
   411 		subsystemIsNewInList = ETrue;
       
   412 		CleanupStack::Pop(subsystemSetting);
       
   413 		}
       
   414 	else 
       
   415 		{
       
   416 		ASSERT(subsysPos >= KErrNone);
       
   417 		subsystemSetting = iSubsystems[subsysPos];
       
   418 		}
       
   419 	//subsystemSetting is now owned in the array, so we don't need to worry about any leaves from here on.
       
   420 	if (aComponent.CompareF(KSubsystemWildCard)==0)
       
   421 		{
       
   422 		subsystemSetting->SetWildCarded(ETrue);
       
   423 		return;
       
   424 		}
       
   425 	TInt err;
       
   426 	if ((err = subsystemSetting->AddComponent(aComponent))!=KErrNone)
       
   427 		{
       
   428 		if (subsystemIsNewInList)
       
   429 			{
       
   430 			delete subsystemSetting;
       
   431 			iSubsystems.Remove(subsysPos);
       
   432 			User::Leave(err);
       
   433 			}
       
   434 		}
       
   435 	}
       
   436 
       
   437 TBool CIniLoggingPairs::SettingValid(const TDesC8& aSubsystem, const TDesC8& aComponent) const
       
   438 	{
       
   439 	iProbeSubsystem->SetSubsystemName(aSubsystem);
       
   440 	TBool settingValid;
       
   441 	TInt positionInArray;
       
   442 	if (iSubsystems.FindInOrder(iProbeSubsystem, positionInArray, TLinearOrder<CSubsystemSettings>(CSubsystemSettings::CompareCSubsystemSettings))==KErrNotFound)
       
   443 		{
       
   444 		settingValid = EFalse;
       
   445 		}
       
   446 	else if (iSubsystems[positionInArray]->IsWildCarded())
       
   447 		{
       
   448 		settingValid = ETrue;
       
   449 		}
       
   450 	else
       
   451 		{
       
   452 		settingValid = iSubsystems[positionInArray]->ElementExistsInArray(aComponent);
       
   453 		}
       
   454 	return settingValid;
       
   455 	}
       
   456 
       
   457 /////////////////////////////////////////////
       
   458 
       
   459 CTimeManager* CTimeManager::NewL(MLogArrayAccess& aArrayAccess)
       
   460 	{
       
   461 	CTimeManager* self = new(ELeave) CTimeManager(aArrayAccess);
       
   462 	CleanupStack::PushL(self);
       
   463 	self->ConstructL();
       
   464 	CleanupStack::Pop(self);
       
   465 	return self;
       
   466 	}
       
   467 
       
   468 void CTimeManager::Beat()
       
   469 /*
       
   470  * Called by kernel every second if we're synchronised.
       
   471  * Updates the variable recording the current time, and sends it to the log queue.
       
   472  */
       
   473 	{
       
   474 	iTime+=TTimeIntervalSeconds(1);
       
   475 	SendTimeUpdate();
       
   476 	}
       
   477 
       
   478 void CTimeManager::Synchronize()
       
   479 /*
       
   480  * Called by kernel when it finds synchronisation is lost (a heartbeat was missed - maybe
       
   481  * device has been off for a while).
       
   482  * Updates the variable recording the current time, and sends it to the log queue.
       
   483  */
       
   484 	{
       
   485 	iTime.HomeTime();
       
   486 	SendTimeUpdate();
       
   487 	}
       
   488 
       
   489 CTimeManager::CTimeManager(MLogArrayAccess& aArrayAccess)
       
   490 : iArrayAccess(aArrayAccess)
       
   491 {}
       
   492 
       
   493 void CTimeManager::SendTimeUpdate()
       
   494 /*
       
   495  * append to queue a time update message
       
   496  */
       
   497 	{
       
   498 	CTimeUpdateMessage* timeMessage = new CTimeUpdateMessage(iTime);
       
   499 	if (timeMessage)
       
   500 		{
       
   501 		if (iArrayAccess.AppendAndGiveOwnership(timeMessage)!=KErrNone)
       
   502 			{
       
   503 			delete timeMessage;	//We failed to get a time update in. Ahh well. 
       
   504 			}
       
   505 		}
       
   506 	}
       
   507 
       
   508 void CTimeManager::ConstructL()
       
   509 /*
       
   510  * Start heartbeat active object to trigger every second, passing in this class
       
   511  * for kernel to callback to.
       
   512  */
       
   513 	{
       
   514 	iTime.HomeTime();
       
   515 	iHeartbeat = CHeartbeat::NewL(EPriorityHigh);
       
   516 	iHeartbeat->Start(ETwelveOClock, this); // 12 1/12th intervals
       
   517 	SendTimeUpdate();
       
   518 	}
       
   519 
       
   520 CTimeManager::~CTimeManager()
       
   521 	{
       
   522 	delete iHeartbeat;
       
   523 	}
       
   524