diff -r 000000000000 -r 08ec8eefde2f traceservices/commsdebugutility/SSVR/comsdbgaux.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/traceservices/commsdebugutility/SSVR/comsdbgaux.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,524 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Implements flogger utility classes +// +// + +/** + @file + @internalComponent +*/ + +#include "comsdbgaux.h" +#include "comsdbgsvr.h" +#include "comsdbgmessages.h" + +_LIT8(KSubsystemWildCard, "*"); + +_LIT8(KLogKeyword, "Log"); +_LIT8(KMediaKeyword, "Media"); +_LIT8(KWin32DbgPortKeyword, "Win32Debug"); +_LIT8(KLogPathKeyword, "LogPath"); +_LIT8(KCommentKeyword, "//"); +_LIT8(KForceFlushKeyword, "Synchronous"); +const TUint8 KCarriageReturn = 0x000D; +const TUint8 KLineFeed = 0x000A; + + + +CIniFileWatcher* CIniFileWatcher::NewL(RFs& aFs, CFileLoggerServer& aServer, const TDesC& aIniFile) + { + CIniFileWatcher* self = new(ELeave) CIniFileWatcher(aFs, aServer, aIniFile); + self->Initialize(); + return self; + } + +CIniFileWatcher::CIniFileWatcher(RFs& aFs, CFileLoggerServer& aServer, const TDesC& aIniFile) +: CActive(EPriorityStandard), iFs(aFs), iServer(aServer), iWatchedIniFile(aIniFile) +{} + +void CIniFileWatcher::Initialize() + { + CActiveScheduler::Add(this); + NotifyChange(); + } + +void CIniFileWatcher::NotifyChange() +/* Listen for change on the CDU ini file. */ + { + iFs.NotifyChange(ENotifyAll, iStatus, iWatchedIniFile); + SetActive(); + } + +void CIniFileWatcher::RunL() + { + iStatus=KRequestPending; + NotifyChange(); + iServer.IniFileChanged(iWatchedIniFile); + } + +void CIniFileWatcher::DoCancel() + { + iFs.NotifyChangeCancel(); + } + + +CIniFileWatcher::~CIniFileWatcher() + { + Cancel(); + } + +///////////////CIniFileParser////////////////////////////////////////////// + +TInt CIniFileParser::ParseIniFile(TDesC& aIniFile) +/* + * Returns: KErrNotFound if file not found or KErrPathNotFound if path not found. + */ + { + TRAPD(err, DoParseIniFileL(aIniFile)); + return err; + } + +TInt CIniFileParser::GetNextTokenAndCheck(TLex8& lex, TPtr8& tempPtr) +/* +Gets next token and ensures the token is simply not the EOF or a linefeed. +lex is the lexical string to get the next token from. +tempPtr points to the next token +Returns KErrGeneral if token is bad or if we've already read past the end. +*/ + { + TUint8 ch; + TInt len; + + if (lex.Eos()) + { + return KErrGeneral; + } + + tempPtr = lex.NextToken(); + + len = tempPtr.Length(); + if (len == 0) + { + // lex has figured out what is left is just the EOF + return KErrGeneral; + } + + // this next part may be superfluous but we've had so much strife with + // the parser thus far that for now we're leaving it in + + ch = tempPtr[0]; + if (ch == KCarriageReturn || ch == KLineFeed) + { + return KErrGeneral; + } + + if (tempPtr.Length() < 2) + { + return KErrNone; + } + ch = tempPtr[1]; + if (ch == KCarriageReturn || ch == KLineFeed) + { + return KErrGeneral; + } + + return KErrNone; + } + +void CIniFileParser::DoParseIniFileL(TDesC& aIniFile) +/* + * + * The force flush state is only updated if it is not already set to something other + * than ENoValue. If force flush option is not found in ini file, force flush is set + * to off. + */ + { + + TInt fileLength; + TInt ret = KErrNone; + RFile iniFile; + + // Open file + User::LeaveIfError(iniFile.Open(iFs, aIniFile, EFileShareAny)); + + CleanupClosePushL(iniFile); + + // as we have been able to open the file, set the media to default. + // If the ini file is parsed correctly, this then gets overwritten. + // Otherwise the caller should pass thru a mesg to get the default enabled. + if (iLoggingMediaString.Length() == 0) + { + iLoggingMediaString = KDefaultMedia; + } + + + + User::LeaveIfError(iniFile.Size(fileLength)); + + HBufC8* iniContents = HBufC8::NewLC(fileLength); + TPtr8 hbufPtr = iniContents->Des(); + User::LeaveIfError(iniFile.Read(hbufPtr)); + TLex8 lex(*iniContents); + + //OK, file is open and ready for parsing. Make a tempory array and if there is a + //problem in the ini file leave settings as they were, leave, and + //the error will get picked up. + + delete iIniSettings; + iIniSettings = NULL; + CIniLoggingPairs* iniSettings = CIniLoggingPairs::NewL(); + CleanupStack::PushL(iniSettings); + TNameTag tempTag; + TNameTag tempTag2; + TChar tempChar; + + FOREVER + { + ret = GetNextTokenAndCheck(lex,hbufPtr); + if (ret != KErrNone) + { + break; + } + if (hbufPtr.Find(KCommentKeyword)!=KErrNotFound) //found a Comment + { + tempChar = lex.Get(); + while (!lex.Eos() && TUint(tempChar) != KCarriageReturn && TUint(tempChar) != KLineFeed) + { + tempChar = lex.Get(); + } + } + else if (hbufPtr.CompareF(KMediaKeyword)==0) //MediaSetting + { + User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr)); + if (hbufPtr.Length()>KMaxMediaStringLength) + { + User::Leave(KErrGeneral); + } + iLoggingMediaString = hbufPtr; + } + else if (hbufPtr.CompareF(KLogKeyword)==0) //LOG + { + User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr)); + + if (hbufPtr.Length()>KMaxTagLength) + { + tempTag = hbufPtr.Left(KMaxTagLength); + } + else + { + tempTag = hbufPtr; + } + User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr)); + if (hbufPtr.Length()>KMaxTagLength) + { + tempTag2 = hbufPtr.Left(KMaxTagLength); + } + else + { + tempTag2 = hbufPtr; + } + iniSettings->AddSettingL(tempTag, tempTag2); + } + else if (hbufPtr.CompareF(KForceFlushKeyword)==0) //ForceFlush + { + if (iForceFlushState == ENoValue) + { + iForceFlushState = EFlushOn; + } + } + else if (hbufPtr.CompareF(KLogPathKeyword) == 0) //LogPath + { + User::LeaveIfError(GetNextTokenAndCheck(lex,hbufPtr)); + if (hbufPtr.Length()>KMaxName) + { + User::Leave(KErrOverflow); + } + iLoggingPathString.Copy(hbufPtr); + } + else if (hbufPtr.CompareF(KWin32DbgPortKeyword)==0) //Win32DebugPort + { + iWin32DebugEnabled = ETrue; + } + else + User::Leave(KErrBadName); + + if (lex.Eos()) + { + break; + } + } + iIniSettings = iniSettings; + CleanupStack::Pop(iniSettings); + CleanupStack::PopAndDestroy(); //iniContents + CleanupStack::PopAndDestroy(); //iniFile + + if (iForceFlushState == ENoValue) + { + iForceFlushState = EFlushOff; + } + } + +CIniFileParser* CIniFileParser::NewL(RFs& aFs) + { + return new(ELeave) CIniFileParser(aFs); + } + +CIniFileParser::~CIniFileParser() + { + delete iIniSettings; + } + +TBool CIniFileParser::LogValid(const TDesC8& aSubsystem, const TDesC8& aComponent) const +// If no memory, this operation will return EFalse so user will not get logs, nor a msg to say so. + { + if (iIniSettings) + { + TBool result = iIniSettings->SettingValid(aSubsystem, aComponent); + return result; + } + else + { + return EFalse; + } + } + +void CIniFileParser::LogMediaSetting(TDes8& aString) const + { + aString=iLoggingMediaString; + } + +void CIniFileParser::LogPathSetting(TDes8& aString) const + { + aString.Copy(iLoggingPathString); + } + +void CIniFileParser::FlushingOn(TBool& aFlushingOn) const +/* + * Return whether flushing is on or off. + */ + { + if (iForceFlushState == EFlushOn) + { + aFlushingOn = ETrue; + } + else + { + aFlushingOn = EFalse; + } + } + +void CIniFileParser::FinaliseFlushSetting() +/* + * It is not safe to switch flush modes once we begin logging, so this is called + * to let fileparser know that system is about to commence logging. + * If the file parser has still not determined whether it should be logging or not, + * then set flushing to off. + */ + { + if (iForceFlushState == ENoValue) + { + iForceFlushState = EFlushOff; + } + } + +CIniFileParser::CIniFileParser(RFs& aFs) +: iFs(aFs) + { + iForceFlushState = ENoValue; + } + +///////////////////////////////////////////// + +CSubsystemSettings::~CSubsystemSettings() + { + iComponentArray.Close(); + } + +TInt CSubsystemSettings::AddComponent(const TDesC8& aComponent) + { + return iComponentArray.InsertInOrder(TNameTag(aComponent), + TLinearOrder(CompareTComponent)); + } + +TBool CSubsystemSettings::ElementExistsInArray(const TDesC8& aComponent) const + { + return (iComponentArray.FindInOrder(aComponent, TLinearOrder(CSubsystemSettings::CompareTComponent))!=KErrNotFound); + } + +CSubsystemSettings::CSubsystemSettings(const TDesC8& aName) +: iSubsystemName(aName) + {} + +void CSubsystemSettings::SetSubsystemName(const TDesC8& aName) + { + iSubsystemName = aName; + } +TInt CSubsystemSettings::CompareCSubsystemSettings(const CSubsystemSettings& aFirst, const CSubsystemSettings& aSecond) + { + return aFirst.iSubsystemName.CompareF(aSecond.iSubsystemName); + } + +TInt CSubsystemSettings::CompareTComponent(const TNameTag& aFirst, const TNameTag& aSecond) + { + return aFirst.CompareF(aSecond); + } + +void CSubsystemSettings::SetWildCarded(TBool aWildCarded) + { + iSubsystemWildcarded = aWildCarded; + } + +CIniLoggingPairs* CIniLoggingPairs::NewL() + { + CIniLoggingPairs* self = new(ELeave) CIniLoggingPairs; + if((self->iProbeSubsystem = new CSubsystemSettings(KNullDesC8)) == NULL) + { + delete self; + User::Leave(KErrNoMemory); + } + return self; + } + +CIniLoggingPairs::~CIniLoggingPairs() + { + iSubsystems.ResetAndDestroy(); + delete iProbeSubsystem; + } + +void CIniLoggingPairs::AddSettingL(const TDesC8& aSubsystem, const TDesC8& aComponent) + { + TBool subsystemIsNewInList(EFalse); + CSubsystemSettings* subsystemSetting; + iProbeSubsystem->SetSubsystemName(aSubsystem); + TInt subsysPos = iSubsystems.FindInOrder(iProbeSubsystem, TLinearOrder(CSubsystemSettings::CompareCSubsystemSettings)); + if (subsysPos == KErrNotFound) + { + subsystemSetting = new(ELeave) CSubsystemSettings(aSubsystem); + CleanupStack::PushL(subsystemSetting); + iSubsystems.InsertInOrderL(subsystemSetting, TLinearOrder(CSubsystemSettings::CompareCSubsystemSettings)); + subsystemIsNewInList = ETrue; + CleanupStack::Pop(subsystemSetting); + } + else + { + ASSERT(subsysPos >= KErrNone); + subsystemSetting = iSubsystems[subsysPos]; + } + //subsystemSetting is now owned in the array, so we don't need to worry about any leaves from here on. + if (aComponent.CompareF(KSubsystemWildCard)==0) + { + subsystemSetting->SetWildCarded(ETrue); + return; + } + TInt err; + if ((err = subsystemSetting->AddComponent(aComponent))!=KErrNone) + { + if (subsystemIsNewInList) + { + delete subsystemSetting; + iSubsystems.Remove(subsysPos); + User::Leave(err); + } + } + } + +TBool CIniLoggingPairs::SettingValid(const TDesC8& aSubsystem, const TDesC8& aComponent) const + { + iProbeSubsystem->SetSubsystemName(aSubsystem); + TBool settingValid; + TInt positionInArray; + if (iSubsystems.FindInOrder(iProbeSubsystem, positionInArray, TLinearOrder(CSubsystemSettings::CompareCSubsystemSettings))==KErrNotFound) + { + settingValid = EFalse; + } + else if (iSubsystems[positionInArray]->IsWildCarded()) + { + settingValid = ETrue; + } + else + { + settingValid = iSubsystems[positionInArray]->ElementExistsInArray(aComponent); + } + return settingValid; + } + +///////////////////////////////////////////// + +CTimeManager* CTimeManager::NewL(MLogArrayAccess& aArrayAccess) + { + CTimeManager* self = new(ELeave) CTimeManager(aArrayAccess); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CTimeManager::Beat() +/* + * Called by kernel every second if we're synchronised. + * Updates the variable recording the current time, and sends it to the log queue. + */ + { + iTime+=TTimeIntervalSeconds(1); + SendTimeUpdate(); + } + +void CTimeManager::Synchronize() +/* + * Called by kernel when it finds synchronisation is lost (a heartbeat was missed - maybe + * device has been off for a while). + * Updates the variable recording the current time, and sends it to the log queue. + */ + { + iTime.HomeTime(); + SendTimeUpdate(); + } + +CTimeManager::CTimeManager(MLogArrayAccess& aArrayAccess) +: iArrayAccess(aArrayAccess) +{} + +void CTimeManager::SendTimeUpdate() +/* + * append to queue a time update message + */ + { + CTimeUpdateMessage* timeMessage = new CTimeUpdateMessage(iTime); + if (timeMessage) + { + if (iArrayAccess.AppendAndGiveOwnership(timeMessage)!=KErrNone) + { + delete timeMessage; //We failed to get a time update in. Ahh well. + } + } + } + +void CTimeManager::ConstructL() +/* + * Start heartbeat active object to trigger every second, passing in this class + * for kernel to callback to. + */ + { + iTime.HomeTime(); + iHeartbeat = CHeartbeat::NewL(EPriorityHigh); + iHeartbeat->Start(ETwelveOClock, this); // 12 1/12th intervals + SendTimeUpdate(); + } + +CTimeManager::~CTimeManager() + { + delete iHeartbeat; + } +