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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Implements flogger utility classes
23 #include "comsdbgaux.h"
24 #include "comsdbgsvr.h"
25 #include "comsdbgmessages.h"
27 _LIT8(KSubsystemWildCard, "*");
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;
40 CIniFileWatcher* CIniFileWatcher::NewL(RFs& aFs, CFileLoggerServer& aServer, const TDesC& aIniFile)
42 CIniFileWatcher* self = new(ELeave) CIniFileWatcher(aFs, aServer, aIniFile);
47 CIniFileWatcher::CIniFileWatcher(RFs& aFs, CFileLoggerServer& aServer, const TDesC& aIniFile)
48 : CActive(EPriorityStandard), iFs(aFs), iServer(aServer), iWatchedIniFile(aIniFile)
51 void CIniFileWatcher::Initialize()
53 CActiveScheduler::Add(this);
57 void CIniFileWatcher::NotifyChange()
58 /* Listen for change on the CDU ini file. */
60 iFs.NotifyChange(ENotifyAll, iStatus, iWatchedIniFile);
64 void CIniFileWatcher::RunL()
66 iStatus=KRequestPending;
68 iServer.IniFileChanged(iWatchedIniFile);
71 void CIniFileWatcher::DoCancel()
73 iFs.NotifyChangeCancel();
77 CIniFileWatcher::~CIniFileWatcher()
82 ///////////////CIniFileParser//////////////////////////////////////////////
84 TInt CIniFileParser::ParseIniFile(TDesC& aIniFile)
86 * Returns: KErrNotFound if file not found or KErrPathNotFound if path not found.
89 TRAPD(err, DoParseIniFileL(aIniFile));
93 TInt CIniFileParser::GetNextTokenAndCheck(TLex8& lex, TPtr8& tempPtr)
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.
109 tempPtr = lex.NextToken();
111 len = tempPtr.Length();
114 // lex has figured out what is left is just the EOF
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
122 if (ch == KCarriageReturn || ch == KLineFeed)
127 if (tempPtr.Length() < 2)
132 if (ch == KCarriageReturn || ch == KLineFeed)
140 void CIniFileParser::DoParseIniFileL(TDesC& aIniFile)
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
154 User::LeaveIfError(iniFile.Open(iFs, aIniFile, EFileShareAny));
156 CleanupClosePushL(iniFile);
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)
163 iLoggingMediaString = KDefaultMedia;
168 User::LeaveIfError(iniFile.Size(fileLength));
170 HBufC8* iniContents = HBufC8::NewLC(fileLength);
171 TPtr8 hbufPtr = iniContents->Des();
172 User::LeaveIfError(iniFile.Read(hbufPtr));
173 TLex8 lex(*iniContents);
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.
181 CIniLoggingPairs* iniSettings = CIniLoggingPairs::NewL();
182 CleanupStack::PushL(iniSettings);
189 ret = GetNextTokenAndCheck(lex,hbufPtr);
194 if (hbufPtr.Find(KCommentKeyword)!=KErrNotFound) //found a Comment
196 tempChar = lex.Get();
197 while (!lex.Eos() && TUint(tempChar) != KCarriageReturn && TUint(tempChar) != KLineFeed)
199 tempChar = lex.Get();
202 else if (hbufPtr.CompareF(KMediaKeyword)==0) //MediaSetting
204 User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr));
205 if (hbufPtr.Length()>KMaxMediaStringLength)
207 User::Leave(KErrGeneral);
209 iLoggingMediaString = hbufPtr;
211 else if (hbufPtr.CompareF(KLogKeyword)==0) //LOG
213 User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr));
215 if (hbufPtr.Length()>KMaxTagLength)
217 tempTag = hbufPtr.Left(KMaxTagLength);
223 User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr));
224 if (hbufPtr.Length()>KMaxTagLength)
226 tempTag2 = hbufPtr.Left(KMaxTagLength);
232 iniSettings->AddSettingL(tempTag, tempTag2);
234 else if (hbufPtr.CompareF(KForceFlushKeyword)==0) //ForceFlush
236 if (iForceFlushState == ENoValue)
238 iForceFlushState = EFlushOn;
241 else if (hbufPtr.CompareF(KLogPathKeyword) == 0) //LogPath
243 User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr));
244 if (hbufPtr.Length()>KMaxName)
246 User::Leave(KErrOverflow);
248 iLoggingPathString.Copy(hbufPtr);
250 else if (hbufPtr.CompareF(KWin32DbgPortKeyword)==0) //Win32DebugPort
252 iWin32DebugEnabled = ETrue;
255 User::Leave(KErrBadName);
262 iIniSettings = iniSettings;
263 CleanupStack::Pop(iniSettings);
264 CleanupStack::PopAndDestroy(); //iniContents
265 CleanupStack::PopAndDestroy(); //iniFile
267 if (iForceFlushState == ENoValue)
269 iForceFlushState = EFlushOff;
273 CIniFileParser* CIniFileParser::NewL(RFs& aFs)
275 return new(ELeave) CIniFileParser(aFs);
278 CIniFileParser::~CIniFileParser()
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.
288 TBool result = iIniSettings->SettingValid(aSubsystem, aComponent);
297 void CIniFileParser::LogMediaSetting(TDes8& aString) const
299 aString=iLoggingMediaString;
302 void CIniFileParser::LogPathSetting(TDes8& aString) const
304 aString.Copy(iLoggingPathString);
307 void CIniFileParser::FlushingOn(TBool& aFlushingOn) const
309 * Return whether flushing is on or off.
312 if (iForceFlushState == EFlushOn)
318 aFlushingOn = EFalse;
322 void CIniFileParser::FinaliseFlushSetting()
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.
330 if (iForceFlushState == ENoValue)
332 iForceFlushState = EFlushOff;
336 CIniFileParser::CIniFileParser(RFs& aFs)
339 iForceFlushState = ENoValue;
342 /////////////////////////////////////////////
344 CSubsystemSettings::~CSubsystemSettings()
346 iComponentArray.Close();
349 TInt CSubsystemSettings::AddComponent(const TDesC8& aComponent)
351 return iComponentArray.InsertInOrder(TNameTag(aComponent),
352 TLinearOrder<TNameTag>(CompareTComponent));
355 TBool CSubsystemSettings::ElementExistsInArray(const TDesC8& aComponent) const
357 return (iComponentArray.FindInOrder(aComponent, TLinearOrder<TNameTag>(CSubsystemSettings::CompareTComponent))!=KErrNotFound);
360 CSubsystemSettings::CSubsystemSettings(const TDesC8& aName)
361 : iSubsystemName(aName)
364 void CSubsystemSettings::SetSubsystemName(const TDesC8& aName)
366 iSubsystemName = aName;
368 TInt CSubsystemSettings::CompareCSubsystemSettings(const CSubsystemSettings& aFirst, const CSubsystemSettings& aSecond)
370 return aFirst.iSubsystemName.CompareF(aSecond.iSubsystemName);
373 TInt CSubsystemSettings::CompareTComponent(const TNameTag& aFirst, const TNameTag& aSecond)
375 return aFirst.CompareF(aSecond);
378 void CSubsystemSettings::SetWildCarded(TBool aWildCarded)
380 iSubsystemWildcarded = aWildCarded;
383 CIniLoggingPairs* CIniLoggingPairs::NewL()
385 CIniLoggingPairs* self = new(ELeave) CIniLoggingPairs;
386 if((self->iProbeSubsystem = new CSubsystemSettings(KNullDesC8)) == NULL)
389 User::Leave(KErrNoMemory);
394 CIniLoggingPairs::~CIniLoggingPairs()
396 iSubsystems.ResetAndDestroy();
397 delete iProbeSubsystem;
400 void CIniLoggingPairs::AddSettingL(const TDesC8& aSubsystem, const TDesC8& aComponent)
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)
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);
416 ASSERT(subsysPos >= KErrNone);
417 subsystemSetting = iSubsystems[subsysPos];
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)
422 subsystemSetting->SetWildCarded(ETrue);
426 if ((err = subsystemSetting->AddComponent(aComponent))!=KErrNone)
428 if (subsystemIsNewInList)
430 delete subsystemSetting;
431 iSubsystems.Remove(subsysPos);
437 TBool CIniLoggingPairs::SettingValid(const TDesC8& aSubsystem, const TDesC8& aComponent) const
439 iProbeSubsystem->SetSubsystemName(aSubsystem);
441 TInt positionInArray;
442 if (iSubsystems.FindInOrder(iProbeSubsystem, positionInArray, TLinearOrder<CSubsystemSettings>(CSubsystemSettings::CompareCSubsystemSettings))==KErrNotFound)
444 settingValid = EFalse;
446 else if (iSubsystems[positionInArray]->IsWildCarded())
448 settingValid = ETrue;
452 settingValid = iSubsystems[positionInArray]->ElementExistsInArray(aComponent);
457 /////////////////////////////////////////////
459 CTimeManager* CTimeManager::NewL(MLogArrayAccess& aArrayAccess)
461 CTimeManager* self = new(ELeave) CTimeManager(aArrayAccess);
462 CleanupStack::PushL(self);
464 CleanupStack::Pop(self);
468 void CTimeManager::Beat()
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.
474 iTime+=TTimeIntervalSeconds(1);
478 void CTimeManager::Synchronize()
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.
489 CTimeManager::CTimeManager(MLogArrayAccess& aArrayAccess)
490 : iArrayAccess(aArrayAccess)
493 void CTimeManager::SendTimeUpdate()
495 * append to queue a time update message
498 CTimeUpdateMessage* timeMessage = new CTimeUpdateMessage(iTime);
501 if (iArrayAccess.AppendAndGiveOwnership(timeMessage)!=KErrNone)
503 delete timeMessage; //We failed to get a time update in. Ahh well.
508 void CTimeManager::ConstructL()
510 * Start heartbeat active object to trigger every second, passing in this class
511 * for kernel to callback to.
515 iHeartbeat = CHeartbeat::NewL(EPriorityHigh);
516 iHeartbeat->Start(ETwelveOClock, this); // 12 1/12th intervals
520 CTimeManager::~CTimeManager()