os/persistentdata/traceservices/commsdebugutility/SSVR/comsdbgaux.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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